Damaging Enemies

The last facet of reacting to impacts is to cause damage to targets. This is a generic system that can travel from project to project. We don’t want to make assumptions, so we use signals.

There’s a single damaged signal on the ModularWeapons.gd that any health and damage related system you use for your game can use.

signal damaged(target, amount)

Emitting the new signal on impact

We can emit this signal along with the damage in the base ProjectileEmitter.gd whenever there’s a collision.

func _on_projectile_collided(target: Node, hit_location: Vector2) -> void:
    weapons_system.emit_signal("damaged", target, damage_per_collision)
    for event in weapons_system.projectile_impact_events:
        event.trigger(hit_location, spawned_objects, weapons_system, false)

Adding damage to the explosion

For the ExplosionEvent.gd, we trigger the explosion, wait a single frame for the physics server to update, then grab any overlapping bodies and calculate the damage caused to them based on their distance from the explosion epicenter.

func _do_trigger(_spawn_location: Vector2, _spawn_parent: Node, _weapons_system, _missed: bool) -> void:
    # ...

    explosion.trigger()

    yield(explosion.get_tree(), "physics_frame")

    var bodies: Array = explosion.area.get_overlapping_bodies()
    for body in bodies:
        var distance: float = body.global_position.distance_to(explosion.global_position)

        var damage := explosion_damage
        if damage_scales_with_distances:
            damage *= clamp(1.0 - distance / explosion_radius, 0, 1)

        _weapons_system.emit_signal("damaged", body, damage)