2021-12-25 11:47:22 +01:00
|
|
|
#include "comp/entity.h"
|
|
|
|
#include "comp/physical.h"
|
|
|
|
#include "comp/visible.h"
|
|
|
|
#include "comp/mechanical.h"
|
|
|
|
#include "comp/fighter.h"
|
2021-06-15 17:27:30 +02:00
|
|
|
#include "enemies.h"
|
2021-12-25 11:47:22 +01:00
|
|
|
#include <string.h>
|
2021-06-15 17:27:30 +02:00
|
|
|
|
2021-10-24 21:54:37 +02:00
|
|
|
/* Declare animations for an enemy */
|
2021-12-25 18:21:31 +01:00
|
|
|
#define ANIMS(name, I, W, A, H, D) \
|
2021-12-25 11:47:22 +01:00
|
|
|
.anim_idle = &anims_ ## name ## _ ## I, \
|
|
|
|
.anim_walking = &anims_ ## name ## _ ## W, \
|
2021-12-25 18:21:31 +01:00
|
|
|
.anim_attack = &anims_ ## name ## _ ## A, \
|
2021-12-25 11:47:22 +01:00
|
|
|
.anim_hit = &anims_ ## name ## _ ## H, \
|
|
|
|
.anim_death = &anims_ ## name ## _ ## D
|
2021-10-24 21:54:37 +02:00
|
|
|
|
2021-06-15 17:27:30 +02:00
|
|
|
static enemy_t const slime = {
|
|
|
|
.name = "Slime",
|
2021-12-25 18:21:31 +01:00
|
|
|
ANIMS(slime, Idle, Walking, Idle, Hit, Death),
|
2021-10-24 21:54:37 +02:00
|
|
|
.hitbox = (rect){ -fix(3)/16, fix(4)/16, -fix(2)/16, fix(3)/16 },
|
|
|
|
.sprite = (rect){ -fix(5)/16, fix(5)/16, -fix(4)/16, fix(3)/16 },
|
2021-12-25 11:47:22 +01:00
|
|
|
.limits = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.max_speed = fix(1),
|
2021-12-25 11:47:22 +01:00
|
|
|
.friction = fix(0.6),
|
2021-06-15 17:27:30 +02:00
|
|
|
},
|
2021-06-25 11:44:29 +02:00
|
|
|
.HP = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.base = fix(10),
|
|
|
|
.growth = fix(5),
|
|
|
|
.affinity = fix(3),
|
2021-06-25 11:44:29 +02:00
|
|
|
},
|
|
|
|
.ATK = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.base = fix(5),
|
|
|
|
.growth = fix(2),
|
|
|
|
.affinity = fix(1),
|
2021-06-25 11:44:29 +02:00
|
|
|
},
|
|
|
|
.DEF = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.base = fix(2),
|
|
|
|
.growth = fix(1),
|
|
|
|
.affinity = fix(0.5),
|
2021-06-25 11:44:29 +02:00
|
|
|
},
|
2021-12-25 11:47:22 +01:00
|
|
|
.shadow_size = 4,
|
|
|
|
.z = 0,
|
2021-06-15 17:27:30 +02:00
|
|
|
};
|
|
|
|
|
2021-06-25 12:07:22 +02:00
|
|
|
static enemy_t const bat = {
|
|
|
|
.name = "Bat",
|
2021-12-25 18:21:31 +01:00
|
|
|
ANIMS(bat, Idle, Idle, Idle, Hit, Death),
|
2021-10-24 21:54:37 +02:00
|
|
|
.hitbox = (rect){ -fix(3)/16, fix(4)/16, -fix(2)/16, fix(3)/16 },
|
|
|
|
.sprite = (rect){ -fix(5)/16, fix(5)/16, -fix(4)/16, fix(3)/16 },
|
2021-12-25 11:47:22 +01:00
|
|
|
.limits = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.max_speed = fix(1.8),
|
2021-12-25 11:47:22 +01:00
|
|
|
.friction = fix(0.8),
|
2021-06-25 12:07:22 +02:00
|
|
|
},
|
|
|
|
.HP = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.base = fix(8),
|
|
|
|
.growth = fix(4),
|
|
|
|
.affinity = fix(2),
|
2021-06-25 12:07:22 +02:00
|
|
|
},
|
|
|
|
.ATK = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.base = fix(8),
|
|
|
|
.growth = fix(2),
|
|
|
|
.affinity = fix(2),
|
2021-06-25 12:07:22 +02:00
|
|
|
},
|
|
|
|
.DEF = {
|
2021-07-16 18:49:58 +02:00
|
|
|
.base = fix(2),
|
|
|
|
.growth = fix(2),
|
|
|
|
.affinity = fix(1),
|
2021-06-25 12:07:22 +02:00
|
|
|
},
|
2021-12-25 11:47:22 +01:00
|
|
|
.shadow_size = 4,
|
|
|
|
.z = fix(0.75),
|
2021-06-25 12:07:22 +02:00
|
|
|
};
|
|
|
|
|
2021-12-25 18:21:31 +01:00
|
|
|
static enemy_t const gunslinger = {
|
|
|
|
.name = "Gunslinger",
|
|
|
|
ANIMS(gunslinger, Idle, Walking, Fire, Hit, Death),
|
|
|
|
.hitbox = (rect){ -fix(3)/16, fix(4)/16, -fix(2)/16, fix(3)/16 },
|
|
|
|
.sprite = (rect){ -fix(5)/16, fix(5)/16, -fix(4)/16, fix(3)/16 },
|
|
|
|
.limits = {
|
|
|
|
.max_speed = fix(1.8),
|
|
|
|
.friction = fix(0.8),
|
|
|
|
},
|
|
|
|
.HP = {
|
|
|
|
.base = fix(8),
|
|
|
|
.growth = fix(4),
|
|
|
|
.affinity = fix(2),
|
|
|
|
},
|
|
|
|
.ATK = {
|
|
|
|
.base = fix(8),
|
|
|
|
.growth = fix(2),
|
|
|
|
.affinity = fix(2),
|
|
|
|
},
|
|
|
|
.DEF = {
|
|
|
|
.base = fix(2),
|
|
|
|
.growth = fix(2),
|
|
|
|
.affinity = fix(1),
|
|
|
|
},
|
|
|
|
.shadow_size = 4,
|
|
|
|
.z = fix(0.375),
|
|
|
|
};
|
|
|
|
|
2021-06-25 12:07:22 +02:00
|
|
|
enemy_t const * const enemies[] = {
|
2021-12-25 18:21:31 +01:00
|
|
|
[ENEMY_SLIME] = &slime,
|
|
|
|
[ENEMY_BAT] = &bat,
|
|
|
|
[ENEMY_GUNSLINGER] = &gunslinger,
|
2021-06-15 17:27:30 +02:00
|
|
|
};
|
|
|
|
|
2021-10-24 21:54:37 +02:00
|
|
|
static int instantiate_stat(enemy_stat_t const *stat, int level)
|
2021-06-25 11:44:29 +02:00
|
|
|
{
|
|
|
|
fixed_t value = stat->base + stat->growth * (level - 1) +
|
|
|
|
stat->affinity * (level * (level - 1) / 2);
|
|
|
|
|
|
|
|
fixed_t variation = value / 8;
|
|
|
|
value = (value - variation) + (rand() % (2 * variation));
|
|
|
|
|
|
|
|
return ffloor(value);
|
|
|
|
}
|
|
|
|
|
2021-12-25 11:47:22 +01:00
|
|
|
entity_t *enemy_make(int enemy_id, int level)
|
2021-06-15 17:27:30 +02:00
|
|
|
{
|
|
|
|
if(enemy_id < 0 || (size_t)enemy_id >= sizeof enemies / sizeof *enemies)
|
|
|
|
return NULL;
|
|
|
|
|
2021-12-25 11:47:22 +01:00
|
|
|
entity_t *e = entity_make(physical, visible, mechanical, fighter);
|
|
|
|
if(e == NULL)
|
|
|
|
return NULL;
|
2021-06-15 17:27:30 +02:00
|
|
|
|
|
|
|
enemy_t const *data = enemies[enemy_id];
|
|
|
|
|
|
|
|
/* These will probably be overridden by the caller */
|
2021-08-30 19:07:22 +02:00
|
|
|
|
2021-12-25 11:47:22 +01:00
|
|
|
physical_t *p = getcomp(e, physical);
|
|
|
|
p->x = fix(0);
|
|
|
|
p->y = fix(0);
|
|
|
|
p->hitbox = data->hitbox;
|
|
|
|
p->facing = LEFT;
|
|
|
|
|
|
|
|
visible_t *v = getcomp(e, visible);
|
|
|
|
v->z = data->z;
|
|
|
|
v->sprite_plane = VERTICAL;
|
|
|
|
v->shadow_size = data->shadow_size;
|
|
|
|
v->anim_priority = 0;
|
|
|
|
visible_set_anim(e, data->anim_idle, 1);
|
|
|
|
|
|
|
|
mechanical_t *m = getcomp(e, mechanical);
|
|
|
|
m->limits = &data->limits;
|
|
|
|
m->vx = fix(0);
|
|
|
|
m->vy = fix(0);
|
|
|
|
m->dash = fix(0);
|
|
|
|
m->dash_facing = LEFT;
|
|
|
|
|
|
|
|
/* Instantiate fighter statistics */
|
|
|
|
fighter_t *f = getcomp(e, fighter);
|
|
|
|
memset(f, 0, sizeof *f);
|
|
|
|
|
|
|
|
f->identity = enemy_id;
|
|
|
|
f->HP_max = instantiate_stat(&data->HP, level);
|
|
|
|
f->ATK = instantiate_stat(&data->ATK, level);
|
|
|
|
f->DEF = instantiate_stat(&data->DEF, level);
|
|
|
|
f->HP = f->HP_max;
|
|
|
|
f->combo_length = 1;
|
2021-06-25 11:44:29 +02:00
|
|
|
|
2021-06-15 17:27:30 +02:00
|
|
|
return e;
|
|
|
|
}
|