RogueLife/src/comp/fighter.c

115 lines
2.9 KiB
C

#include "comp/entity.h"
#include "comp/fighter.h"
#include "comp/visible.h"
#include "enemies.h"
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <gint/defs/util.h>
fighter_stat_model_t fighter_stat_model_mul(int amount, ...)
{
va_list args;
va_start(args, amount);
fighter_stat_model_t model = {
.HP = fix(1),
.ATK = fix(1),
.DEF = fix(1),
.MAG = fix(1), };
for(int i = 0; i < amount; i++) {
fighter_stat_model_t op = va_arg(args, fighter_stat_model_t);
model.HP = fmul(model.HP , op.HP);
model.ATK = fmul(model.ATK, op.ATK);
model.DEF = fmul(model.DEF, op.DEF);
model.MAG = fmul(model.MAG, op.MAG);
}
va_end(args);
return model;
}
static int instantiate_stat(fixed_t affinity, fixed_t multiplier, int level)
{
float a = f2double(affinity);
float x = level;
float y = powf(x, a) + x + 3 * a;
return fround(multiplier * (int)y);
}
fighter_stat_model_t fighter_stat_model_instantiate(
fighter_stat_model_t const *model, fighter_stat_model_t const *equipment,
int level, fixed_t hp_multiplier)
{
fighter_stat_model_t m;
m.HP = fix(instantiate_stat(model->HP, 3 * hp_multiplier, level));
m.ATK = fix(instantiate_stat(model->ATK, fix(1.6), level));
m.DEF = fix(instantiate_stat(model->DEF, fix(0.7), level));
m.MAG = fix(instantiate_stat(model->MAG, fix(1.2), level));
/* Apply equipment boost */
if(equipment) {
m.HP = fmul(m.HP, equipment->HP);
m.ATK = fmul(m.ATK, equipment->ATK);
m.DEF = fmul(m.DEF, equipment->DEF);
m.MAG = fmul(m.MAG, equipment->MAG);
}
return m;
}
void fighter_set_stats(fighter_t *f, fighter_stat_model_t const *instance)
{
f->HP_max = ffloor(instance->HP);
f->ATK = ffloor(instance->ATK);
f->MAG = ffloor(instance->MAG);
f->DEF = ffloor(instance->DEF);
}
int fighter_damage(entity_t *e, int base_damage)
{
fighter_t *f = getcomp(e, fighter);
if(f->HP == 0) return 0;
base_damage = max(base_damage - f->DEF, 0);
int variation = (base_damage >= 4) ? (rand() % (base_damage / 4)) : 0;
int damage = (base_damage * 7) / 8 + variation;
damage = max(damage, 1);
if(f->HP < damage) f->HP = 0;
else f->HP -= damage;
if(f->enemy) {
if(f->HP == 0)
visible_set_anim(e, f->enemy->id->anim_death, 4);
else
visible_set_anim(e, f->enemy->id->anim_hit, 3);
}
else {
visible_set_anim(e, &anims_player_Hit, 3);
}
return damage;
}
void fighter_stun(entity_t *e, fixed_t duration)
{
fighter_t *f = getcomp(e, fighter);
f->stun_delay = max(f->stun_delay, duration);
}
void fighter_invulnerability(entity_t *e, fixed_t duration)
{
fighter_t *f = getcomp(e, fighter);
f->invulnerability_delay = max(f->invulnerability_delay, duration);
}
void fighter_destroy(entity_t *e)
{
fighter_t *f = getcomp(e, fighter);
free(f->enemy);
}