pre cw with probe and a bunch script to read game behavior
This commit is contained in:
1 parent
5120219ae2
commit
da8a32f60d
310 files changed
+219693
-872
No files matched your search
@@ -0,0 +1,88 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Role variants retain the native row JSON without converting FixPoint strings
|
||||
// or text hashes to float64. Only the captured star is available here; this
|
||||
// does not imply that every star or every hidden shop role has been captured.
|
||||
type CurrencyWarsRoleVariant struct {
|
||||
Config CurrencyWarsRoleConfig `json:"Config"`
|
||||
Price uint32 `json:"Price"`
|
||||
MaxStar uint32 `json:"MaxStar"`
|
||||
Star uint32 `json:"Star"`
|
||||
SellPrice uint32 `json:"SellPrice"`
|
||||
SaleQuoteKnown *bool `json:"SaleQuoteKnown,omitempty"`
|
||||
StarConfig json.RawMessage `json:"StarConfig"`
|
||||
ServantStarConfig json.RawMessage `json:"ServantStarConfig"`
|
||||
}
|
||||
|
||||
func (c *CurrencyWarsCatalog) validateRoleVariants() error {
|
||||
c.variantByKey = make(map[[2]uint32]CurrencyWarsRoleVariant)
|
||||
if len(c.CapturedVariants) == 0 && c.Provenance.VariantsSHA256 == "" {
|
||||
return nil // Older catalogs have no variant capture; lookups reject it.
|
||||
}
|
||||
digest, err := hex.DecodeString(c.Provenance.VariantsSHA256)
|
||||
if err != nil || len(digest) != sha256.Size || len(c.CapturedVariants) == 0 {
|
||||
return fmt.Errorf("CW role variant capture or provenance is missing")
|
||||
}
|
||||
if c.Provenance.StarRowsSHA256 != "" {
|
||||
d, e := hex.DecodeString(c.Provenance.StarRowsSHA256)
|
||||
if e != nil || len(d) != sha256.Size {
|
||||
return fmt.Errorf("CW star row capture identity is invalid")
|
||||
}
|
||||
}
|
||||
for _, role := range c.CapturedVariants {
|
||||
key := [2]uint32{role.Config.ID, role.Star}
|
||||
if role.Config.ID == 0 || role.Config.AvatarID == 0 || role.Config.Rarity == 0 ||
|
||||
role.Config.SeasonID != c.ActiveSeasonID || role.Star == 0 || role.Star > role.MaxStar {
|
||||
return fmt.Errorf("invalid CW captured role variant %v", key)
|
||||
}
|
||||
if _, exists := c.variantByKey[key]; exists {
|
||||
return fmt.Errorf("duplicate CW captured role variant %v", key)
|
||||
}
|
||||
var identity struct{ ID, Star uint32 }
|
||||
if err := json.Unmarshal(role.StarConfig, &identity); err != nil || identity.ID != key[0] || identity.Star != key[1] {
|
||||
return fmt.Errorf("CW role star row identity differs for %v", key)
|
||||
}
|
||||
c.variantByKey[key] = role
|
||||
}
|
||||
for id, role := range c.roleByID {
|
||||
variant, exists := c.variantByKey[[2]uint32{id, role.DefaultStar}]
|
||||
if !exists || variant.Price != role.Price || variant.SellPrice != role.DefaultSellPrice || variant.MaxStar != role.MaxStar ||
|
||||
variant.Config.AvatarID != role.Config.AvatarID || variant.Config.SeasonID != role.Config.SeasonID {
|
||||
return fmt.Errorf("CW variant capture differs from default role %d", id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CurrencyWarsCatalog) CapturedRoleVariant(roleID, star uint32) (CurrencyWarsRoleVariant, error) {
|
||||
role, exists := c.variantByKey[[2]uint32{roleID, star}]
|
||||
if !exists {
|
||||
return CurrencyWarsRoleVariant{}, fmt.Errorf("CW role %d star %d has not been captured", roleID, star)
|
||||
}
|
||||
role.Config.TraitList = append([]uint32(nil), role.Config.TraitList...)
|
||||
role.Config.BackendRankList = append([]uint32(nil), role.Config.BackendRankList...)
|
||||
role.Config.ChargeType = append([]uint32(nil), role.Config.ChargeType...)
|
||||
role.StarConfig = append(json.RawMessage(nil), role.StarConfig...)
|
||||
role.ServantStarConfig = append(json.RawMessage(nil), role.ServantStarConfig...)
|
||||
return role, nil
|
||||
}
|
||||
|
||||
// Native special roles can have a sale quote different from the rarity array.
|
||||
// Return only an observed quote, with run modifiers/refunds left to the caller.
|
||||
func (c *CurrencyWarsCatalog) CapturedSalePrice(roleID, star uint32) (uint32, error) {
|
||||
role, err := c.CapturedRoleVariant(roleID, star)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if role.SaleQuoteKnown != nil && !*role.SaleQuoteKnown {
|
||||
return 0, fmt.Errorf("CW role %d star %d sale quote has not been established", roleID, star)
|
||||
}
|
||||
return role.SellPrice, nil
|
||||
}
|
||||
Reference in new issue
Block a user