forked from NotAShelf/rogged
initial commit
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ie3b66d17f6f660c9b9a719210bd86f9f6a6a6964
This commit is contained in:
commit
b381e2efbd
29 changed files with 1633 additions and 0 deletions
139
src/enemy.c
Normal file
139
src/enemy.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include "enemy.h"
|
||||
#include "combat.h"
|
||||
#include "common.h"
|
||||
#include "map.h"
|
||||
#include "rng.h"
|
||||
|
||||
// Forward declaration
|
||||
int is_enemy_at(Enemy *enemies, int count, int x, int y);
|
||||
|
||||
void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) {
|
||||
*count = 0;
|
||||
|
||||
// Number of enemies scales with floor
|
||||
int num_enemies = 3 + floor + rng_int(0, 2);
|
||||
if (num_enemies > MAX_ENEMIES)
|
||||
num_enemies = MAX_ENEMIES;
|
||||
|
||||
// Enemy types available for this floor
|
||||
int max_type = 1;
|
||||
if (floor >= 2)
|
||||
max_type = 2;
|
||||
if (floor >= 4)
|
||||
max_type = 3;
|
||||
|
||||
for (int i = 0; i < num_enemies; i++) {
|
||||
// Find random floor position
|
||||
int ex, ey;
|
||||
get_random_floor_tile(map, &ex, &ey, 50);
|
||||
|
||||
// Don't spawn on player position
|
||||
if (ex == p->x && ey == p->y) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't spawn on other enemies
|
||||
if (is_enemy_at(enemies, *count, ex, ey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create enemy
|
||||
Enemy e;
|
||||
e.x = ex;
|
||||
e.y = ey;
|
||||
e.alive = 1;
|
||||
e.type = rng_int(ENEMY_GOBLIN, max_type);
|
||||
|
||||
// Stats based on type and floor
|
||||
switch (e.type) {
|
||||
case ENEMY_GOBLIN:
|
||||
e.hp = ENEMY_BASE_HP + floor;
|
||||
e.attack = ENEMY_BASE_ATTACK;
|
||||
break;
|
||||
case ENEMY_SKELETON:
|
||||
e.hp = ENEMY_BASE_HP + floor + 2;
|
||||
e.attack = ENEMY_BASE_ATTACK + 1;
|
||||
break;
|
||||
case ENEMY_ORC:
|
||||
e.hp = ENEMY_BASE_HP + floor + 4;
|
||||
e.attack = ENEMY_BASE_ATTACK + 2;
|
||||
break;
|
||||
default:
|
||||
e.hp = ENEMY_BASE_HP;
|
||||
e.attack = ENEMY_BASE_ATTACK;
|
||||
break;
|
||||
}
|
||||
|
||||
enemies[i] = e;
|
||||
(*count)++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if position has an enemy
|
||||
int is_enemy_at(Enemy *enemies, int count, int x, int y) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (enemies[i].alive && enemies[i].x == x && enemies[i].y == y) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if enemy can see player (adjacent)
|
||||
static int can_see_player(Enemy *e, Player *p) {
|
||||
int dx = p->x - e->x;
|
||||
int dy = p->y - e->y;
|
||||
return (dx >= -1 && dx <= 1 && dy >= -1 && dy <= 1);
|
||||
}
|
||||
|
||||
// Move enemy toward player
|
||||
static void enemy_move_toward_player(Enemy *e, Player *p, Map *map,
|
||||
Enemy *all_enemies, int enemy_count) {
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
if (p->x > e->x)
|
||||
dx = 1;
|
||||
else if (p->x < e->x)
|
||||
dx = -1;
|
||||
|
||||
if (p->y > e->y)
|
||||
dy = 1;
|
||||
else if (p->y < e->y)
|
||||
dy = -1;
|
||||
|
||||
// Try horizontal first, then vertical
|
||||
int new_x = e->x + dx;
|
||||
int new_y = e->y;
|
||||
|
||||
if (dx != 0 && is_floor(map, new_x, new_y) &&
|
||||
!is_enemy_at(all_enemies, enemy_count, new_x, new_y)) {
|
||||
e->x = new_x;
|
||||
} else if (dy != 0) {
|
||||
new_x = e->x;
|
||||
new_y = e->y + dy;
|
||||
if (is_floor(map, new_x, new_y) &&
|
||||
!is_enemy_at(all_enemies, enemy_count, new_x, new_y)) {
|
||||
e->x = new_x;
|
||||
e->y = new_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enemy_update_all(Enemy enemies[], int count, Player *p, Map *map) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
Enemy *e = &enemies[i];
|
||||
|
||||
if (!e->alive)
|
||||
continue;
|
||||
|
||||
// Check if adjacent to player - attack
|
||||
if (can_see_player(e, p)) {
|
||||
// Use combat system
|
||||
combat_enemy_attack(e, p);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, move toward player
|
||||
enemy_move_toward_player(e, p, map, enemies, count);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue