Files
GaCy-GO/docs/damage-analyst-live.md

6.6 KiB
Raw Permalink Blame History

Damage Analyst: native live statistics

The Client's final PVEBattleResult packet can contain a correct monster/team total while all AvatarBattleInfo detail counters are zero. Its cached native PVEGameStatistics still contains the complete character details. The old live sender also read this last completed report during the next battle.

The live sender now reads the active BattleGamePhase.BattleInstanceRef's logic GameWorld, then the native level entity's StatisticsComponent. It reads only known fields and caches them; component discovery is bounded to 16 entities and 32 component slots per sample and uses the named StatisticsComponent type. No assembly-wide reflection is performed. Do not call BuildPVEStatistics while playing: native code caches the snapshot it builds, so calling it for a UI poll could freeze the game's eventual report at an early point.

The source _LightTeamStt contains the current AvatarBattleInfo. Native PVECharacterStt dictionaries supply attack-type totals (FNFFCPLHPGI), break totals (HNJNDLEFMBE) and maximum hits (KEOOJBHFLFD) because the corresponding protobuf lists are assembled only at settlement. The aggregate total remains the named TotalDamage; some attribution counters do not appear in the category dictionary, so that aggregate is not replaced by a category sum.

Additional fixes:

  • XLua returns protobuf byte arrays as Lua strings on this Client. Their byte length is #bytes; .Length was nil and stopped all uploads.
  • UploadHandlerRaw accepts the ASCII JSON body directly as bytes. Calling the unavailable Encoding.GetBytes overload stopped uploads after the first fix.
  • Sampling runs every 750 ms through render callbacks, with a heartbeat fallback for background windows/render paths that suppress a callback. Callbacks read the current sample function after a script refresh; earlier broken callback states are disabled without changing Client battle state.
  • Native NOGHNMCDDAI is a damage-taken breakdown, verified against supports with zero dealt damage. It is no longer used as a damage-dealt fallback.
  • BattleInfo accompanies live reports, providing StageID, BattleID, level, rank and each avatar's actual slot. The companion UI orders by these slots, independently of the overworld team. Historical reports without slots keep their recorded order.
  • Final native details are attached only to a completed result whose duration, turn count and avatar IDs match. Server outcome and monster analysis remain intact; mismatching snapshots are rejected and cannot change the report.
  • The UI renders additional native attack types, including ElationDamage and TrueDamage, with escaped labels instead of omitting those categories.

Evidence and verification

The ignored battle_diagnostics/damage-live-20261019 directory preserves native protobuf snapshots, diagnostic logs and live-api-verified.json. The Client assembly SHA-256 is c5e02e6e984f7e5577c78b995a8efeee2d06ee22e67d484ad5e859c8bf21e144.

During the user's active stage 1052106, API is_live=true changed from 5,906,923.87 to 6,825,838.95 damage before settlement, with four current characters in slots 0–3, level/rank metadata, native category breakdowns and shares summing to 100%. This verifies the Client-to-SDK live path; it is not a synthetic test report. Frontend slot/category changes require the corresponding GaC-srtool build to be published before they appear on hosted GitHub Pages.

Focused Go report/API tests cover damage-taken exclusion, native category data, slot identity, final matching/rejection and expiry. The frontend Node tests cover actual battle order versus a different overworld team and historical report behavior. Diagnostic probes are kept outside scripts after capture.

Published GaC-srtool commit e03e5b1 to main with user approval. The GitHub Pages workflow completed successfully, and fetching the public app.js confirmed the battle-slot and additional-category code. The final real Client report retained WIN, Stage1052106, four slots 0-3 and detailed damage after leaving battle. Browser UI automation was unavailable in local Work settings; frontend rendering was checked with the actual captured live report in a DOM fixture, plus a public asset check.

Memosprite attribution and Other (2026-10-20)

The earlier reader omitted the separate servant statistics. The native named StatisticsComponent field _ServantStt contains LLPEHDFMLNJ values; bounded reflection of this specific type found LJLDPJFOKCE (HFALLFOEHKN servant protobuf) and the same three attack-type dictionaries as character statistics. Completed PVEGameStatistics exposes servantBattleInfoList. Both are now sent through the SDK as separate servant protobufs; active category dictionaries are hydrated without invoking the native final snapshot builder.

The checked-in protocol's BattleAvatarServantInfo explicitly names avatar_id, entity_id, aggregate damage and attack-type lists. Ownership uses avatar_id, with no character ID or lineup-position special cases. The report combines the separate servant damage/healing/shield with that owner and exposes the included damage as memosprite_damage. Damage taken and owner turns remain the owner's counters. Maximum hit uses the maximum across owner and servant, rather than adding maxima. Repeated nonzero entity IDs are ignored. Team totals/shares are rebuilt from attributed records so a monster damage-taken fallback is not added again. Inputs are not modified, and alternate servant sources cannot be mixed in the same request.

The fifth frontend category is Other: the nonnegative remainder after Basic, Skill, Ultimate and Break. Existing named extra categories remain visible as details. A Memosprite line explicitly marks its damage as included in the character total. Frontend commit ca5831c contains only these damage changes; unrelated item-catalog work in the shared checkout was left uncommitted.

Verification: focused Go report/API tests pass, including an HTTP roundtrip with owner-only and servant records, correct percentage recalculation, duplicate/unknown owner handling, and prevention of monster-fallback double counting. Four frontend tests pass, including Other arithmetic and existing slot order. The local SDK executable has the new receiver. Temporary servant probes have been removed from scripts/ and retained only under tools/.

Runtime limitation: the current session did not provide a nonempty servant sample. The previous real Client verification above used a team without memosprites. Evernight's live/final ownership and aggregate behavior still need a real battle capture; passing synthetic tests does not establish that the Client integration works. Native obfuscated field names remain revision-bound.