121 lines
3.3 KiB
Go
121 lines
3.3 KiB
Go
package common
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"strconv"
|
||
|
|
)
|
||
|
|
|
||
|
|
type CurrencyWarsWeeklyRank struct {
|
||
|
|
Rank uint32 `json:"rank"`
|
||
|
|
Score uint32 `json:"score"`
|
||
|
|
Reward uint32 `json:"reward"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type CurrencyWarsScoreDivision struct {
|
||
|
|
Rule uint32 `json:"rule"`
|
||
|
|
OCRule uint32 `json:"oc_rule"`
|
||
|
|
WeeklyModify uint32 `json:"weekly_modify"`
|
||
|
|
ExpModify uint32 `json:"exp_modify"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type CurrencyWarsScoreNode struct {
|
||
|
|
Chapter uint32 `json:"chapter"`
|
||
|
|
Section uint32 `json:"section"`
|
||
|
|
Weekly uint32 `json:"weekly"`
|
||
|
|
Exp uint32 `json:"exp"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type CurrencyWarsOfferingLevel struct {
|
||
|
|
Level uint32 `json:"level"`
|
||
|
|
ItemCost uint32 `json:"item_cost"`
|
||
|
|
RewardID uint32 `json:"reward_id"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type CurrencyWarsScore struct {
|
||
|
|
FormatVersion uint32 `json:"format_version"`
|
||
|
|
TargetClientVersion string `json:"target_client_version"`
|
||
|
|
TargetAssemblySHA256 string `json:"target_assembly_sha256"`
|
||
|
|
WeeklyCap uint32 `json:"weekly_cap"`
|
||
|
|
WeeklyRanks []CurrencyWarsWeeklyRank `json:"weekly_ranks"`
|
||
|
|
Divisions map[string]CurrencyWarsScoreDivision `json:"divisions"`
|
||
|
|
Rules map[string][]CurrencyWarsScoreNode `json:"rules"`
|
||
|
|
OfferingLevels []CurrencyWarsOfferingLevel `json:"offering_levels"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func LoadCurrencyWarsScore(catalog *CurrencyWarsCatalog) (*CurrencyWarsScore, error) {
|
||
|
|
raw, err := ReadResourceFile("resources/CurrencyWarsScore.json")
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
var out CurrencyWarsScore
|
||
|
|
if err = json.Unmarshal(raw, &out); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if catalog != nil {
|
||
|
|
if out.FormatVersion != 1 || out.TargetClientVersion != catalog.ClientVersion || out.TargetAssemblySHA256 != catalog.Provenance.GameAssemblySHA256 {
|
||
|
|
return nil, fmt.Errorf("CW score revision differs from catalog")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return &out, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *CurrencyWarsScore) CalculateRunScore(divisionID uint32, isOverclock bool, chapter, section uint32, isWon bool) (weeklyScore, expBase, expExtra uint32) {
|
||
|
|
if s == nil {
|
||
|
|
return 0, 0, 0
|
||
|
|
}
|
||
|
|
divKey := strconv.FormatUint(uint64(divisionID), 10)
|
||
|
|
div, exists := s.Divisions[divKey]
|
||
|
|
if !exists {
|
||
|
|
return 0, 0, 0
|
||
|
|
}
|
||
|
|
rule := div.Rule
|
||
|
|
if isOverclock && div.OCRule != 0 {
|
||
|
|
rule = div.OCRule
|
||
|
|
}
|
||
|
|
ruleKey := strconv.FormatUint(uint64(rule), 10)
|
||
|
|
nodes, exists := s.Rules[ruleKey]
|
||
|
|
if !exists || len(nodes) == 0 {
|
||
|
|
return 0, 0, 0
|
||
|
|
}
|
||
|
|
here := chapter*100 + section
|
||
|
|
var best *CurrencyWarsScoreNode
|
||
|
|
for i := range nodes {
|
||
|
|
n := &nodes[i]
|
||
|
|
at := n.Chapter*100 + n.Section
|
||
|
|
if at < here || (isWon && at == here) {
|
||
|
|
best = n
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if best == nil {
|
||
|
|
return 0, 0, 0
|
||
|
|
}
|
||
|
|
weeklyMod := div.WeeklyModify
|
||
|
|
if weeklyMod == 0 {
|
||
|
|
weeklyMod = 100
|
||
|
|
}
|
||
|
|
weeklyScore = (best.Weekly * weeklyMod) / 100
|
||
|
|
expBase = best.Exp
|
||
|
|
if div.ExpModify > 100 {
|
||
|
|
expExtra = (best.Exp * (div.ExpModify - 100)) / 100
|
||
|
|
}
|
||
|
|
return weeklyScore, expBase, expExtra
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *CurrencyWarsScore) OfferingLevel(exp uint32) (level uint32, levelExp uint32) {
|
||
|
|
if s == nil || len(s.OfferingLevels) == 0 {
|
||
|
|
return 0, exp
|
||
|
|
}
|
||
|
|
left := exp
|
||
|
|
for _, row := range s.OfferingLevels {
|
||
|
|
if row.ItemCost == 0 {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if left < row.ItemCost {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
left -= row.ItemCost
|
||
|
|
level = row.Level
|
||
|
|
}
|
||
|
|
return level, left
|
||
|
|
}
|