package game Tower :: struct { position: Vec2, kind: Tower_Kind, cooldown: f32, } Tower_Kind :: enum { Archer, } Tower_Archetype :: struct { kind: Tower_Kind, range: f32, damage: int, fire_rate: f32, cost: int, } TOWER_ARCHETYPES: [Tower_Kind]Tower_Archetype = { .Archer = {kind = .Archer, range = 95, damage = 12, fire_rate = 0.45, cost = TOWER_COST}, } get_archetype :: proc(kind: Tower_Kind) -> Tower_Archetype { return TOWER_ARCHETYPES[kind] } try_place_tower :: proc(world: ^World, gx, gy: int, kind: Tower_Kind) -> bool { arch := get_archetype(kind) if !can_build_at(&world.world_map, gx, gy) do return false if world.gold < TOWER_COST do return false pos := grid_to_center(gx, gy) for t in world.towers { if distance(t.position, pos) < 1 do return false } world.gold -= arch.cost append(&world.towers, Tower{position = pos, kind = kind, cooldown = 0}) return true } find_target :: proc(tower: Tower, world: ^World) -> ^Enemy { arch := get_archetype(tower.kind) best: ^Enemy = nil best_dist: f32 = 999999 for i in 0 ..< MAX_ENEMIES { e := &world.enemies[i] if !e.active do continue d := distance(tower.position, e.position) if d <= arch.range && d < best_dist { best = e best_dist = d } } return best } update_towers :: proc(world: ^World, dt: f32) { for i in 0 ..< len(world.towers) { t := &world.towers[i] t.cooldown -= dt if t.cooldown > 0 do continue target := find_target(t^, world) if target == nil do continue arch := get_archetype(t.kind) target.health -= arch.damage t.cooldown = arch.fire_rate if target.health <= 0 { target.active = false push_event(world, .Enemy_Killed, gold_reward = 5) } } }