diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index b94533972d..ba49cd70eb 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -3,7 +3,10 @@ use crate::{ Attack, AttackDamage, AttackEffect, CombatEffect, CombatRequirement, Damage, DamageKind, DamageSource, GroupTarget, }, - comp::{beam, Body, CharacterState, EnergyChange, EnergySource, Ori, Pos, StateUpdate}, + comp::{ + beam, body::biped_large, Body, CharacterState, EnergyChange, EnergySource, Ori, Pos, + StateUpdate, + }, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, @@ -158,25 +161,8 @@ impl CharacterBehavior for Data { .prerotated(pitch) }; // Gets offsets - let body_offsets = { - let body_radius = data.body.radius(); - - // TODO: make it public function to use in Agent code - // to help with aim. - let body_offsets_z = match data.body { - Body::BirdLarge(_) => data.body.height() * 0.8, - Body::Golem(_) => { - data.body.height() * 0.9 + data.inputs.look_dir.z * 3.0 - }, - _ => data.body.height() * 0.5, - }; - - Vec3::new( - body_radius * update.ori.look_vec().x * 1.1, - body_radius * update.ori.look_vec().y * 1.1, - body_offsets_z, - ) - }; + let body_offsets = + beam_offsets(data.body, data.inputs.look_dir, update.ori.look_vec()); let pos = Pos(data.pos.0 + body_offsets); // Create beam segment @@ -232,3 +218,25 @@ impl CharacterBehavior for Data { update } } + +fn height_offset(body: &Body, look_dir: Dir) -> f32 { + match body { + Body::BirdLarge(_) => body.height() * 0.8, + Body::Golem(_) => body.height() * 0.9 + look_dir.z * 3.0, + Body::BipedLarge(b) => match b.species { + biped_large::Species::Mindflayer => body.height() * 0.6, + _ => body.height() * 0.5, + }, + _ => body.height() * 0.5, + } +} + +pub fn beam_offsets(body: &Body, look_dir: Dir, ori: Vec3<f32>) -> Vec3<f32> { + let body_radius = body.radius(); + let body_offsets_z = height_offset(body, look_dir); + Vec3::new( + body_radius * ori.x * 1.1, + body_radius * ori.y * 1.1, + body_offsets_z, + ) +} diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index ef1d033b65..ede5d366d7 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::utils::StageSection, + states::{basic_beam, utils::StageSection}, terrain::{Block, TerrainGrid}, time::DayPeriod, trade::{TradeAction, TradePhase, TradeResult}, @@ -1802,6 +1802,8 @@ impl<'a> AgentData<'a> { // And this is quite hard to debug when you don't see it in actual // attack handler. if let Some(dir) = match tactic { + // FIXME: this code make Staff flamethrower aim flamethrower + // like a projectile. Tactic::Bow | Tactic::FixedTurret | Tactic::QuadLowRanged @@ -1891,13 +1893,25 @@ impl<'a> AgentData<'a> { Dir::from_unnormalized(Vec3::new(delta_x, delta_y, -1.0)) }, - _ => Dir::from_unnormalized( - Vec3::new( + _ => { + let aim_from = match self.char_state { + CharacterState::BasicBeam(_) => self.body.map_or(self.pos.0, |body| { + self.pos.0 + + basic_beam::beam_offsets( + body, + controller.inputs.look_dir, + self.ori.look_vec(), + ) + }), + _ => Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset), + }; + let aim_to = Vec3::new( tgt_data.pos.0.x, tgt_data.pos.0.y, tgt_data.pos.0.z + tgt_eye_offset, - ) - Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset), - ), + ); + Dir::from_unnormalized(aim_to - aim_from) + }, } { controller.inputs.look_dir = dir; }