105 lines
6.6 KiB
Markdown
105 lines
6.6 KiB
Markdown
# 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.
|