Files
aetherbound-guild/runtime/p10_2/motion_presenter.gd
T

185 lines
6.0 KiB
GDScript

class_name P102MotionPresenter
extends "res://p10_1/motion_presenter.gd"
const FOGJAW_ID := "EN-R2-10"
var drownseed_state := ""
var drownseed_target := ""
var drownseed_started := -100.0
var medic_state := ""
var medic_target := ""
var medic_started := -100.0
var fogjaw_state := ""
var fogjaw_started := -100.0
var center_guard_state := ""
func reset(initial_order: Array, safe_index: int) -> void:
super.reset(initial_order, safe_index)
drownseed_state = ""
drownseed_target = ""
drownseed_started = -100.0
medic_state = ""
medic_target = ""
medic_started = -100.0
fogjaw_state = ""
fogjaw_started = -100.0
center_guard_state = ""
func consume(event: Dictionary, now: float) -> Array:
var kind := String(event.get("kind", ""))
var source_id := String(event.get("source_id", ""))
var target_id := String(event.get("target_id", ""))
var payload: Dictionary = Dictionary(event.get("payload", {})).duplicate(true)
var normalized := _normalized_event(event, payload)
if not normalized.is_empty():
super.consume(normalized, now)
match kind:
"drownseed_placed":
drownseed_state = "countdown"
drownseed_target = actor_order[0] if not actor_order.is_empty() else ""
drownseed_started = now
_set_enemy_action(source_id, "telegraph", now, ACTION_DURATION)
"drownseed_evaded":
drownseed_state = "evaded"
drownseed_started = now
_set_actor_action(drownseed_target, "resist", now, TIDE_DURATION)
"drownseed_burst":
drownseed_state = "burst"
drownseed_started = now
_set_actor_action(drownseed_target, "hit", now, HIT_DURATION)
_add_trauma(now, 0.62)
"mire_medic_heal":
medic_state = "healing"
medic_target = target_id
medic_started = now
_set_enemy_action(source_id, "telegraph", now, ACTION_DURATION)
_set_enemy_action(target_id, "telegraph", now, ACTION_DURATION)
"source_interrupted":
medic_state = "interrupted"
medic_started = now
_set_enemy_action(target_id, "hit", now, HIT_DURATION)
"enemy_sustain_resolved":
medic_state = "sustained"
medic_started = now
"fogjaw_hidden":
fogjaw_state = "hidden"
fogjaw_started = now
_add_visible_enemy(source_id)
"fogjaw_center_attack":
fogjaw_state = "revealed"
fogjaw_started = now
_set_enemy_action(source_id, "attack", now, ACTION_DURATION)
"center_guarded", "center_exposed":
center_guard_state = "guarded" if kind == "center_guarded" else "exposed"
var center_actor := _center_actor()
_set_actor_action(center_actor, "resist" if kind == "center_guarded" else "hit", now, HIT_DURATION)
if kind == "center_exposed":
_add_trauma(now, 0.54)
"prepared_response_succeeded":
for actor_id in actor_order:
_set_actor_action(String(actor_id), "resist", now, HIT_DURATION)
prune(now)
return actor_order.duplicate()
func enemy_visual(enemy_id: String, now: float, reduced_motion: bool, low_power: bool) -> Dictionary:
var visual: Dictionary = super.enemy_visual(enemy_id, now, reduced_motion, low_power)
if enemy_id != FOGJAW_ID:
return visual
if fogjaw_state == "hidden":
visual.alpha = 0.24
visual.scale = Vector2(0.88, 0.88)
visual.state = "telegraph"
elif fogjaw_state == "revealed" and now - fogjaw_started < 1.1:
var pulse := sin(clampf((now - fogjaw_started) / 1.1, 0.0, 1.0) * PI)
visual.alpha = 1.0
visual.scale = Vector2.ONE * (1.0 + pulse * (0.04 if reduced_motion else 0.16))
return visual
func mechanic_effects(now: float) -> Dictionary:
return {
"drownseed": {
"state": drownseed_state,
"target_id": drownseed_target,
"age": maxf(0.0, now - drownseed_started),
},
"medic": {
"state": medic_state,
"target_id": medic_target,
"age": maxf(0.0, now - medic_started),
},
"fogjaw": {
"state": fogjaw_state,
"age": maxf(0.0, now - fogjaw_started),
},
"center": {"state": center_guard_state},
}
func _normalized_event(event: Dictionary, payload: Dictionary) -> Dictionary:
var kind := String(event.get("kind", ""))
var source_id := String(event.get("source_id", ""))
var target_id := String(event.get("target_id", ""))
var normalized := event.duplicate(true)
match kind:
"battle_started", "tide_shift_warning", "battle_terminal":
_normalize_payload(normalized, payload)
return normalized
"wave_entered":
normalized["enemy_ids"] = [source_id]
return normalized
"rear_pull":
normalized["kind"] = "pull_resisted" if bool(payload.get("resisted", false)) else "pull_committed"
normalized["enemy_id"] = source_id
normalized["target_id"] = String(actor_order[-1]) if not actor_order.is_empty() else ""
if normalized.kind == "pull_committed":
var reordered := actor_order.duplicate()
if reordered.size() > 1:
reordered.push_front(reordered.pop_back())
normalized["order_after"] = reordered
return normalized
"healing_denial_attached":
normalized["enemy_id"] = source_id
normalized["target_id"] = String(actor_order[-1]) if not actor_order.is_empty() else ""
return normalized
"indexed_mud_marked":
normalized["kind"] = "indexed_bank_marked"
normalized["position_index"] = current_safe_index
return normalized
"tide_shifted":
normalized["kind"] = "tide_followed" if bool(payload.get("followed", false)) else "tide_shifted_while_holding"
normalized["safe_index"] = int(payload.get("safe_index", current_safe_index))
normalized["wet_targets"] = [] if bool(payload.get("followed", false)) else actor_order.duplicate()
return normalized
"allied_basic":
normalized["actor_id"] = source_id
return normalized
"authoritative_damage":
_normalize_payload(normalized, payload)
return normalized
"fallen":
normalized["kind"] = "recruit_fallen"
normalized["recruit_id"] = target_id
return normalized
return {}
func _normalize_payload(event: Dictionary, payload: Dictionary) -> void:
for key in payload:
event[key] = payload[key]
func _add_visible_enemy(enemy_id: String) -> void:
if not enemy_id.is_empty() and enemy_id not in visible_enemy_ids:
visible_enemy_ids.append(enemy_id)
func _center_actor() -> String:
if actor_order.is_empty():
return ""
return String(actor_order[actor_order.size() / 2])