saumwacht-godot/scripts/combat/movement_component.gd
Martin Stickelbroeck c2b447610c Baseline: Saumwacht 0.15.0 (Phase 20A) vor dem Umbau zu Champions of Luneraria
Unveränderter Ausgangsstand inklusive Masterprompt und Konzeptbildern
unter assets/. .godot/ und docs/screenshots/ bleiben laut .gitignore
unversioniert; letztere sind unter ../backups gesichert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 20:00:36 +02:00

37 lines
1.6 KiB
GDScript

extends RefCounted
## Ground movement with lightweight separation, without navigation dependencies.
func step(unit, combatants: Array, delta: float, lane_center: float) -> void:
var heading = Vector3.ZERO
var travel_limit = INF
if is_instance_valid(unit.target) and unit.target.alive:
var offset: Vector3 = unit.target.position - unit.position
offset.y = 0.0
var gap = offset.length()
if gap > float(unit.data.attack_range):
heading = offset.normalized()
travel_limit = maxf(0.0, gap - float(unit.data.attack_range) + 0.02)
elif unit.is_attacker:
heading = Vector3.BACK
var separation = Vector3.ZERO
for other in combatants:
if other == unit or not other.alive or other.team_id != unit.team_id:
continue
var offset: Vector3 = unit.position - other.position
offset.y = 0.0
var distance = offset.length()
# Space allies according to the visible stone bodies. Opponents can still
# enter the shortest melee range (1.0 m); separation must not prevent hits.
var spacing: float = 1.30 if other.is_attacker == unit.is_attacker else .90
if distance < spacing:
if distance < 0.0001:
offset = Vector3.RIGHT if unit.uid < other.uid else Vector3.LEFT
distance = 0.001
separation += offset.normalized() * (spacing - distance) * 2.0
var displacement = heading * minf(float(unit.data.speed) * unit.movement_factor() * delta, travel_limit)
displacement += separation.limit_length(0.9) * delta
unit.position += displacement
unit.position.x = clampf(unit.position.x, lane_center - 5.6, lane_center + 5.6)
unit.position.z = clampf(unit.position.z, -20.0, 16.1)
if heading.length_squared() > 0.001:
unit.facing = atan2(heading.x, heading.z)