Files
odin-iso-test/src3/enemy.odin
T
2026-08-03 21:11:00 +03:00

72 lines
1.9 KiB
Odin

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))))
}
}