package model import ( "math" "math/rand" ) // IlvlFactor returns L(ilvl) = 1 + 0.03 * max(0, ilvl - 1) per spec section 6.4. func IlvlFactor(ilvl int) float64 { d := ilvl - 1 if d < 0 { d = 0 } return 1.0 + 0.03*float64(d) } // RarityMultiplier returns M(rarity) per spec section 6.4.2. func RarityMultiplier(rarity Rarity) float64 { switch rarity { case RarityCommon: return 1.00 case RarityUncommon: return 1.12 case RarityRare: return 1.30 case RarityEpic: return 1.52 case RarityLegendary: return 1.78 default: return 1.00 } } // ScalePrimary computes primaryOut = round(basePrimary * L(ilvl) * M(rarity)). func ScalePrimary(basePrimary int, ilvl int, rarity Rarity) int { return int(math.Round(float64(basePrimary) * IlvlFactor(ilvl) * RarityMultiplier(rarity))) } // RollIlvl generates an item level from the monster level per spec section 6.4.5. // Base enemies: delta in {-1, 0, +1} uniform. // Elite enemies: delta in {0, +1, +2} with weights 0.4/0.4/0.2. func RollIlvl(monsterLevel int, isElite bool) int { var delta int if isElite { r := rand.Float64() switch { case r < 0.4: delta = 0 case r < 0.8: delta = 1 default: delta = 2 } } else { delta = rand.Intn(3) - 1 // -1, 0, or +1 } ilvl := monsterLevel + delta if ilvl < 1 { ilvl = 1 } return ilvl }