package main import math "core:math" import rand "core:math/rand" import rl "vendor:raylib" EnemyKind :: enum { Grunt, Brute, Scout, } Enemy :: struct { using actor: Actor, touch_dmg: i32, kind: EnemyKind, xp_reward: i32, } make_enemy :: proc(pos: rl.Vector2, kind: EnemyKind) -> Entity { e: Enemy switch kind { case .Grunt: e = Enemy{actor = Actor{hp = 45, max_hp = 45, speed = 55}, touch_dmg = 8, kind = .Grunt, xp_reward = 12} e.base.gfx = {0 = GfxCircle{pos = {}, radius = 11, color = {220, 80, 80, 255}}} case .Brute: e = Enemy{actor = Actor{hp = 140, max_hp = 140, speed = 32}, touch_dmg = 20, kind = .Brute, xp_reward = 30} e.base.gfx = {0 = GfxCircle{pos = {}, radius = 17, color = {160, 60, 220, 255}}} case .Scout: e = Enemy{actor = Actor{hp = 25, max_hp = 25, speed = 120}, touch_dmg = 5, kind = .Scout, xp_reward = 8} e.base.gfx = {0 = GfxCircle{pos = {}, radius = 8, color = {240, 180, 60, 255}}} } e.base.pos = pos e.base.col_size = 16 return Entity{v = e} } enemy_update :: proc(state: ^GameState, e: ^Enemy, h: Handle, dt: f32) { pe := get_entity(state, state.player) if pe != nil { dir := get_base(pe).pos - e.pos e.vel = rl.Vector2Normalize(dir) * e.speed } if e.hp <= 0 && !e.marked { e.marked = true enemy_give_rewards(e, state) } } enemy_give_rewards :: proc(e: ^Enemy, state: ^GameState) { _, p := get_player(state) if p == nil do return p.xp += e.xp_reward add_log(state, "+%d XP", e.xp_reward) check_level_up(state, p) if rand.int_max(100) < 60 { item := random_item(p.level) spawn(state, make_ground_item(e.pos, item)) add_log(state, "Dropped: %s lvl %d", item.name, item.level) } if rand.int_max(100) < 45 { ang := rand.float32() * 6.28 dist := 500 + rand.float32() * 300 pos := p.pos + rl.Vector2{math.cos_f32(ang), math.sin_f32(ang)} * dist spawn(state, make_enemy(pos, EnemyKind(rand.int_max(3)))) } }