Files

75 lines
2.9 KiB
C++

#include "Hitbox.h"
#include <algorithm>
#include <unordered_set>
#include "Character.h"
#include "Ragdoll.h"
#include "RenderSystem.h"
#include "tFunctions.h"
static constexpr float DEBUG_LINGER = 0.4f; // real seconds a hitbox stays drawn after it's gone
static const glm::vec3 HURTBOX_COLOR(0.2f, 0.9f, 0.35f);
static const glm::vec3 HITBOX_COLOR(1.0f, 0.2f, 0.2f);
static const glm::vec3 LANDED_COLOR(1.0f, 0.85f, 0.2f);
void HitboxSystem::Resolve(const std::vector<Character*>& characters, const HitHandler& onHit, float dt) {
// A swing nothing was added for this frame is over, so who it hit can go
std::unordered_set<unsigned int> going;
for (const Hitbox& hitbox : pending)
if (hitbox.swing != 0)
going.insert(hitbox.swing);
for (auto it = hitBySwing.begin(); it != hitBySwing.end(); )
it = going.count(it->first) ? std::next(it) : hitBySwing.erase(it);
for (Shown& old : shown)
old.timeLeft -= dt;
shown.erase(std::remove_if(shown.begin(), shown.end(), [](const Shown& old) { return old.timeLeft <= 0.0f; }), shown.end());
// Taken first, a hit is free to add more for next frame
const std::vector<Hitbox> hitboxes = std::move(pending);
pending.clear();
for (const Hitbox& hitbox : hitboxes) {
bool landed = false;
for (Character* target : characters) {
if (target == hitbox.owner || target->IsDead() || target->ragdoll || !target->body)
continue;
if (target->IsInvulnerable() || (target->DodgesHits() && !hitbox.hitsKnockedDown))
continue;
if (hitbox.swing != 0) {
const std::vector<const Character*>& already = hitBySwing[hitbox.swing];
if (std::find(already.begin(), already.end(), target) != already.end())
continue;
}
if (!TInT(hitbox.box, target->body->t, false).has_value())
continue;
if (hitbox.swing != 0)
hitBySwing[hitbox.swing].push_back(target);
landed = true;
onHit(hitbox, *target);
}
shown.push_back({ hitbox.box, landed, DEBUG_LINGER });
}
}
void HitboxSystem::AppendDebugLines(const std::vector<Character*>& characters, std::vector<HitboxDebugLine>& lines) const {
for (Character* character : characters) {
if (!character->body)
continue;
if (character->ragdoll) {
for (Ragdoll::Part* part : character->ragdoll->GetParts())
lines.push_back({ part->transform.t.GetMatrix(), HURTBOX_COLOR });
continue;
}
lines.push_back({ character->body->t.GetMatrix(), HURTBOX_COLOR });
}
for (const Shown& old : shown) {
const float fade = 0.3f + 0.7f * glm::clamp(old.timeLeft / DEBUG_LINGER, 0.0f, 1.0f);
lines.push_back({ old.box.GetMatrix(), (old.landed ? LANDED_COLOR : HITBOX_COLOR) * fade });
}
}