feat(stats): heals, repairs and restores count what they applied

Live sent TotalArmorRepaired / TotalImaginationRestored with what a repair
or restore applied, 0 included (1,050 and 2,148 zeros in the captures: a
power-up picked up at full), and never a TotalDamageHealed or
TotalDamageTaken of 0. DLU counted every change of the value instead, so
setting stats up (loading, respawning, level changes) counted as healing
and a heal at full health counted as 0 damage taken.

Now Heal, Repair and Imagine count what they applied; health lost and
imagination spent still count wherever they change.

Check in game: pick up an armor or imagination power-up when full; the
passport's Armor Repaired / Imagination Restored stay the same. Take damage
and heal; Damage Taken and Damage Healed go up by what the bar shows.
Respawn: Damage Healed doesn't jump.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 02:19:43 -05:00
parent 1f29e9604a
commit fd10e19a06
4 changed files with 56 additions and 13 deletions

View File

@@ -208,8 +208,9 @@ void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
void DestroyableComponent::SetHealth(int32_t value) {
m_DirtyHealth = true;
// Health lost counts as damage taken; healing counts where it is applied (Heal)
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
if (characterComponent != nullptr && value < m_iHealth) {
characterComponent->TrackHealthDelta(value - m_iHealth);
}
@@ -251,11 +252,6 @@ void DestroyableComponent::SetArmor(int32_t value) {
// If Destroyable Component already has zero armor do not trigger the passive ability again.
bool hadArmor = m_iArmor > 0;
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
characterComponent->TrackArmorDelta(value - m_iArmor);
}
m_iArmor = value;
auto* inventroyComponent = m_Parent->GetComponent<InventoryComponent>();
@@ -294,8 +290,9 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) {
void DestroyableComponent::SetImagination(int32_t value) {
m_DirtyHealth = true;
// Imagination spent counts as used; restoring counts where it is applied (Imagine)
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
if (characterComponent != nullptr && value < m_iImagination) {
characterComponent->TrackImaginationDelta(value - m_iImagination);
}
@@ -499,8 +496,12 @@ void DestroyableComponent::Heal(const uint32_t health) {
current = std::min(current, max);
const auto before = GetHealth();
SetHealth(current);
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->TrackHealthDelta(GetHealth() - before);
Game::entityManager->SerializeEntity(m_Parent);
}
@@ -517,8 +518,13 @@ void DestroyableComponent::Imagine(const int32_t deltaImagination) {
current = 0;
}
const auto before = GetImagination();
SetImagination(current);
// What was restored, 0 included (live sent TotalImaginationRestored 0 for a power-up picked up when full)
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
if (characterComponent && deltaImagination > 0) characterComponent->TrackImaginationDelta(GetImagination() - before);
Game::entityManager->SerializeEntity(m_Parent);
}
@@ -531,8 +537,13 @@ void DestroyableComponent::Repair(const uint32_t armor) {
current = std::min(current, max);
const auto before = GetArmor();
SetArmor(current);
// What was repaired, 0 included (live sent TotalArmorRepaired 0 when the armor was already full)
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->TrackArmorDelta(GetArmor() - before);
Game::entityManager->SerializeEntity(m_Parent);
}