95 lines
3.2 KiB
Go
95 lines
3.2 KiB
Go
package common
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"crypto/sha256"
|
||
|
|
"encoding/hex"
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
)
|
||
|
|
|
||
|
|
type CurrencyWarsOrb struct {
|
||
|
|
ID uint32 `json:"OrbID"`
|
||
|
|
Bonus uint32 `json:"BonusID"`
|
||
|
|
Type uint32 `json:"Type"`
|
||
|
|
}
|
||
|
|
type CurrencyWarsConsumable struct {
|
||
|
|
ID uint32
|
||
|
|
IfStack, IfConsume bool
|
||
|
|
ConsumableRule uint32
|
||
|
|
ConsumableParamList []uint32
|
||
|
|
}
|
||
|
|
type CurrencyWarsForge struct {
|
||
|
|
ID, FuncType, EquipNum, EquipCategory uint32
|
||
|
|
ParamList []uint32
|
||
|
|
}
|
||
|
|
type CurrencyWarsCombination struct {
|
||
|
|
ID uint32 `json:"BonusID"`
|
||
|
|
Pools []uint32 `json:"CombinationBonusList"`
|
||
|
|
Counts []uint32 `json:"BonusNumberList"`
|
||
|
|
}
|
||
|
|
type CurrencyWarsRewards struct {
|
||
|
|
Orbs map[uint32]CurrencyWarsOrb
|
||
|
|
Consumables map[uint32]CurrencyWarsConsumable
|
||
|
|
Forges map[uint32]CurrencyWarsForge
|
||
|
|
Combinations map[uint32]CurrencyWarsCombination
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tables are complete flat-table captures for the recorded Client revision.
|
||
|
|
// Bonus-pool resolution and item-effect execution are separate prerequisites.
|
||
|
|
func LoadCurrencyWarsRewards(c *CurrencyWarsCatalog) (*CurrencyWarsRewards, error) {
|
||
|
|
raw, err := ReadResourceFile("resources/CurrencyWarsRewards.json")
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
var r struct {
|
||
|
|
Format uint32 `json:"format_version"`
|
||
|
|
Client string `json:"target_client_version"`
|
||
|
|
Assembly string `json:"target_assembly_sha256"`
|
||
|
|
Capture string `json:"source_capture_sha256"`
|
||
|
|
Tables struct {
|
||
|
|
Orbs []CurrencyWarsOrb `json:"orb"`
|
||
|
|
Consumables []CurrencyWarsConsumable `json:"consumable"`
|
||
|
|
Forges []CurrencyWarsForge `json:"forge"`
|
||
|
|
Combinations []CurrencyWarsCombination `json:"combination"`
|
||
|
|
} `json:"tables"`
|
||
|
|
}
|
||
|
|
if err = json.Unmarshal(raw, &r); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if c == nil || r.Format != 1 || r.Client != c.ClientVersion || r.Assembly != c.Provenance.GameAssemblySHA256 {
|
||
|
|
return nil, fmt.Errorf("CW reward table revision differs")
|
||
|
|
}
|
||
|
|
hash, e := hex.DecodeString(r.Capture)
|
||
|
|
if e != nil || len(hash) != sha256.Size {
|
||
|
|
return nil, fmt.Errorf("CW reward capture provenance missing")
|
||
|
|
}
|
||
|
|
out := &CurrencyWarsRewards{Orbs: map[uint32]CurrencyWarsOrb{}, Consumables: map[uint32]CurrencyWarsConsumable{}, Forges: map[uint32]CurrencyWarsForge{}, Combinations: map[uint32]CurrencyWarsCombination{}}
|
||
|
|
for _, v := range r.Tables.Orbs {
|
||
|
|
if _, ok := out.Orbs[v.ID]; v.ID == 0 || v.Bonus == 0 || ok {
|
||
|
|
return nil, fmt.Errorf("CW Orb identity invalid")
|
||
|
|
}
|
||
|
|
out.Orbs[v.ID] = v
|
||
|
|
}
|
||
|
|
for _, v := range r.Tables.Consumables {
|
||
|
|
if _, ok := out.Consumables[v.ID]; v.ID == 0 || ok {
|
||
|
|
return nil, fmt.Errorf("CW consumable identity invalid")
|
||
|
|
}
|
||
|
|
out.Consumables[v.ID] = v
|
||
|
|
}
|
||
|
|
for _, v := range r.Tables.Forges {
|
||
|
|
if _, ok := out.Forges[v.ID]; v.ID == 0 || v.EquipNum == 0 || ok {
|
||
|
|
return nil, fmt.Errorf("CW forge identity invalid")
|
||
|
|
}
|
||
|
|
out.Forges[v.ID] = v
|
||
|
|
}
|
||
|
|
for _, v := range r.Tables.Combinations {
|
||
|
|
if _, ok := out.Combinations[v.ID]; v.ID == 0 || len(v.Pools) != len(v.Counts) || ok {
|
||
|
|
return nil, fmt.Errorf("CW combination identity invalid")
|
||
|
|
}
|
||
|
|
out.Combinations[v.ID] = v
|
||
|
|
}
|
||
|
|
if len(out.Orbs) == 0 || len(out.Consumables) == 0 || len(out.Forges) == 0 || len(out.Combinations) == 0 {
|
||
|
|
return nil, fmt.Errorf("CW reward tables incomplete")
|
||
|
|
}
|
||
|
|
return out, nil
|
||
|
|
}
|