Add profile-specific attack motion curves

This commit is contained in:
2026-06-18 22:43:46 +09:00
parent 70a34cf262
commit 3cdadf8599
2 changed files with 91 additions and 4 deletions

View File

@@ -2003,8 +2003,9 @@ func _visual_rect_for_unit(unit: Dictionary) -> Rect2:
var action_duration: float = maxf(0.01, float(action_motion.get("duration", UNIT_ATTACK_ANIMATION_DURATION)))
var action_age := float(action_motion.get("age", 0.0))
var action_progress := clampf(action_age / action_duration, 0.0, 1.0)
var lunge_scale := _action_motion_lunge_scale(str(action_motion.get("profile", "slash")))
rect.position += direction * sin(action_progress * PI) * UNIT_ATTACK_LUNGE_DISTANCE * lunge_scale
var profile := str(action_motion.get("profile", "slash"))
var lunge_scale := _action_motion_lunge_scale(profile)
rect.position += direction * _action_motion_lunge_curve(profile, action_progress) * UNIT_ATTACK_LUNGE_DISTANCE * lunge_scale
return rect
@@ -2021,7 +2022,8 @@ func _draw_attack_effects() -> void:
var duration: float = maxf(0.01, float(motion.get("duration", UNIT_ATTACK_ANIMATION_DURATION)))
var age := float(motion.get("age", 0.0))
var progress := clampf(age / duration, 0.0, 1.0)
var peak := sin(progress * PI)
var profile := str(motion.get("profile", "slash"))
var peak := _action_motion_effect_peak(profile, progress)
if peak <= 0.0:
continue
var from_cell: Vector2i = motion.get("from", Vector2i(-1, -1))
@@ -2034,7 +2036,6 @@ func _draw_attack_effects() -> void:
var unit := state.get_unit(str(unit_id))
if not unit.is_empty() and unit.get("team", "") == BattleState.TEAM_ENEMY:
team_color = ENEMY_COLOR
var profile := str(motion.get("profile", "slash"))
var impact_cue := str(motion.get("impact_cue", _action_motion_impact_cue(profile)))
var impact_radius := float(motion.get("impact_radius", _action_motion_impact_radius(profile)))
_draw_action_effect(profile, start, end, progress, peak, team_color)
@@ -3362,6 +3363,51 @@ func _action_motion_lunge_scale(profile: String) -> float:
return 1.0
func _action_motion_lunge_curve(profile: String, progress: float) -> float:
var p := clampf(progress, 0.0, 1.0)
if profile == "arrow":
return sin(p * PI) * 0.32
if profile == "cavalry_charge":
if p < 0.75:
return _action_motion_smoothstep(p / 0.75)
return 1.0 - _action_motion_smoothstep((p - 0.75) / 0.25)
if profile == "infantry_strike":
return sin(p * PI) * (0.72 + 0.28 * (1.0 - p))
if profile == "command_strike" or profile.begins_with("tactic_"):
return sin(p * PI) * 0.30
if profile == "heavy_strike":
var late := _action_motion_smoothstep(clampf((p - 0.18) / 0.72, 0.0, 1.0))
var recovery := 1.0 - _action_motion_smoothstep(clampf((p - 0.72) / 0.28, 0.0, 1.0))
return late * recovery
return sin(p * PI)
func _action_motion_effect_peak(profile: String, progress: float) -> float:
var p := clampf(progress, 0.0, 1.0)
if profile == "arrow":
return pow(1.0 - abs(p - 0.34) / 0.34, 2.0) if p <= 0.68 else 0.0
if profile == "cavalry_charge":
return _action_motion_smoothstep(p) * (1.0 - _action_motion_smoothstep(clampf((p - 0.82) / 0.18, 0.0, 1.0)) * 0.22)
if profile == "infantry_strike":
return sin(p * PI)
if profile == "command_strike":
return 0.42 + 0.58 * sin(p * PI)
if profile == "heavy_strike":
return pow(maxf(0.0, sin(p * PI)), 0.62) * _action_motion_smoothstep(clampf((p - 0.18) / 0.40, 0.0, 1.0))
if profile == "tactic_damage":
return 0.28 + 0.72 * sin(p * PI)
if profile == "tactic_heal":
return 0.36 + 0.64 * sin(p * PI)
if profile == "tactic_support":
return 0.32 + 0.68 * sin(p * PI)
return sin(p * PI)
func _action_motion_smoothstep(value: float) -> float:
var p := clampf(value, 0.0, 1.0)
return p * p * (3.0 - 2.0 * p)
func _action_motion_allows_same_cell(profile: String) -> bool:
return profile.begins_with("tactic_")