package game Projectile :: struct { active: bool, position: Vec2, target_slot: int, damage: int, speed: f32, } acquire_projectile :: proc(world: ^World) -> ^Projectile { for i in 0 ..< MAX_PROJECTILES { if !world.projectiles[i].active { return &world.projectiles[i] } } return nil } enemy_still_on_map :: proc(world: ^World, slot: int) -> (^Enemy, bool) { if slot < 0 || slot >= MAX_ENEMIES do return nil, false e := &world.enemies[slot] if !e.active do return nil, false if len(world.path) == 0 do return nil, false if e.path_index >= len(world.path) do return nil, false return e, true } spawn_projectile :: proc(world: ^World, from: Vec2, target_slot: int, damage: int) { p := acquire_projectile(world) if p == nil do return p^ = Projectile { active = true, position = from, target_slot = target_slot, damage = damage, speed = PROJECTILE_SPEED, } } update_projectiles :: proc(world: ^World, dt: f32) { for i in 0 ..< MAX_PROJECTILES { p := &world.projectiles[i] if !p.active do continue target, ok := enemy_still_on_map(world, p.target_slot) if !ok { p.active = false continue } move_toward(&p.position, target.position, p.speed, dt) if distance(p.position, target.position) <= PROJECTILE_HIT_RADIUS { target.health -= p.damage p.active = false if target.health <= 0 { target.active = false push_event(world, .Enemy_Killed, gold_reward = 5) } } } }