From 9c2ce83430c7ceafc477c5fcc1353d652dc5aba0 Mon Sep 17 00:00:00 2001 From: Snowram <robin.gilh@gmail.com> Date: Sat, 18 Sep 2021 16:16:20 +0200 Subject: [PATCH] Set projectile offsets in states instead of globally --- common/src/event.rs | 1 + common/src/states/basic_ranged.rs | 35 ++++++++++++++++++++++- common/src/states/charged_ranged.rs | 35 ++++++++++++++++++++++- common/src/states/repeater_ranged.rs | 35 ++++++++++++++++++++++- server/src/events/entity_creation.rs | 19 ++---------- server/src/events/mod.rs | 5 +++- server/src/sys/agent.rs | 17 ++++++++--- server/src/sys/object.rs | 1 + server/src/sys/wiring/dispatch_actions.rs | 3 +- 9 files changed, 125 insertions(+), 26 deletions(-) diff --git a/common/src/event.rs b/common/src/event.rs index 3c243a4eb1..cdc068cba3 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -66,6 +66,7 @@ pub enum ServerEvent { Respawn(EcsEntity), Shoot { entity: EcsEntity, + pos: Pos, dir: Dir, body: comp::Body, light: Option<comp::LightEmitter>, diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index cf2bb06523..3e223fd51f 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{Body, CharacterState, LightEmitter, ProjectileConstructor, StateUpdate}, + comp::{Body, CharacterState, LightEmitter, Pos, ProjectileConstructor, StateUpdate}, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -10,6 +10,7 @@ use crate::{ use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use std::time::Duration; +use vek::*; /// Separated out to condense update portions of character state #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] @@ -83,6 +84,9 @@ impl CharacterBehavior for Data { ); // Shoots all projectiles simultaneously for i in 0..self.static_data.num_projectiles { + // Gets offsets + let body_offsets = projectile_offsets(data.body, update.ori.look_vec()); + let pos = Pos(data.pos.0 + body_offsets); // Adds a slight spread to the projectiles. First projectile has no spread, // and spread increases linearly with number of projectiles created. let dir = Dir::from_unnormalized(data.inputs.look_dir.map(|x| { @@ -95,6 +99,7 @@ impl CharacterBehavior for Data { // Tells server to create and shoot the projectile update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, + pos, dir, body: self.static_data.projectile_body, projectile: projectile.clone(), @@ -141,3 +146,31 @@ impl CharacterBehavior for Data { fn reset_state(data: &Data, join: &JoinData, update: &mut StateUpdate) { handle_input(join, update, data.static_data.ability_info.input); } + +fn height_offset(body: &Body) -> f32 { + match body { + Body::Golem(_) => body.height() * 0.4, + _ => body.eye_height(), + } +} + +pub fn projectile_offsets(body: &Body, ori: Vec3<f32>) -> Vec3<f32> { + let dim = body.dimensions(); + // The width (shoulder to shoulder) and length (nose to tail) + let (width, length) = (dim.x, dim.y); + let body_radius = if length > width { + // Dachshund-like + body.max_radius() + } else { + // Cyclops-like + body.min_radius() + }; + + let body_offsets_z = height_offset(body); + + Vec3::new( + body_radius * ori.x * 1.1, + body_radius * ori.y * 1.1, + body_offsets_z, + ) +} diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 9ef1c430ef..60ee545ccd 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ projectile::ProjectileConstructor, Body, CharacterState, EnergyChange, EnergySource, - LightEmitter, StateUpdate, + LightEmitter, Pos, StateUpdate, }, event::ServerEvent, states::{ @@ -11,6 +11,7 @@ use crate::{ }; use serde::{Deserialize, Serialize}; use std::time::Duration; +use vek::*; /// Separated out to condense update portions of character state #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -110,6 +111,9 @@ impl CharacterBehavior for Data { let (crit_chance, crit_mult) = get_crit_data(data, self.static_data.ability_info); let buff_strength = get_buff_strength(data, self.static_data.ability_info); + // Gets offsets + let body_offsets = projectile_offsets(data.body, update.ori.look_vec()); + let pos = Pos(data.pos.0 + body_offsets); let projectile = arrow.create_projectile( Some(*data.uid), crit_chance, @@ -118,6 +122,7 @@ impl CharacterBehavior for Data { ); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, + pos, dir: data.inputs.look_dir, body: self.static_data.projectile_body, projectile, @@ -187,3 +192,31 @@ impl CharacterBehavior for Data { update } } + +fn height_offset(body: &Body) -> f32 { + match body { + Body::Golem(_) => body.height() * 0.4, + _ => body.eye_height(), + } +} + +pub fn projectile_offsets(body: &Body, ori: Vec3<f32>) -> Vec3<f32> { + let dim = body.dimensions(); + // The width (shoulder to shoulder) and length (nose to tail) + let (width, length) = (dim.x, dim.y); + let body_radius = if length > width { + // Dachshund-like + body.max_radius() + } else { + // Cyclops-like + body.min_radius() + }; + + let body_offsets_z = height_offset(body); + + Vec3::new( + body_radius * ori.x * 1.1, + body_radius * ori.y * 1.1, + body_offsets_z, + ) +} diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index 07471bcd25..5b443ca399 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -1,6 +1,6 @@ use crate::{ comp::{ - Body, CharacterState, EnergyChange, EnergySource, LightEmitter, ProjectileConstructor, + Body, CharacterState, EnergyChange, EnergySource, LightEmitter, Pos, ProjectileConstructor, StateUpdate, }, event::ServerEvent, @@ -11,6 +11,7 @@ use crate::{ }; use serde::{Deserialize, Serialize}; use std::time::Duration; +use vek::*; #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] /// Separated out to condense update portions of character state @@ -91,6 +92,9 @@ impl CharacterBehavior for Data { let (crit_chance, crit_mult) = get_crit_data(data, self.static_data.ability_info); let buff_strength = get_buff_strength(data, self.static_data.ability_info); + // Gets offsets + let body_offsets = projectile_offsets(data.body, update.ori.look_vec()); + let pos = Pos(data.pos.0 + body_offsets); let projectile = self.static_data.projectile.create_projectile( Some(*data.uid), crit_chance, @@ -99,6 +103,7 @@ impl CharacterBehavior for Data { ); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, + pos, dir: data.inputs.look_dir, body: self.static_data.projectile_body, projectile, @@ -164,3 +169,31 @@ impl CharacterBehavior for Data { update } } + +fn height_offset(body: &Body) -> f32 { + match body { + Body::Golem(_) => body.height() * 0.4, + _ => body.eye_height(), + } +} + +pub fn projectile_offsets(body: &Body, ori: Vec3<f32>) -> Vec3<f32> { + let dim = body.dimensions(); + // The width (shoulder to shoulder) and length (nose to tail) + let (width, length) = (dim.x, dim.y); + let body_radius = if length > width { + // Dachshund-like + body.max_radius() + } else { + // Cyclops-like + body.min_radius() + }; + + let body_offsets_z = height_offset(body); + + Vec3::new( + body_radius * ori.x * 1.1, + body_radius * ori.y * 1.1, + body_offsets_z, + ) +} diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index 67ecf150c3..43294d0dff 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -173,6 +173,7 @@ pub fn handle_create_ship( pub fn handle_shoot( server: &mut Server, entity: EcsEntity, + pos: Pos, dir: Dir, body: Body, light: Option<LightEmitter>, @@ -182,11 +183,7 @@ pub fn handle_shoot( ) { let state = server.state_mut(); - let mut pos = if let Some(pos) = state.ecs().read_storage::<Pos>().get(entity) { - pos.0 - } else { - return; - }; + let pos = pos.0; let vel = *dir * speed + state @@ -201,18 +198,6 @@ pub fn handle_shoot( .write_resource::<Vec<Outcome>>() .push(Outcome::ProjectileShot { pos, body, vel }); - let eye_height = - state - .ecs() - .read_storage::<comp::Body>() - .get(entity) - .map_or(0.0, |b| match b { - comp::Body::Golem(_) => b.height() * 0.45, - _ => b.eye_height(), - }); - - pos.z += eye_height; - let mut builder = state.create_projectile(Pos(pos), Vel(vel), body, projectile); if let Some(light) = light { builder = builder.with(light) diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index 504f593825..6846333301 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -71,13 +71,16 @@ impl Server { ServerEvent::Bonk { pos, owner, target } => handle_bonk(self, pos, owner, target), ServerEvent::Shoot { entity, + pos, dir, body, light, projectile, speed, object, - } => handle_shoot(self, entity, dir, body, light, projectile, speed, object), + } => handle_shoot( + self, entity, pos, dir, body, light, projectile, speed, object, + ), ServerEvent::Shockwave { properties, pos, diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index bab6cdb37b..37da940657 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -28,7 +28,7 @@ use common::{ path::TraversalConfig, resources::{DeltaTime, Time, TimeOfDay}, rtsim::{Memory, MemoryItem, RtSimEntity, RtSimEvent}, - states::{basic_beam, utils::StageSection}, + states::{basic_beam, basic_ranged, charged_ranged, repeater_ranged, utils::StageSection}, terrain::{Block, TerrainGrid}, time::DayPeriod, trade::{TradeAction, TradePhase, TradeResult}, @@ -1830,7 +1830,10 @@ impl<'a> AgentData<'a> { + charge_factor * c.static_data.scaled_projectile_speed; aim_projectile( projectile_speed, - Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset), + self.pos.0 + + self.body.map_or(Vec3::zero(), |body| { + charged_ranged::projectile_offsets(body, self.ori.look_vec()) + }), Vec3::new( tgt_data.pos.0.x, tgt_data.pos.0.y, @@ -1842,7 +1845,10 @@ impl<'a> AgentData<'a> { let projectile_speed = c.static_data.projectile_speed; aim_projectile( projectile_speed, - Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset), + self.pos.0 + + self.body.map_or(Vec3::zero(), |body| { + basic_ranged::projectile_offsets(body, self.ori.look_vec()) + }), Vec3::new( tgt_data.pos.0.x, tgt_data.pos.0.y, @@ -1854,7 +1860,10 @@ impl<'a> AgentData<'a> { let projectile_speed = c.static_data.projectile_speed; aim_projectile( projectile_speed, - Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset), + self.pos.0 + + self.body.map_or(Vec3::zero(), |body| { + repeater_ranged::projectile_offsets(body, self.ori.look_vec()) + }), Vec3::new( tgt_data.pos.0.x, tgt_data.pos.0.y, diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index dc99af33c6..0daf0a081f 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -115,6 +115,7 @@ impl<'a> System<'a> for Sys { .expect("nonzero vector should normalize"); server_emitter.emit(ServerEvent::Shoot { entity, + pos: *pos, dir, body: Body::Object(object::Body::for_firework(*reagent)), light: Some(LightEmitter { diff --git a/server/src/sys/wiring/dispatch_actions.rs b/server/src/sys/wiring/dispatch_actions.rs index d5ae4dc6ad..ea28c4405a 100644 --- a/server/src/sys/wiring/dispatch_actions.rs +++ b/server/src/sys/wiring/dispatch_actions.rs @@ -13,7 +13,7 @@ use common::{ use common_state::BlockChange; use hashbrown::HashMap; use specs::{join::Join, Entity, Read, Write}; -use vek::Rgb; +use vek::{Rgb, Vec3}; pub fn dispatch_actions(system_data: &mut WiringData) { let WiringData { @@ -113,6 +113,7 @@ fn dispatch_action_spawn_projectile( // NOTE: constr in RFC is about Arrow projectile server_emitter.emit(ServerEvent::Shoot { entity, + pos: Pos(Vec3::zero()), dir: Dir::forward(), body: Body::Object(object::Body::Arrow), projectile: constr.create_projectile(None, 0.0, 1.0, 1.0),