diff --git a/bear.gd b/bear.gd index 956246f..62c080d 100644 --- a/bear.gd +++ b/bear.gd @@ -630,7 +630,7 @@ func _try_hit(reach: float) -> bool: return false if _facing().dot(to_bull / dist) < cos(deg_to_rad(DP.f("bear_hit_arc"))): return false - _bull.call(&"take_sword_hit", "mauled") + DamageEvent.deal(_bull, DamageEvent.Cause.MAULED, _bull.global_position, self) _shake(0.55) return true diff --git a/damage_event.gd b/damage_event.gd index 33ea963..8df68f6 100644 --- a/damage_event.gd +++ b/damage_event.gd @@ -37,6 +37,24 @@ static func make(kind: Cause, at: Vector3, src: Node = null) -> DamageEvent: return e +## The single entry point every attacker uses to wound a target: build the typed event and hand it +## to receive_damage(). Falls back to the legacy string call for any target not yet migrated, so a +## caller never has to branch on which contract the victim speaks. `knock_up_v` is the already-shaped +## pop (0 = grounded); callers that scale it by distance compute it before calling. +static func deal(target: Node, kind: Cause, at: Vector3, src: Node = null, knock_up_v: float = 0.0) -> void: + if target == null: + return + if target.has_method(&"receive_damage"): + var event := make(kind, at, src) + event.knock_up = knock_up_v + target.call(&"receive_damage", event) + return + if target.has_method(&"take_sword_hit"): + target.call(&"take_sword_hit", make(kind, at, src).cause_name(), at) + if knock_up_v > 0.0 and target.has_method(&"apply_knock_up"): + target.call(&"apply_knock_up", knock_up_v) + + ## Lower-case name of the cause, for logs and for the bull's existing cause-keyed reactions ## ("gored" / "mauled" / "thrown") during the migration off string causes. func cause_name() -> String: diff --git a/hitbox.gd b/hitbox.gd index bfba987..d415f0c 100644 --- a/hitbox.gd +++ b/hitbox.gd @@ -80,17 +80,8 @@ func _apply_hit(body: Node3D) -> void: return _hit_this_swing[body] = true _did_hit = true - if body.has_method(&"receive_damage"): - var event := DamageEvent.make(DamageEvent.cause_from(damage_cause), body.global_position, self) - if knock_up > 0.0: - event.knock_up = _knock_up_for(body) - body.call(&"receive_damage", event) - else: - body.call(&"take_sword_hit", damage_cause) - if knock_up > 0.0: - var v := _knock_up_for(body) - if v > 0.0: - body.call(&"apply_knock_up", v) + var ku := _knock_up_for(body) if knock_up > 0.0 else 0.0 + DamageEvent.deal(body, DamageEvent.cause_from(damage_cause), body.global_position, self, ku) # Scale the pop by how far the body is from this hitbox's origin (planar). See the export docs. diff --git a/matador.gd b/matador.gd index 6829385..2d1a019 100644 --- a/matador.gd +++ b/matador.gd @@ -955,7 +955,7 @@ func _try_melee_hit(reach: float) -> void: if facing.dot(to_bull / dist) < cos(deg_to_rad(DP.f("mat_stab_arc"))): return _blade_hit_cd = DP.f("mat_stab_cooldown") - _bull.call(&"take_sword_hit", "gored") + DamageEvent.deal(_bull, DamageEvent.Cause.GORED, _bull.global_position, self) func _enter_ragdoll(hit_dir: Vector3, bull_speed: float, up_boost: float = 0.0) -> void: diff --git a/spear_projectile.gd b/spear_projectile.gd index ba0c371..cee78d0 100644 --- a/spear_projectile.gd +++ b/spear_projectile.gd @@ -223,7 +223,7 @@ func _embed(other: Object, contact: Vector3, flight: Vector3) -> void: var pose := Transform3D(_aim_basis(f), contact + f * (_EMBED_DEPTH - _TIP_Z)) var bull := other as Node if bull != null and bull.is_in_group(&"player"): - bull.call(&"take_sword_hit", "thrown", contact) + DamageEvent.deal(bull, DamageEvent.Cause.THROWN, contact, self) if is_instance_valid(_mesh) and is_instance_valid(bull): _mesh.reparent(_spear_anchor(bull), false) _mesh.global_transform = pose