75 lines
2.9 KiB
C++
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 });
|
|
}
|
|
}
|