Addressed round of testing feedback.

This commit is contained in:
Sam 2020-09-13 00:32:50 -05:00
parent 18c2b850d3
commit de45784596
16 changed files with 103 additions and 49 deletions

View File

@ -182,6 +182,7 @@ https://account.veloren.net."#,
"hud.chat.pvp_melee_kill_msg": "[{attacker}] defeated [{victim}]",
"hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]",
"hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]",
"hud.chat.pvp_explosion_kill_msg": "[{attacker}] used magic to kill [{victim}]",
"hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]",
"hud.chat.npc_ranged_kill_msg": "{attacker} shot [{victim}]",

View File

@ -123,9 +123,9 @@ vec3 spiral_motion(vec3 line, float radius, float time_function) {
vec3 axis3 = perp_axis2(line, axis2);
return line * time_function + vec3(
radius * cos(10 * time_function) * axis2.x + radius * sin(10 * time_function) * axis3.x,
radius * cos(10 * time_function) * axis2.y + radius * sin(10 * time_function) * axis3.y,
radius * cos(10 * time_function) * axis2.z + radius * sin(10 * time_function) * axis3.z + 1.0);
radius * cos(10 * time_function - inst_time) * axis2.x + radius * sin(10 * time_function - inst_time) * axis3.x,
radius * cos(10 * time_function - inst_time) * axis2.y + radius * sin(10 * time_function - inst_time) * axis3.y,
radius * cos(10 * time_function - inst_time) * axis2.z + radius * sin(10 * time_function - inst_time) * axis3.z + 1.0);
}
void main() {
@ -275,7 +275,7 @@ void main() {
);
} else if (inst_mode == HEALING_BEAM) {
attr = Attr(
spiral_motion(beam_pos2() - inst_pos, 0.3 * (floor(2 * hash(vec4(inst_time)) + 0.5) - 0.5), lifetime / 2),
spiral_motion(beam_pos2() - inst_pos, 0.3 * (floor(2 * hash(vec4(inst_time)) + 0.5) - 0.5), lifetime / 1), // The 1 that lifetime is divided by is the duration of the beam. It is currently hardcoded here due to limitations in passing in variables.
vec3((1.7 - 0.7 * abs(floor(2 * hash(vec4(inst_time)) - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
vec4(vec3(0.3, 0.7 + 0.4 * sin(tick.x * 8 - lifetime * 3), 0.3 + 0.1 * sin (tick.x * 2)), 0.3),
spin_in_axis(vec3(inst_entropy, inst_misc, inst_lifespan), tick.z)

View File

@ -1673,6 +1673,11 @@ impl Client {
alias_of_uid(attacker_uid),
alias_of_uid(victim)
),
KillSource::Player(attacker_uid, KillType::Energy) => format!(
"[{}] used magic to kill [{}]",
alias_of_uid(attacker_uid),
alias_of_uid(victim)
),
KillSource::NonPlayer(attacker_name, KillType::Melee) => {
format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
},
@ -1682,6 +1687,11 @@ impl Client {
KillSource::NonPlayer(attacker_name, KillType::Explosion) => {
format!("{} blew up [{}]", attacker_name, alias_of_uid(victim))
},
KillSource::NonPlayer(attacker_name, KillType::Energy) => format!(
"{} used magic to kill [{}]",
attacker_name,
alias_of_uid(victim)
),
KillSource::Environment(environment) => {
format!("[{}] died in {}", alias_of_uid(victim), environment)
},
@ -1704,6 +1714,9 @@ impl Client {
KillSource::Player(attacker_uid, KillType::Explosion) => message
.replace("{attacker}", &alias_of_uid(attacker_uid))
.replace("{victim}", &alias_of_uid(victim)),
KillSource::Player(attacker_uid, KillType::Energy) => message
.replace("{attacker}", &alias_of_uid(attacker_uid))
.replace("{victim}", &alias_of_uid(victim)),
KillSource::NonPlayer(attacker_name, KillType::Melee) => message
.replace("{attacker}", attacker_name)
.replace("{victim}", &alias_of_uid(victim)),
@ -1713,6 +1726,9 @@ impl Client {
KillSource::NonPlayer(attacker_name, KillType::Explosion) => message
.replace("{attacker}", attacker_name)
.replace("{victim}", &alias_of_uid(victim)),
KillSource::NonPlayer(attacker_name, KillType::Energy) => message
.replace("{attacker}", attacker_name)
.replace("{victim}", &alias_of_uid(victim)),
KillSource::Environment(environment) => message
.replace("{name}", &alias_of_uid(victim))
.replace("{environment}", environment),

View File

@ -50,6 +50,7 @@ pub enum KillType {
Melee,
Projectile,
Explosion,
Energy,
// Projectile(String), TODO: add projectile name when available
}

View File

@ -40,11 +40,6 @@ impl Damage {
if (damage_reduction - 1.0).abs() > f32::EPSILON {
self.healthchange += critdamage;
}
// Min damage
if (damage_reduction - 1.0).abs() > f32::EPSILON && self.healthchange > -10.0 {
self.healthchange = -10.0;
}
},
DamageSource::Projectile => {
// Critical hit
@ -58,11 +53,6 @@ impl Damage {
// Armor
let damage_reduction = loadout.get_damage_reduction();
self.healthchange *= 1.0 - damage_reduction;
// Min damage
if (damage_reduction - 1.0).abs() > f32::EPSILON && self.healthchange > -10.0 {
self.healthchange = -10.0;
}
},
DamageSource::Explosion => {
// Block
@ -72,31 +62,16 @@ impl Damage {
// Armor
let damage_reduction = loadout.get_damage_reduction();
self.healthchange *= 1.0 - damage_reduction;
// Min damage
if (damage_reduction - 1.0).abs() > f32::EPSILON && self.healthchange > -10.0 {
self.healthchange = -10.0;
}
},
DamageSource::Shockwave => {
// Armor
let damage_reduction = loadout.get_damage_reduction();
self.healthchange *= 1.0 - damage_reduction;
// Min damage
if (damage_reduction - 1.0).abs() > f32::EPSILON && self.healthchange > -10.0 {
self.healthchange = -10.0;
}
},
DamageSource::Energy => {
// Armor
let damage_reduction = loadout.get_damage_reduction();
self.healthchange *= 1.0 - damage_reduction;
// Min damage
if (damage_reduction - 1.0).abs() > f32::EPSILON && self.healthchange > -10.0 {
self.healthchange = -10.0;
}
},
_ => {},
}

View File

@ -306,7 +306,7 @@ impl Tool {
energy_cost: 0,
buildup_duration: Duration::from_millis(250),
recover_duration: Duration::from_millis(250),
beam_duration: Duration::from_secs(2),
beam_duration: Duration::from_secs(1),
base_hps: (60.0 * self.base_power()) as u32,
base_dps: (40.0 * self.base_power()) as u32,
tick_rate: 2.0,

View File

@ -19,6 +19,7 @@ pub enum HealthSource {
Attack { by: Uid }, // TODO: Implement weapon
Projectile { owner: Option<Uid> },
Explosion { owner: Option<Uid> },
Energy { owner: Option<Uid> },
Suicide,
World,
Revive,

View File

@ -498,7 +498,9 @@ impl<'a> System<'a> for Sys {
// Only if the attack was recent
if my_stats.health.last_change.0 < 3.0 {
if let comp::HealthSource::Attack { by }
| comp::HealthSource::Projectile { owner: Some(by) } =
| comp::HealthSource::Projectile { owner: Some(by) }
| comp::HealthSource::Energy { owner: Some(by) }
| comp::HealthSource::Explosion { owner: Some(by) } =
my_stats.health.last_change.1.cause
{
if !agent.activity.is_attack() {

View File

@ -190,7 +190,11 @@ impl<'a> System<'a> for Sys {
}
if damage.healthchange != 0.0 {
let cause = if is_heal { HealthSource::Healing { by: Some(*uid) } } else { HealthSource::Attack { by: *uid } };
let cause = if is_heal {
HealthSource::Healing { by: beam.owner }
} else {
HealthSource::Energy { owner: beam.owner }
};
server_emitter.emit(ServerEvent::Damage {
uid: *uid_b,
change: HealthChange {
@ -203,9 +207,7 @@ impl<'a> System<'a> for Sys {
uid: beam.owner.unwrap_or(*uid),
change: HealthChange {
amount: (-damage.healthchange * beam.lifesteal_eff) as i32,
cause: HealthSource::Attack {
by: beam.owner.unwrap_or(*uid),
},
cause: HealthSource::Healing { by: beam.owner },
},
});
}

View File

@ -148,7 +148,11 @@ impl<'a> System<'a> for Sys {
}
if damage.healthchange != 0.0 {
let cause = if is_heal { HealthSource::Healing { by: Some(*uid) } } else { HealthSource::Attack { by: *uid } };
let cause = if is_heal {
HealthSource::Healing { by: Some(*uid) }
} else {
HealthSource::Attack { by: *uid }
};
server_emitter.emit(ServerEvent::Damage {
uid: *uid_b,
change: HealthChange {

View File

@ -1,6 +1,6 @@
use crate::{
comp::{
Collider, Gravity, Group, Mass, Mounting, Ori, PhysicsState, Pos, Projectile, Scale,
Beam, Collider, Gravity, Group, Mass, Mounting, Ori, PhysicsState, Pos, Projectile, Scale,
Sticky, Vel,
},
event::{EventBus, ServerEvent},
@ -70,6 +70,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Mounting>,
ReadStorage<'a, Group>,
ReadStorage<'a, Projectile>,
ReadStorage<'a, Beam>,
);
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
@ -96,6 +97,7 @@ impl<'a> System<'a> for Sys {
mountings,
groups,
projectiles,
beams,
): Self::SystemData,
) {
let start_time = std::time::Instant::now();
@ -133,7 +135,7 @@ impl<'a> System<'a> for Sys {
// it means the step needs to take into account the speeds of both
// entities.
span!(guard, "Apply pushback");
for (entity, pos, scale, mass, collider, _, _, physics, projectile) in (
for (entity, pos, scale, mass, collider, _, _, physics, projectile, _) in (
&entities,
&positions,
scales.maybe(),
@ -145,10 +147,13 @@ impl<'a> System<'a> for Sys {
// TODO: if we need to avoid collisions for other things consider moving whether it
// should interact into the collider component or into a separate component
projectiles.maybe(),
beams.maybe(),
)
.join()
.filter(|(_, _, _, _, _, _, sticky, physics, _)| {
sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground)
.filter(|(_, _, _, _, _, _, sticky, physics, _, beam)| {
sticky.is_none()
|| (physics.on_wall.is_none() && !physics.on_ground)
|| beam.is_none()
})
{
let scale = scale.map(|s| s.0).unwrap_or(1.0);
@ -177,6 +182,7 @@ impl<'a> System<'a> for Sys {
collider_other,
_,
group_b,
_,
) in (
&entities,
&uids,
@ -186,8 +192,10 @@ impl<'a> System<'a> for Sys {
colliders.maybe(),
!&mountings,
groups.maybe(),
beams.maybe(),
)
.join()
.filter(|(_, _, _, _, _, _, _, _, beam)| beam.is_none())
{
if entity == entity_other || (ignore_group.is_some() && ignore_group == group_b) {
continue;

View File

@ -138,10 +138,33 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
KillSource::NonPlayer("<?>".to_string(), KillType::Explosion)
}
},
HealthSource::Energy { owner: Some(by) } => {
// Get energy owner entity
if let Some(char_entity) = state.ecs().entity_from_uid(by.into()) {
// Check if attacker is another player or entity with stats (npc)
if state
.ecs()
.read_storage::<Player>()
.get(char_entity)
.is_some()
{
KillSource::Player(by, KillType::Energy)
} else if let Some(stats) =
state.ecs().read_storage::<Stats>().get(char_entity)
{
KillSource::NonPlayer(stats.name.clone(), KillType::Energy)
} else {
KillSource::NonPlayer("<?>".to_string(), KillType::Energy)
}
} else {
KillSource::NonPlayer("<?>".to_string(), KillType::Energy)
}
},
HealthSource::World => KillSource::FallDamage,
HealthSource::Suicide => KillSource::Suicide,
HealthSource::Projectile { owner: None }
| HealthSource::Explosion { owner: None }
| HealthSource::Energy { owner: None }
| HealthSource::Revive
| HealthSource::Command
| HealthSource::LevelUp
@ -158,8 +181,10 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
// Give EXP to the killer if entity had stats
(|| {
let mut stats = state.ecs().write_storage::<Stats>();
let by = if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
cause
let by = if let HealthSource::Attack { by }
| HealthSource::Projectile { owner: Some(by) }
| HealthSource::Energy { owner: Some(by) }
| HealthSource::Explosion { owner: Some(by) } = cause
{
by
} else {
@ -534,7 +559,11 @@ pub fn handle_explosion(
}
if damage.healthchange != 0.0 {
let cause = if is_heal { HealthSource::Healing { by: owner } } else { HealthSource::Explosion { owner } };
let cause = if is_heal {
HealthSource::Healing { by: owner }
} else {
HealthSource::Explosion { owner }
};
stats_b.health.change_by(HealthChange {
amount: damage.healthchange as i32,
cause,

View File

@ -72,7 +72,11 @@ impl<'a> System<'a> for Sys {
// (maybe health changes could be sent to the client as a list
// of events)
if match health.last_change.1.cause {
HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } => {
HealthSource::Attack { by }
| HealthSource::Projectile { owner: Some(by) }
| HealthSource::Energy { owner: Some(by) }
| HealthSource::Explosion { owner: Some(by) }
| HealthSource::Healing { by: Some(by) } => {
let by_me = my_uid.map_or(false, |&uid| by == uid);
// If the attack was by me also reset this timer
if by_me {

View File

@ -369,6 +369,10 @@ impl<'a> Widget for Chat<'a> {
.localized_strings
.get("hud.chat.pvp_explosion_kill_msg")
.to_string(),
KillSource::Player(_, KillType::Energy) => self
.localized_strings
.get("hud.chat.pvp_energy_kill_msg")
.to_string(),
KillSource::NonPlayer(_, KillType::Melee) => self
.localized_strings
.get("hud.chat.npc_melee_kill_msg")
@ -381,6 +385,10 @@ impl<'a> Widget for Chat<'a> {
.localized_strings
.get("hud.chat.npc_explosion_kill_msg")
.to_string(),
KillSource::NonPlayer(_, KillType::Energy) => self
.localized_strings
.get("hud.chat.npc_energy_kill_msg")
.to_string(),
KillSource::Environment(_) => self
.localized_strings
.get("hud.chat.environmental_kill_msg")

View File

@ -1257,14 +1257,14 @@ impl Hud {
let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - timer) * 0.25) + 0.2;
if hp_damage < 10 {
// Damage and heal below 10/10 are shown as decimals
Text::new(&format!("{}", hp_damage as f32 / 10.0))
Text::new(&format!("{}", hp_damage.abs() as f32 / 10.0))
.font_size(font_size)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
.x_y(0.0, y - 3.0)
.position_ingame(ingame_pos)
.set(sct_bg_id, ui_widgets);
Text::new(&format!("{}", hp_damage as f32 / 10.0))
Text::new(&format!("{}", hp_damage.abs() as f32 / 10.0))
.font_size(font_size)
.font_id(self.fonts.cyri.conrod_id)
.x_y(0.0, y)

View File

@ -352,13 +352,16 @@ impl ParticleMgr {
{
if let CharacterState::BasicBeam(b) = character_state {
let particle_ori = b.particle_ori.unwrap_or(*ori.vec());
for _ in 0..self.scheduler.heartbeats(Duration::from_millis(5)) {
for i in 0..self.scheduler.heartbeats(Duration::from_millis(1)) {
if b.buildup_duration == Duration::default() {
self.particles.push(Particle::new_beam(
b.beam_duration,
time,
time + (i as f64) / 1000.0,
ParticleMode::HealingBeam,
pos.0,
pos.0
+ (i as f32 / b.beam_duration.as_millis() as f32)
* particle_ori
* b.range,
pos.0 + particle_ori * b.range,
));
}