mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-16 17:44:08 +00:00
feat(stats): coins, bricks and smashes counted by the server as live did
The passport totals for coins, bricks and enemies came from the client's ModifyPlayerZoneStatistic, which live's client sent for its per-zone counts; live's server counted the totals itself and told the client (UpdatePlayerStatistic). Now: - CurrencyCollected (the amount gained) right after every SetCurrency that raised the coins (pickups, missions, achievements, selling, activities); none for losses. Captures: 15,815 pickups + mission/achievement/vendor/ activity gains, all with the stat; no loss had one. - BricksCollected (the count) after every add to the bricks inventory the client is told about (captures: 999 of 1,010, pickups and relocations). - The kill counts go to the killer right after Die, before the loot: EnemiesSmashed when the DestructibleComponent's isnpc is set, else SmashablesSmashed for a smashable (captures: 2,766 NPC kills and 538 smashables; faction or AI don't decide it, e.g. the Banana Cluster has AI and counted as a smashable). Neither while racing. Before, every kill was a SmashablesSmashed. - ModifyPlayerZoneStatistic from the client only updates the zone counts, so nothing is counted twice. Check in game: pick up coins, sell an item, finish a mission, pick up bricks, smash a stromling and a crate; each passport number goes up by the right amount at once and stays the same after relogging (no double counts). The per-zone statistics still go up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -606,6 +606,10 @@ void CharacterComponent::TrackArmorDelta(int32_t armor) {
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterComponent::TrackItemsAdded(eInventoryType inventoryType, uint32_t count) {
|
||||
if (inventoryType == eInventoryType::BRICKS && count > 0) UpdatePlayerStatistic(BricksCollected, count);
|
||||
}
|
||||
|
||||
void CharacterComponent::TrackQuickBuildComplete() {
|
||||
UpdatePlayerStatistic(QuickBuildsCompleted);
|
||||
|
||||
@@ -670,14 +674,13 @@ void CharacterComponent::SendPlayerStatistic(StatisticID updateID, uint64_t upda
|
||||
void CharacterComponent::HandleZoneStatisticsUpdate(LWOMAPID zoneID, const std::u16string& name, int32_t value) {
|
||||
auto zoneStatistics = &GetZoneStatisticsForMap(zoneID);
|
||||
|
||||
// The client's per-zone counts; the passport totals are the server's (UpdatePlayerStatistic), so they aren't
|
||||
// counted twice
|
||||
if (name == u"BricksCollected") {
|
||||
m_BricksCollected += value;
|
||||
zoneStatistics->m_BricksCollected += value;
|
||||
} else if (name == u"CoinsCollected") {
|
||||
m_CurrencyCollected += value;
|
||||
zoneStatistics->m_CoinsCollected += value;
|
||||
} else if (name == u"EnemiesSmashed") {
|
||||
m_EnemiesSmashed += value;
|
||||
zoneStatistics->m_EnemiesSmashed += value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <set>
|
||||
#include "Loot.h"
|
||||
#include "StatisticID.h"
|
||||
#include "eInventoryType.h"
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
|
||||
@@ -217,6 +218,12 @@ public:
|
||||
*/
|
||||
void TrackArmorDelta(int32_t armor);
|
||||
|
||||
/**
|
||||
* Counts items added to the inventory the client was told about (AddItemToInventoryClientSync): live followed
|
||||
* every add to the bricks inventory with BricksCollected (the count), whatever the source.
|
||||
*/
|
||||
void TrackItemsAdded(eInventoryType inventoryType, uint32_t count);
|
||||
|
||||
/**
|
||||
* Handles completing a rebuild by updating the statistics
|
||||
*/
|
||||
|
||||
@@ -743,6 +743,16 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
die.lootOwnerID = source;
|
||||
die.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
// Live told the killer right after Die, before the loot: EnemiesSmashed for an NPC, SmashablesSmashed for another
|
||||
// smashable. Racing counts its own (RacingSmashablesSmashed).
|
||||
if (owner && owner != m_Parent) {
|
||||
auto* killerCharacter = owner->GetComponent<CharacterComponent>();
|
||||
if (killerCharacter && !killerCharacter->GetIsRacing()) {
|
||||
if (m_IsNPC) killerCharacter->UpdatePlayerStatistic(EnemiesSmashed);
|
||||
else if (m_IsSmashable) killerCharacter->UpdatePlayerStatistic(SmashablesSmashed);
|
||||
}
|
||||
}
|
||||
|
||||
//NANI?!
|
||||
if (!isPlayer) {
|
||||
if (owner != nullptr) {
|
||||
|
||||
@@ -225,6 +225,13 @@ public:
|
||||
*/
|
||||
bool GetIsSmashable() const { return m_IsSmashable; }
|
||||
|
||||
/**
|
||||
* Whether this is an NPC (the DestructibleComponent's isnpc): live counted smashing one as EnemiesSmashed, other
|
||||
* smashables as SmashablesSmashed
|
||||
*/
|
||||
void SetIsNPC(bool value) { m_IsNPC = value; }
|
||||
bool GetIsNPC() const { return m_IsNPC; }
|
||||
|
||||
/**
|
||||
* Returns the current is-dead value, this is mostly unused
|
||||
* @return the current is-dead value, this is mostly unused
|
||||
@@ -574,6 +581,8 @@ private:
|
||||
*/
|
||||
bool m_IsSmashable;
|
||||
|
||||
bool m_IsNPC = false;
|
||||
|
||||
/**
|
||||
* Whether this entity is dead. Unused, here for serialization
|
||||
*/
|
||||
|
||||
@@ -345,6 +345,7 @@ ReceivedItem InventoryComponent::ReceiveItem(const LWOOBJID id, const LOT lot, c
|
||||
addItem.newObjID = id;
|
||||
addItem.showFlyingLoot = options.showFlyingLoot && !options.equip;
|
||||
addItem.SendToClient(m_Parent->GetSystemAddress());
|
||||
if (auto* characterComponent = m_Parent->GetComponent<CharacterComponent>()) characterComponent->TrackItemsAdded(inventoryType, count);
|
||||
EconomyLedger::RecordItems(m_Parent, lot, count, static_cast<uint32_t>(lootSourceType));
|
||||
Contraband::OnItemAdded(m_Parent, lot, count, lootSourceType, options.sourceInventory);
|
||||
if (options.equip) {
|
||||
|
||||
Reference in New Issue
Block a user