This repository has been archived on 2022-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
LEFTONE/core/loui/combat.c

128 lines
3.7 KiB
C

#include "./combat.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "util/math/algorithm.h"
#include "util/math/vector.h"
#include "core/locommon/easing.h"
#include "core/locommon/ticker.h"
#include "core/loplayer/player.h"
#include "core/loshader/set.h"
#define FADE_SPEED_ 50
#define RING_ATTACK_RANGE_ .6f
#define RING_GUARD_RANGE_ .8f
#define RING_BASE_COLOR_(a) vec4(0, 0, 0, (a)*.6f)
#define RING_CLOCKHAND_COLOR_(a) vec4(1, 1, 1, (a))
#define RING_ATTACK_COLOR_(a) vec4(1, 0, 0, (a))
#define RING_GUARD_COLOR_(a) vec4(0, 0, 1, (a))
#define RING_TAIL_PADDING_ 500
void loui_combat_initialize(
loui_combat_t* combat,
loshader_set_t* shaders,
const locommon_ticker_t* ticker,
const loplayer_t* player) {
assert(combat != NULL);
assert(shaders != NULL);
assert(ticker != NULL);
assert(player != NULL);
*combat = (typeof(*combat)) {
.shaders = shaders,
.ticker = ticker,
.player = player,
};
}
void loui_combat_deinitialize(loui_combat_t* combat) {
assert(combat != NULL);
}
void loui_combat_update(loui_combat_t* combat) {
assert(combat != NULL);
const float dt = combat->ticker->delta_f;
const loplayer_combat_attack_t* la = combat->player->combat.last_attack;
locommon_easing_smooth_float(&combat->alpha, !!(la != NULL), dt*FADE_SPEED_);
if (la == NULL) {
if (combat->ring_end <= combat->ticker->time) {
combat->ring_end = 0;
}
return;
}
if (combat->ring_end <= combat->ring_start) {
combat->ring_start = combat->ticker->time;
}
combat->ring_end = la->start + la->duration + RING_TAIL_PADDING_;
}
void loui_combat_draw(const loui_combat_t* combat) {
assert(combat != NULL);
if (combat->alpha <= 0) return;
loshader_combat_ring_drawer_add_instance(
&combat->shaders->drawer.combat_ring,
&(loshader_combat_ring_drawer_instance_t) {
.range = -1, /* = base */
.color = RING_BASE_COLOR_(combat->alpha),
});
const uint64_t ring_st = combat->ring_start;
const uint64_t ring_ed = combat->ring_end;
if (ring_ed < ring_st) return;
const uint64_t t = combat->ticker->time;
const uint64_t dur = ring_ed - ring_st;
loshader_combat_ring_drawer_add_instance(
&combat->shaders->drawer.combat_ring,
&(loshader_combat_ring_drawer_instance_t) {
.range = 0, /* = clockhand */
.start = (t - ring_st)*1.f/dur,
.color = RING_CLOCKHAND_COLOR_(combat->alpha),
});
const loplayer_combat_t* pcombat = &combat->player->combat;
for (size_t i = 0; i < LOPLAYER_COMBAT_RESERVE; ++i) {
const loplayer_combat_attack_t* a = &pcombat->attacks[i];
if (a->duration == 0) continue;
const uint64_t st = MATH_MAX(ring_st, a->start);
const uint64_t ed = a->start+a->duration;
loshader_combat_ring_drawer_add_instance(
&combat->shaders->drawer.combat_ring,
&(loshader_combat_ring_drawer_instance_t) {
.range = RING_ATTACK_RANGE_,
.start = (st - ring_st)*1.f/dur,
.end = (ed - ring_st)*1.f/dur,
.color = RING_ATTACK_COLOR_(combat->alpha),
});
}
const uint64_t gst = MATH_MAX(ring_st, pcombat->last_guard_start);
const uint64_t ged =
pcombat->last_guard_start <= pcombat->last_guard_end?
pcombat->last_guard_end: t;
if (ring_st <= gst && gst < ged && ged < ring_ed) {
loshader_combat_ring_drawer_add_instance(
&combat->shaders->drawer.combat_ring,
&(loshader_combat_ring_drawer_instance_t) {
.range = RING_GUARD_RANGE_,
.start = (gst - ring_st)*1.f/dur,
.end = (ged - ring_st)*1.f/dur,
.color = RING_GUARD_COLOR_(combat->alpha),
});
}
}