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