From 118be92dc5e6833007330aa217a8a83b179698a5 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Mon, 1 Jun 2026 10:35:45 -0400 Subject: [PATCH] feat(battle-node): ScriptedProfiles named constants for scripted bodies --- .../Lifecycle/ScriptedProfiles.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 SVSim.BattleNode/Lifecycle/ScriptedProfiles.cs diff --git a/SVSim.BattleNode/Lifecycle/ScriptedProfiles.cs b/SVSim.BattleNode/Lifecycle/ScriptedProfiles.cs new file mode 100644 index 0000000..63c24b5 --- /dev/null +++ b/SVSim.BattleNode/Lifecycle/ScriptedProfiles.cs @@ -0,0 +1,72 @@ +using SVSim.BattleNode.Protocol.Bodies; + +namespace SVSim.BattleNode.Lifecycle; + +/// +/// Named constants and templates for the v1 scripted lifecycle. Every value here +/// originated in a real prod frame in +/// data_dumps/captures/battle-traffic_tk2_regular.ndjson; pulling them out +/// of makes the magic numerics navigable and gives +/// the seed a single source of truth instead of two duplicated literals. +/// +internal static class ScriptedProfiles +{ + // Shared per the spec — selfInfo.seed and oppoInfo.seed always agree. + // From frame[2] (Matched). + public const long BattleSeed = 17_548_138L; + + // From frame[2] (Matched). OppoId is overwritten per battle from the bridge. + public static readonly MatchedSelfInfo PlayerMatchedProfile = new( + CountryCode: "KOR", + UserName: "Player", + SleeveId: "3000011", + EmblemId: "701441011", + DegreeId: "300003", + FieldId: 43, + IsOfficial: 0, + OppoId: 0, + Seed: BattleSeed); + + public static readonly MatchedOppoInfo OpponentMatchedProfile = new( + CountryCode: "JPN", + UserName: "Opponent", + SleeveId: "704141010", + EmblemId: "400001100", + DegreeId: "120027", + FieldId: 5, + IsOfficial: 0, + OppoId: 0, + Seed: BattleSeed, + OppoDeckCount: 30); + + // From frame[5] (BattleStart). + public static readonly BattleStartSelfInfo PlayerBattleStartProfile = new( + Rank: "10", + BattlePoint: "6270", + ClassId: "1", + CharaId: "1", + CardMasterName: "card_master_node_10015"); + + public static readonly BattleStartOppoInfo OpponentBattleStartProfile = new( + Rank: "1", + IsMasterRank: "0", + BattlePoint: 0, + MasterPoint: "0", + ClassId: "8", + CharaId: "8", + CardMasterName: "card_master_node_10015"); + + // From frame[8] (Ready). Provenance is "what prod sent"; the client + // doesn't validate, but echoing matches the capture protects against + // a regression on a future tightening. + public const int ReadyIdxChangeSeed = 771_335_280; + public const int ReadySpin = 243; + + // Generic non-zero spin that lands the client in "Opponent's turn..." + // display state. v1 doesn't simulate the opponent — once this lands, + // the client sits there indefinitely. + public const int OpponentTurnStartSpin = 100; + + // BattleFinish result code for v1 no-contest finishes (player wins). + public const int BattleResultPlayerWins = 1; +}