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;
         }