mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improved single-tick projectile wall/entity collision bug
This commit is contained in:
parent
9b812b0d8b
commit
12ea028a3d
@ -32,7 +32,7 @@
|
|||||||
),
|
),
|
||||||
column: (
|
column: (
|
||||||
cold_grass: (0.0, 0.3, 0.1),
|
cold_grass: (0.0, 0.3, 0.1),
|
||||||
warm_grass: (0.3, 0.25, -0.8),
|
warm_grass: (0.5, 0.55, 0.0),
|
||||||
dark_grass: (0.15, 0.4, 0.1),
|
dark_grass: (0.15, 0.4, 0.1),
|
||||||
wet_grass: (0.1, 0.8, 0.2),
|
wet_grass: (0.1, 0.8, 0.2),
|
||||||
cold_stone: (0.4, 0.67, 0.8),
|
cold_stone: (0.4, 0.67, 0.8),
|
||||||
|
@ -126,10 +126,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
// already possible with poorly-defined hitboxes anyway so it's not too
|
// already possible with poorly-defined hitboxes anyway so it's not too
|
||||||
// much of a concern.
|
// much of a concern.
|
||||||
//
|
//
|
||||||
// Actually, the aforementioned case can't happen, but only because wall
|
|
||||||
// collision is checked prior to entity collision in the projectile
|
|
||||||
// code.
|
|
||||||
//
|
|
||||||
// If this situation becomes a problem, this code should be integrated with the
|
// If this situation becomes a problem, this code should be integrated with the
|
||||||
// terrain collision code below, although that's not trivial to do since
|
// terrain collision code below, although that's not trivial to do since
|
||||||
// it means the step needs to take into account the speeds of both
|
// it means the step needs to take into account the speeds of both
|
||||||
|
@ -61,6 +61,81 @@ impl<'a> System<'a> for Sys {
|
|||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
|
// Hit entity
|
||||||
|
for other in physics.touch_entities.iter().copied() {
|
||||||
|
if projectile.owner == Some(other) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for effect in projectile.hit_entity.iter().cloned() {
|
||||||
|
match effect {
|
||||||
|
projectile::Effect::Damage(healthchange) => {
|
||||||
|
let owner_uid = projectile.owner.unwrap();
|
||||||
|
let mut damage = Damage {
|
||||||
|
healthchange: healthchange as f32,
|
||||||
|
source: DamageSource::Projectile,
|
||||||
|
};
|
||||||
|
|
||||||
|
let other_entity = uid_allocator.retrieve_entity_internal(other.into());
|
||||||
|
if let Some(loadout) = other_entity.and_then(|e| loadouts.get(e)) {
|
||||||
|
damage.modify_damage(false, loadout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if other != owner_uid {
|
||||||
|
server_emitter.emit(ServerEvent::Damage {
|
||||||
|
uid: other,
|
||||||
|
change: HealthChange {
|
||||||
|
amount: damage.healthchange as i32,
|
||||||
|
cause: HealthSource::Attack { by: owner_uid },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
projectile::Effect::Knockback(knockback) => {
|
||||||
|
if let Some(entity) =
|
||||||
|
uid_allocator.retrieve_entity_internal(other.into())
|
||||||
|
{
|
||||||
|
local_emitter.emit(LocalEvent::ApplyForce {
|
||||||
|
entity,
|
||||||
|
force: knockback
|
||||||
|
* *Dir::slerp(ori.0, Dir::new(Vec3::unit_z()), 0.5),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
projectile::Effect::RewardEnergy(energy) => {
|
||||||
|
if let Some(energy_mut) = projectile
|
||||||
|
.owner
|
||||||
|
.and_then(|o| uid_allocator.retrieve_entity_internal(o.into()))
|
||||||
|
.and_then(|o| energies.get_mut(o))
|
||||||
|
{
|
||||||
|
energy_mut.change_by(energy as i32, EnergySource::HitEnemy);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
projectile::Effect::Explode { power } => {
|
||||||
|
server_emitter.emit(ServerEvent::Explosion {
|
||||||
|
pos: pos.0,
|
||||||
|
power,
|
||||||
|
owner: projectile.owner,
|
||||||
|
friendly_damage: false,
|
||||||
|
reagent: None,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy {
|
||||||
|
entity,
|
||||||
|
cause: HealthSource::World,
|
||||||
|
}),
|
||||||
|
projectile::Effect::Possess => {
|
||||||
|
if other != projectile.owner.unwrap() {
|
||||||
|
if let Some(owner) = projectile.owner {
|
||||||
|
server_emitter.emit(ServerEvent::Possess(owner, other));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hit something solid
|
// Hit something solid
|
||||||
if physics.on_wall.is_some() || physics.on_ground || physics.on_ceiling {
|
if physics.on_wall.is_some() || physics.on_ground || physics.on_ceiling {
|
||||||
for effect in projectile.hit_solid.drain(..) {
|
for effect in projectile.hit_solid.drain(..) {
|
||||||
@ -81,91 +156,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// Hit entity
|
|
||||||
for other in physics.touch_entities.iter().copied() {
|
|
||||||
if projectile.owner == Some(other) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for effect in projectile.hit_entity.iter().cloned() {
|
if let Some(dir) = velocities
|
||||||
match effect {
|
.get(entity)
|
||||||
projectile::Effect::Damage(healthchange) => {
|
.and_then(|vel| vel.0.try_normalized())
|
||||||
let owner_uid = projectile.owner.unwrap();
|
{
|
||||||
let mut damage = Damage {
|
ori.0 = dir.into();
|
||||||
healthchange: healthchange as f32,
|
|
||||||
source: DamageSource::Projectile,
|
|
||||||
};
|
|
||||||
|
|
||||||
let other_entity =
|
|
||||||
uid_allocator.retrieve_entity_internal(other.into());
|
|
||||||
if let Some(loadout) = other_entity.and_then(|e| loadouts.get(e)) {
|
|
||||||
damage.modify_damage(false, loadout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if other != owner_uid {
|
|
||||||
server_emitter.emit(ServerEvent::Damage {
|
|
||||||
uid: other,
|
|
||||||
change: HealthChange {
|
|
||||||
amount: damage.healthchange as i32,
|
|
||||||
cause: HealthSource::Attack { by: owner_uid },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
projectile::Effect::Knockback(knockback) => {
|
|
||||||
if let Some(entity) =
|
|
||||||
uid_allocator.retrieve_entity_internal(other.into())
|
|
||||||
{
|
|
||||||
local_emitter.emit(LocalEvent::ApplyForce {
|
|
||||||
entity,
|
|
||||||
force: knockback
|
|
||||||
* *Dir::slerp(ori.0, Dir::new(Vec3::unit_z()), 0.5),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
projectile::Effect::RewardEnergy(energy) => {
|
|
||||||
if let Some(energy_mut) = projectile
|
|
||||||
.owner
|
|
||||||
.and_then(|o| uid_allocator.retrieve_entity_internal(o.into()))
|
|
||||||
.and_then(|o| energies.get_mut(o))
|
|
||||||
{
|
|
||||||
energy_mut.change_by(energy as i32, EnergySource::HitEnemy);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
projectile::Effect::Explode { power } => {
|
|
||||||
server_emitter.emit(ServerEvent::Explosion {
|
|
||||||
pos: pos.0,
|
|
||||||
power,
|
|
||||||
owner: projectile.owner,
|
|
||||||
friendly_damage: false,
|
|
||||||
reagent: None,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
projectile::Effect::Vanish => {
|
|
||||||
server_emitter.emit(ServerEvent::Destroy {
|
|
||||||
entity,
|
|
||||||
cause: HealthSource::World,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
projectile::Effect::Possess => {
|
|
||||||
if other != projectile.owner.unwrap() {
|
|
||||||
if let Some(owner) = projectile.owner {
|
|
||||||
server_emitter.emit(ServerEvent::Possess(owner, other));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(dir) = velocities
|
|
||||||
.get(entity)
|
|
||||||
.and_then(|vel| vel.0.try_normalized())
|
|
||||||
{
|
|
||||||
ori.0 = dir.into();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if projectile.time_left == Duration::default() {
|
if projectile.time_left == Duration::default() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user