Files
GaCy-GO/internal/common/currency_wars_experience.go
T

57 lines
2.0 KiB
Go

package common
import "fmt"
// The action processor applies each crossed level's properties, capacity and
// shop weights together with this plan. It must not credit an EXP purchase
// separately from its gold/HP debit or persist only part of the level effects.
type CurrencyWarsExperiencePlan struct {
Level uint32
Exp uint32
Crossed []CurrencyWarsPlayerLevel
}
// PlanBaseExperience uses the captured thresholds before run modifiers.
// levelLimit is the resolved run limit, not a fallback to a normal-mode cap.
// Residual EXP at that limit is retained in the returned plan; callers must
// apply a separately established cap/reset policy before encoding the Client
// counter. This function does not guess that policy or spend any currency.
func (c *CurrencyWarsCatalog) PlanBaseExperience(level, exp, gain, levelLimit uint32) (CurrencyWarsExperiencePlan, error) {
var empty CurrencyWarsExperiencePlan
if c == nil || level == 0 || levelLimit < level {
return empty, fmt.Errorf("CW experience level/limit is invalid")
}
if _, err := c.PlayerLevel(levelLimit); err != nil {
return empty, fmt.Errorf("CW experience limit: %w", err)
}
current, err := c.PlayerLevel(level)
if err != nil {
return empty, err
}
if level < levelLimit && (current.LevelUpExp == 0 || exp >= current.LevelUpExp) {
return empty, fmt.Errorf("CW initial experience counter is not normalized")
}
plan := CurrencyWarsExperiencePlan{Level: level}
remaining := uint64(exp) + uint64(gain)
for plan.Level < levelLimit {
if current.LevelUpExp == 0 {
return empty, fmt.Errorf("CW level %d has no positive EXP threshold", plan.Level)
}
if remaining < uint64(current.LevelUpExp) {
break
}
remaining -= uint64(current.LevelUpExp)
plan.Level++
current, err = c.PlayerLevel(plan.Level)
if err != nil {
return empty, err
}
plan.Crossed = append(plan.Crossed, current)
}
if remaining > uint64(^uint32(0)) {
return empty, fmt.Errorf("CW experience counter overflows protocol uint32")
}
plan.Exp = uint32(remaining)
return plan, nil
}