package gameserver import ( "fmt" goproto "gac-hkrpg-go/protocol/proto" ) // currencyWarsPlayerStats is run-local state, separate from adventure avatars. // Initial values must come from captured CW rules/run configuration. Zero is a // valid price or win count and is never replaced with an implicit default. type currencyWarsPlayerStats struct { HP, MaxHP uint32 Level, LevelLimit, Exp uint32 Gold, KeepWinCount uint32 FrontCapacity, BackCapacity uint32 BenchCapacity, MaxInterest uint32 BuyExpGoldCost, BuyExpHPCost uint32 } // applyProtoScalars preserves the separately managed restriction/tracker // containers on dst. It does not create a complete session or start a run. // Mapping: native GridFightPlayer.SetData at RVA 0xdb9d670, setter MethodDef // checks, and isolated NIHNGPKHEPC scalar wire encoding. See the CW investigation // document for the field-layout inference and outstanding Client verification. func (p currencyWarsPlayerStats) applyProtoScalars(dst *goproto.NIHNGPKHEPC) error { if dst == nil { return fmt.Errorf("CW player destination is missing") } if p.MaxHP == 0 || p.HP > p.MaxHP || p.Level == 0 || p.LevelLimit < p.Level { return fmt.Errorf("CW player health/level state is invalid") } dst.PPKKHHNEOHB = p.MaxHP dst.GridFightLineupHp = p.HP dst.NDAINFLOLPJ = p.LevelLimit dst.AFFCFLFIFPH = p.FrontCapacity dst.KNFOCCPOJEA = p.MaxInterest dst.GridFightCurLevelExp = p.Exp dst.JLOCMDIDPCI = p.BackCapacity dst.CPKLHPJMMDO = p.BuyExpHPCost dst.EHNJDIDABHD = p.Level dst.BEPMODICONA = p.BuyExpGoldCost dst.GDAKCOICIDA = p.KeepWinCount dst.Gold = p.Gold dst.MICEOJBAKGN = p.BenchCapacity return nil }