bats now back off after an attack

This commit is contained in:
Lephenixnoir 2022-02-13 17:07:24 +01:00
parent d330c22d66
commit 33b8fda4da
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
2 changed files with 59 additions and 4 deletions

View File

@ -6,6 +6,7 @@
#include "aoe.h"
#include "enemies.h"
#include "skills.h"
#include <gint/defs/util.h>
#include <string.h>
/* Declare animations for an enemy */
@ -35,6 +36,11 @@ static enemy_t const slime_1 = {
.shadow_size = 4,
.xp = 2,
.z = 0,
.ai_data_size = 0,
};
struct bat_ai {
fixed_t retreat_period;
};
static enemy_t const bat_2 = {
@ -56,6 +62,7 @@ static enemy_t const bat_2 = {
.shadow_size = 4,
.xp = 6,
.z = fix(0.75),
.ai_data_size = sizeof(struct bat_ai),
};
static enemy_t const fire_slime_4 = {
@ -77,6 +84,7 @@ static enemy_t const fire_slime_4 = {
.shadow_size = 4,
.xp = 14,
.z = 0,
.ai_data_size = 0,
};
static enemy_t const gunslinger_8 = {
@ -98,6 +106,7 @@ static enemy_t const gunslinger_8 = {
.shadow_size = 4,
.xp = 30,
.z = fix(0.25),
.ai_data_size = 0,
};
static enemy_t const * const enemies[] = {
@ -151,13 +160,18 @@ entity_t *enemy_make(int enemy_id)
fighter_set_stats(f, &data->stats, data->level, fix(1.0));
f->HP = f->HP_max;
f->combo_length = 1;
f->enemy = malloc(sizeof *f->enemy);
f->enemy = malloc(sizeof *f->enemy + data->ai_data_size);
f->enemy->id = data;
f->enemy->pathfind_dir = (vec2){ 0, 0 };
f->enemy->pathfind_cycles = 0;
f->enemy->ai_data = (void *)f->enemy + sizeof *f->enemy;
/* Specify skills */
if(enemy_id == ENEMY_GUNSLINGER_8) {
/* Specify skills and initialize AI data */
if(enemy_id == ENEMY_BAT_2) {
struct bat_ai *ai_data = f->enemy->ai_data;
ai_data->retreat_period = 0;
}
else if(enemy_id == ENEMY_GUNSLINGER_8) {
f->skills[0] = AOE_PROJECTILE;
}
@ -216,6 +230,28 @@ static bool move_within_range_of_player(game_t *g, entity_t *e, fixed_t range,
return false;
}
static bool move_away_from_player_range(game_t *g, entity_t *e, fixed_t range,
fixed_t dt)
{
physical_t *p = getcomp(e, physical);
fighter_t *f = getcomp(e, fighter);
if(!p || !f || !f->enemy)
return true;
if(dist2(physical_pos(e), physical_pos(g->player)) > fmul(range, range))
return true;
/* Escape opposite the direction of normal movement */
vec2 direction = f->enemy->pathfind_dir;
direction = (vec2){ -direction.x, -direction.y };
mechanical_move(e, direction, dt, g->map);
if(p->x < getcomp(g->player, physical)->x) p->facing = RIGHT;
else p->facing = LEFT;
return false;
}
static bool contact_attack(game_t *g, entity_t *e)
{
fighter_t *f = getcomp(e, fighter);
@ -254,12 +290,27 @@ void enemy_ai(game_t *g, entity_t *e, fixed_t dt)
{
fighter_t *f = getcomp(e, fighter);
if(f->enemy->id == &slime_1 || f->enemy->id == &bat_2) {
if(f->enemy->id == &slime_1) {
if(move_within_range_of_player(g, e, fix(1.0), dt)) {
contact_attack(g, e);
}
}
else if(f->enemy->id == &bat_2) {
struct bat_ai *ai_data = f->enemy->ai_data;
/* After an attack, move away for a couple of seconds */
if(ai_data->retreat_period > 0) {
move_away_from_player_range(g, e, fix(3.0), dt);
ai_data->retreat_period = max(ai_data->retreat_period-dt, fix(0));
}
/* Otherwise, get close and attack */
else if(move_within_range_of_player(g, e, fix(1.0), dt)) {
contact_attack(g, e);
ai_data->retreat_period = fix(1.5);
}
}
else if(f->enemy->id == &fire_slime_4) {
}

View File

@ -32,6 +32,8 @@ typedef struct
uint16_t xp;
/* Rendering elevation */
fixed_t z;
/* Size of the monster-specific data structure for IA */
size_t ai_data_size;
} enemy_t;
@ -51,6 +53,8 @@ typedef struct enemy_data {
vec2 pathfind_dir;
/* Number of frames left until next pathfinding cycle */
uint8_t pathfind_cycles;
/* Pointer to AI-specific data */
void *ai_data;
} enemy_data_t;