mirror of
https://github.com/araxiaonline/wow-item-generator.git
synced 2026-06-13 03:02:22 -04:00
updated formulas to make legenday items scale from mythic. Adjusted level requirements and added random prefix by tier
This commit is contained in:
465264
data/legend-scaled.sql
465264
data/legend-scaled.sql
File diff suppressed because it is too large
Load Diff
1801073
data/mythic-scaled.sql
1801073
data/mythic-scaled.sql
File diff suppressed because it is too large
Load Diff
Binary file not shown.
10
internal/config/itemLevels.go
Normal file
10
internal/config/itemLevels.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package config
|
||||
|
||||
var MythicItemLevelStart = 300
|
||||
var MythicItemLevelEnd = 340
|
||||
|
||||
var LegendaryItemLevelStart = 340
|
||||
var LegendaryItemLevelEnd = 379
|
||||
|
||||
var AscendantItemLevelStart = 380
|
||||
var AscendantItemLevelEnd = 419
|
||||
@@ -11,7 +11,7 @@ var InvTypeModifiers = map[int]float64{
|
||||
9: 0.437, // Wrists
|
||||
10: 0.625, // Hands
|
||||
11: 1.0, // Finger
|
||||
13: 0.42, // One-Hand (not to confuse with Off-Hand = 22)
|
||||
13: 0.62, // One-Hand (not to confuse with Off-Hand = 22)
|
||||
14: 0.66, // Shield (class = armor, not weapon even if in weapon slot)
|
||||
15: 0.32, // Ranged (Bows) (see also Ranged right = 26)
|
||||
16: 0.66, // Back
|
||||
@@ -19,7 +19,7 @@ var InvTypeModifiers = map[int]float64{
|
||||
18: 1.0, // Bag (assuming same as Chest for simplicity)
|
||||
19: 1.0, // Tabard (assuming same as Chest for simplicity)
|
||||
20: 1.0, // Robe (see also Chest = 5)
|
||||
21: 0.85, // Main hand
|
||||
21: 0.80, // Main hand
|
||||
22: 0.42, // Off Hand weapons (see also One-Hand = 13)
|
||||
23: 0.56, // Held in Off-Hand (class = armor, not weapon even if in weapon slot)
|
||||
24: 1.0, // Ammo (assuming same as Chest for simplicity)
|
||||
@@ -95,36 +95,36 @@ var StatModifiers = map[int]float64{
|
||||
var ScalingFactor = map[int]float64{
|
||||
0: 1.1, // ITEM_MOD_MANA
|
||||
1: 1.5, // ITEM_MOD_HEALTH
|
||||
3: 1.2, // ITEM_MOD_AGILITY
|
||||
4: 1.2, // ITEM_MOD_STRENGTH
|
||||
5: 1.2, // ITEM_MOD_INTELLECT
|
||||
6: 1.3, // ITEM_MOD_SPIRIT
|
||||
7: 1.85, // ITEM_MOD_STAMINA
|
||||
12: 1.1, // ITEM_MOD_DEFENSE_SKILL_RATING
|
||||
13: 1.1, // ITEM_MOD_DODGE_RATING
|
||||
14: 1.1, // ITEM_MOD_PARRY_RATING
|
||||
3: 1.30, // ITEM_MOD_AGILITY
|
||||
4: 1.30, // ITEM_MOD_STRENGTH
|
||||
5: 1.30, // ITEM_MOD_INTELLECT
|
||||
6: 1.30, // ITEM_MOD_SPIRIT
|
||||
7: 1.75, // ITEM_MOD_STAMINA
|
||||
12: 1.2, // ITEM_MOD_DEFENSE_SKILL_RATING
|
||||
13: 1.15, // ITEM_MOD_DODGE_RATING
|
||||
14: 1.15, // ITEM_MOD_PARRY_RATING
|
||||
15: 1.1, // ITEM_MOD_BLOCK_RATING
|
||||
16: 1.1, // ITEM_MOD_HIT_MELEE_RATING
|
||||
17: 1.1, // ITEM_MOD_HIT_RANGED_RATING
|
||||
18: 1.1, // ITEM_MOD_HIT_SPELL_RATING
|
||||
19: 1.2, // ITEM_MOD_CRIT_MELEE_RATING
|
||||
20: 1.2, // ITEM_MOD_CRIT_RANGED_RATING
|
||||
21: 1.2, // ITEM_MOD_CRIT_SPELL_RATING
|
||||
21: 1.3, // ITEM_MOD_CRIT_SPELL_RATING
|
||||
22: 1.3, // ITEM_MOD_HIT_TAKEN_MELEE_RATING
|
||||
23: 1.3, // ITEM_MOD_HIT_TAKEN_RANGED_RATING
|
||||
24: 1.3, // ITEM_MOD_HIT_TAKEN_SPELL_RATING
|
||||
25: 1.3, // ITEM_MOD_CRIT_TAKEN_MELEE_RATING
|
||||
26: 1.3, // ITEM_MOD_CRIT_TAKEN_RANGED_RATING
|
||||
27: 1.3, // ITEM_MOD_CRIT_TAKEN_SPELL_RATING
|
||||
28: 1.15, // ITEM_MOD_HASTE_MELEE_RATING
|
||||
29: 1.15, // ITEM_MOD_HASTE_RANGED_RATING
|
||||
30: 1.15, // ITEM_MOD_HASTE_SPELL_RATING
|
||||
31: 1.1, // ITEM_MOD_HIT_RATING
|
||||
32: 1.25, // ITEM_MOD_CRIT_RATING
|
||||
28: 1.25, // ITEM_MOD_HASTE_MELEE_RATING
|
||||
29: 1.25, // ITEM_MOD_HASTE_RANGED_RATING
|
||||
30: 1.25, // ITEM_MOD_HASTE_SPELL_RATING
|
||||
31: 1.15, // ITEM_MOD_HIT_RATING
|
||||
32: 1.30, // ITEM_MOD_CRIT_RATING
|
||||
33: 1.3, // ITEM_MOD_HIT_TAKEN_RATING
|
||||
34: 1.3, // ITEM_MOD_CRIT_TAKEN_RATING
|
||||
35: 1.0, // ITEM_MOD_RESILIENCE_RATING
|
||||
36: 1.15, // ITEM_MOD_HASTE_RATING
|
||||
36: 1.25, // ITEM_MOD_HASTE_RATING
|
||||
37: 0.8, // ITEM_MOD_EXPERTISE_RATING
|
||||
38: 1.45, // ITEM_MOD_ATTACK_POWER
|
||||
39: 1.45, // ITEM_MOD_RANGED_ATTACK_POWER
|
||||
@@ -133,7 +133,7 @@ var ScalingFactor = map[int]float64{
|
||||
42: 1.4, // ITEM_MOD_SPELL_DAMAGE_DONE
|
||||
43: 1.3, // ITEM_MOD_MANA_REGENERATION
|
||||
44: 1.1, // ITEM_MOD_ARMOR_PENETRATION_RATING
|
||||
45: 1.5, // ITEM_MOD_SPELL_POWER
|
||||
45: 1.6, // ITEM_MOD_SPELL_POWER
|
||||
46: 1.3, // ITEM_MOD_HEALTH_REGEN
|
||||
47: 1.0, // ITEM_MOD_SPELL_PENETRATION
|
||||
48: 1.0, // ITEM_MOD_BLOCK_VALUE
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/config"
|
||||
)
|
||||
|
||||
type DbItem struct {
|
||||
@@ -80,6 +84,42 @@ func (db *MySqlDb) GetItem(entry int) (DbItem, error) {
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// Look up a mythic item by name
|
||||
func (db *MySqlDb) GetByNameAndDifficulty(name string, difficulty int) (DbItem, error) {
|
||||
item := DbItem{}
|
||||
var min, max int = 0, 0
|
||||
if difficulty == 0 {
|
||||
return DbItem{}, errors.New("difficulty cannot be 0")
|
||||
}
|
||||
|
||||
if difficulty == 3 {
|
||||
min = config.MythicItemLevelStart
|
||||
max = config.MythicItemLevelEnd
|
||||
}
|
||||
|
||||
if difficulty == 4 {
|
||||
min = config.LegendaryItemLevelStart
|
||||
max = config.LegendaryItemLevelEnd
|
||||
}
|
||||
|
||||
if difficulty == 5 {
|
||||
min = config.AscendantItemLevelStart
|
||||
max = config.AscendantItemLevelEnd
|
||||
}
|
||||
|
||||
// though levels are flexible I am going to assume here that mythics are between 300 to 340 these can be overriden in config
|
||||
sql := "SELECT " + GetItemFields("") + " FROM item_template WHERE name like ? and ItemLevel >= ? and ItemLevel < ? LIMIT 1"
|
||||
name = "%" + name
|
||||
err := db.Get(&item, sql, name, min, max)
|
||||
if err != nil {
|
||||
log.Printf("failed to get item: %v sql: %v", err, fmt.Sprintf("SELECT * FROM item_template WHERE name like %v and ItemLevel >= %v and ItemLevel < %v LIMIT 1", name, min, max))
|
||||
return DbItem{}, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// returns all items from item_template where the quality is between rare and legendary items
|
||||
func (db *MySqlDb) GetRarePlusItems(limit, offset int) ([]DbItem, error) {
|
||||
items := []DbItem{}
|
||||
sql := "SELECT " + GetItemFields("") + " FROM item_template WHERE Quality >= 3 and Quality <= 5 and (class = 2 or class = 4) "
|
||||
|
||||
@@ -52,12 +52,12 @@ func (db *SqlLite) GetRandItem(class, subclass int, statsList []int, end bool) (
|
||||
|
||||
// if we have a stats_list try to match by that first, if not then just select a random item from the class and subclass
|
||||
if len(statsList) == 0 {
|
||||
sql = "SELECT * FROM items WHERE class = ? and subclass = ? ORDER BY RANDOM() LIMIT 1"
|
||||
sql = "SELECT * FROM items WHERE class = ? and subclass = ? and itemLevel >= 240 ORDER BY RANDOM() LIMIT 1"
|
||||
err = db.Get(&rndItem, sql, class, subclass)
|
||||
} else {
|
||||
// convert the array of ints to a commas string for lookup
|
||||
statsTxt = intSliceToString(statsList)
|
||||
sql = "SELECT * FROM items WHERE class = ? and subclass = ? and stats_list like ? ORDER BY RANDOM() LIMIT 1"
|
||||
sql = "SELECT * FROM items WHERE class = ? and subclass = ? and stats_list and itemLevel >= 240 like ? ORDER BY RANDOM() LIMIT 1"
|
||||
err = db.Get(&rndItem, sql, class, subclass, statsTxt+"%")
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/config"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/mysql"
|
||||
@@ -24,6 +25,7 @@ type Item struct {
|
||||
StatsMap map[int]*ItemStat
|
||||
ConvStatCount int
|
||||
Spells []spells.Spell
|
||||
Difficulty int
|
||||
}
|
||||
|
||||
// Use for storing item stats for all stats that will be scaled.
|
||||
@@ -50,6 +52,14 @@ func ItemFromDbItem(dbItem mysql.DbItem) Item {
|
||||
}
|
||||
}
|
||||
|
||||
func (item Item) GetDifficulty() int {
|
||||
return item.Difficulty
|
||||
}
|
||||
|
||||
func (item *Item) SetDifficulty(difficulty int) {
|
||||
item.Difficulty = difficulty
|
||||
}
|
||||
|
||||
// Get the primary stat for an item (strength, agility, intellect, spirit, stamina)
|
||||
func (item Item) GetPrimaryStat() (int, int, error) {
|
||||
var primaryStat int64
|
||||
@@ -472,6 +482,7 @@ func (item *Item) ScaleItem(itemLevel int, itemQuality int) (bool, error) {
|
||||
}
|
||||
|
||||
allStats := item.GetStatPercents(allSpellStats)
|
||||
|
||||
for statId, stat := range allStats {
|
||||
origValue := stat.Value
|
||||
|
||||
@@ -484,13 +495,15 @@ func (item *Item) ScaleItem(itemLevel int, itemQuality int) (bool, error) {
|
||||
StatValue: stat.Value,
|
||||
}
|
||||
|
||||
stat.Value = scaleStatv3(scaleParams)
|
||||
stat.Value = scaleStatv3(scaleParams, item.GetDifficulty())
|
||||
// stat.Value = scaleStatv2(itemLevel, *item.InventoryType, *item.Quality, stat.Percent, config.StatModifiers[statId])
|
||||
|
||||
if statId == 45 && stat.Value < 100 {
|
||||
if statId == STAT.SpellPower && stat.Value < 100 {
|
||||
stat.Value = int(math.Round(float64(stat.Value) * 2.3785))
|
||||
}
|
||||
|
||||
correctSpellAttackPower(item, allStats)
|
||||
|
||||
log.Printf(">>>>>> Scaled : StatId: %v Type: %s Orig: %v - New Value: %v Percent: %v", statId, stat.Type, origValue, stat.Value, stat.Percent)
|
||||
}
|
||||
|
||||
@@ -718,7 +731,7 @@ func scaleStatv2(scaleParams StatScaleParams) int {
|
||||
return int(math.Ceil(scaledValue))
|
||||
}
|
||||
|
||||
func scaleStatv3(scaleParams StatScaleParams) int {
|
||||
func scaleStatv3(scaleParams StatScaleParams, difficulty int) int {
|
||||
// Calculate the quality and inventory type modifiers
|
||||
qualityModifier := config.QualityModifiers[scaleParams.Quality]
|
||||
// invTypeModifier := config.InvTypeModifiers[scaleParams.ItemType]
|
||||
@@ -727,12 +740,20 @@ func scaleStatv3(scaleParams StatScaleParams) int {
|
||||
baseScalingFactor := config.ScalingFactor[scaleParams.StatTypeId]
|
||||
|
||||
// Calculate the level ratio (new item level / original item level)
|
||||
levelRatio := float64(scaleParams.NewItemLevel) / float64(scaleParams.ItemLevel)
|
||||
levelRatio := float64(scaleParams.NewItemLevel) * 1.0795 / float64(scaleParams.ItemLevel)
|
||||
|
||||
// Apply the comprehensive scaling formula
|
||||
scaledValue := float64(scaleParams.StatValue) *
|
||||
math.Pow(levelRatio, baseScalingFactor) *
|
||||
qualityModifier
|
||||
math.Pow(levelRatio, baseScalingFactor)
|
||||
|
||||
if difficulty == 3 {
|
||||
scaledValue = scaledValue * qualityModifier
|
||||
} else {
|
||||
// Apply the legendary modifier only
|
||||
if scaleParams.Quality == 5 {
|
||||
scaledValue = scaledValue * 1.25
|
||||
}
|
||||
}
|
||||
|
||||
// // Log the details for debugging
|
||||
// log.Printf("------- scaledValue: %v, levelRatio: %v, qualityModifier: %v, baseScalingFactor: %v",
|
||||
@@ -742,8 +763,44 @@ func scaleStatv3(scaleParams StatScaleParams) int {
|
||||
return int(math.Ceil(scaledValue))
|
||||
}
|
||||
|
||||
// This will copy higher value of spell power and attack powers into one unit. This is to fix items that have both
|
||||
func correctSpellAttackPower(item *Item, allStats map[int]*ItemStat) {
|
||||
// do some manual corrections for stats oddly getting attack power and spell power
|
||||
itemStats, err := item.GetStatList()
|
||||
if err != nil {
|
||||
log.Printf("Failed to get stat list: %v not attempting to fix stats", err)
|
||||
}
|
||||
if slices.Contains(itemStats, STAT.AttackPower) && slices.Contains(itemStats, STAT.SpellPower) {
|
||||
|
||||
// if the Attack power is greater than spell power then add it spell power and remove spell power
|
||||
if allStats[STAT.AttackPower] != nil && allStats[STAT.SpellPower] != nil {
|
||||
if allStats[STAT.AttackPower].Value > allStats[STAT.SpellPower].Value {
|
||||
allStats[STAT.AttackPower].Value += allStats[STAT.SpellPower].Value
|
||||
delete(allStats, STAT.SpellPower)
|
||||
} else {
|
||||
allStats[STAT.SpellPower].Value += allStats[STAT.AttackPower].Value
|
||||
delete(allStats, STAT.AttackPower)
|
||||
}
|
||||
}
|
||||
}
|
||||
if slices.Contains(itemStats, STAT.RangedAttackPower) && slices.Contains(itemStats, STAT.SpellPower) {
|
||||
|
||||
if allStats[STAT.RangedAttackPower] != nil && allStats[STAT.SpellPower] != nil {
|
||||
if allStats[STAT.RangedAttackPower].Value > allStats[STAT.SpellPower].Value {
|
||||
allStats[STAT.RangedAttackPower].Value += allStats[STAT.SpellPower].Value
|
||||
delete(allStats, STAT.SpellPower)
|
||||
} else {
|
||||
allStats[STAT.SpellPower].Value += allStats[STAT.RangedAttackPower].Value
|
||||
delete(allStats, STAT.RangedAttackPower)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ItemToSql(item Item, reqLevel int, difficulty int) string {
|
||||
|
||||
fmt.Printf("-- Required level: %v\n", reqLevel)
|
||||
|
||||
var name string = item.Name
|
||||
|
||||
entryBump := 20000000
|
||||
@@ -756,6 +813,15 @@ func ItemToSql(item Item, reqLevel int, difficulty int) string {
|
||||
spellBump = 32000000
|
||||
}
|
||||
|
||||
if difficulty == 4 {
|
||||
entryBump = 21000000
|
||||
}
|
||||
if difficulty == 5 {
|
||||
entryBump = 22000000
|
||||
}
|
||||
|
||||
name = getRandomWord(difficulty) + " " + name
|
||||
|
||||
spellList := ""
|
||||
if len(item.Spells) > 0 {
|
||||
for i, spell := range item.Spells {
|
||||
@@ -876,3 +942,25 @@ func ItemToSql(item Item, reqLevel int, difficulty int) string {
|
||||
|
||||
return fmt.Sprintf("%s %s \n %s \n %s", spellList, delete, clone, update)
|
||||
}
|
||||
|
||||
func getRandomWord(difficulty int) string {
|
||||
mythic := []string{"Mythic", "Powerful", "Stalwart", "Venerated", "Mighty", "Unyielding"}
|
||||
legendary := []string{"Legendary", "Fabled", "Exalted", "Magnificent", "Pristine", "Supreme", "Glorious"}
|
||||
ascendant := []string{"Ascendant", "Godlike", "Celestial", "Transcendant", "Divine", "Omnipotent", "Demonforged", "Immortal", "Omniscient", "Ethereal"}
|
||||
|
||||
r := rand.New(rand.NewPCG(uint64(time.Now().UnixNano()), 2))
|
||||
|
||||
switch difficulty {
|
||||
case 3: // Mythic
|
||||
randomIndex := r.IntN(len(mythic))
|
||||
return mythic[randomIndex]
|
||||
case 4: // Legendary
|
||||
randomIndex := r.IntN(len(legendary))
|
||||
return legendary[randomIndex]
|
||||
case 5: // Ascendant
|
||||
randomIndex := r.IntN(len(ascendant))
|
||||
return ascendant[randomIndex]
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
95
internal/items/stat.go
Normal file
95
internal/items/stat.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package items
|
||||
|
||||
type stats struct {
|
||||
Mana int
|
||||
Health int
|
||||
Agility int
|
||||
Strength int
|
||||
Intellect int
|
||||
Spirit int
|
||||
Stamina int
|
||||
DefenseSkillRating int
|
||||
DodgeRating int
|
||||
ParryRating int
|
||||
BlockRating int
|
||||
HitMeleeRating int
|
||||
HitRangedRating int
|
||||
HitSpellRating int
|
||||
CritMeleeRating int
|
||||
CritRangedRating int
|
||||
CritSpellRating int
|
||||
HitTakenMeleeRating int
|
||||
HitTakenRangedRating int
|
||||
HitTakenSpellRating int
|
||||
CritTakenMeleeRating int
|
||||
CritTakenRangedRating int
|
||||
CritTakenSpellRating int
|
||||
HasteMeleeRating int
|
||||
HasteRangedRating int
|
||||
HasteSpellRating int
|
||||
HitRating int
|
||||
CritRating int
|
||||
HitTakenRating int
|
||||
CritTakenRating int
|
||||
ResilienceRating int
|
||||
HasteRating int
|
||||
ExpertiseRating int
|
||||
AttackPower int
|
||||
RangedAttackPower int
|
||||
FeralAttackPower int
|
||||
SpellHealingDone int
|
||||
SpellDamageDone int
|
||||
ManaRegeneration int
|
||||
ArmorPenetrationRating int
|
||||
SpellPower int
|
||||
HealthRegen int
|
||||
SpellPenetration int
|
||||
BlockValue int
|
||||
}
|
||||
|
||||
var STAT = stats{
|
||||
Mana: 0,
|
||||
Health: 1,
|
||||
Agility: 3,
|
||||
Strength: 4,
|
||||
Intellect: 5,
|
||||
Spirit: 6,
|
||||
Stamina: 7,
|
||||
DefenseSkillRating: 12,
|
||||
DodgeRating: 13,
|
||||
ParryRating: 14,
|
||||
BlockRating: 15,
|
||||
HitMeleeRating: 16,
|
||||
HitRangedRating: 17,
|
||||
HitSpellRating: 18,
|
||||
CritMeleeRating: 19,
|
||||
CritRangedRating: 20,
|
||||
CritSpellRating: 21,
|
||||
HitTakenMeleeRating: 22,
|
||||
HitTakenRangedRating: 23,
|
||||
HitTakenSpellRating: 24,
|
||||
CritTakenMeleeRating: 25,
|
||||
CritTakenRangedRating: 26,
|
||||
CritTakenSpellRating: 27,
|
||||
HasteMeleeRating: 28,
|
||||
HasteRangedRating: 29,
|
||||
HasteSpellRating: 30,
|
||||
HitRating: 31,
|
||||
CritRating: 32,
|
||||
HitTakenRating: 33,
|
||||
CritTakenRating: 34,
|
||||
ResilienceRating: 35,
|
||||
HasteRating: 36,
|
||||
ExpertiseRating: 37,
|
||||
AttackPower: 38,
|
||||
RangedAttackPower: 39,
|
||||
FeralAttackPower: 40,
|
||||
SpellHealingDone: 41,
|
||||
SpellDamageDone: 42,
|
||||
ManaRegeneration: 43,
|
||||
ArmorPenetrationRating: 44,
|
||||
SpellPower: 45,
|
||||
HealthRegen: 46,
|
||||
SpellPenetration: 47,
|
||||
BlockValue: 48,
|
||||
}
|
||||
145
main.go
145
main.go
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/config"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/mysql"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/sqlite"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/items"
|
||||
@@ -23,7 +24,6 @@ func main() {
|
||||
// database.models.Connect()
|
||||
|
||||
debug := flag.Bool("debug", false, "Enable verbose logging inside generator")
|
||||
itemLevel := flag.Int("ilvl", 300, "Specify the item level to start scaling from, expansion and difficulty modifiers scale up.")
|
||||
difficulty := flag.Int("difficulty", 3, "set the difficulty of the dungeon, defaults to 3 (mythic) 4 (legendary) 5 (ascendant)")
|
||||
// levelUp := flag.Bool("levelUp", false, "Boss items require higher +1 level to equip, defaults to false")
|
||||
baselevel := flag.Int("baselevel", 80, "set the base level for items to be used, defaults to 80 this is required for levelUp flag")
|
||||
@@ -34,16 +34,21 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if itemLevel == nil || *itemLevel < 280 {
|
||||
log.Fatal("item level must be greater than 280")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if baselevel == nil || *baselevel < 0 {
|
||||
log.Fatal("base level must be greater than 80")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var itemLevel *int = new(int)
|
||||
switch *difficulty {
|
||||
case 3:
|
||||
*itemLevel = config.MythicItemLevelStart
|
||||
case 4:
|
||||
*itemLevel = config.LegendaryItemLevelStart
|
||||
case 5:
|
||||
*itemLevel = config.AscendantItemLevelStart
|
||||
}
|
||||
|
||||
if *debug {
|
||||
log.SetOutput(os.Stdout)
|
||||
} else {
|
||||
@@ -68,60 +73,84 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Get all rare items int the acore_world.item_template that are rare or higher quality
|
||||
rareItems, err := mysqlDb.GetRarePlusItems(0, 0)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// do scaling and write sql for all items that are processed from the rareItems list
|
||||
for itr, dbItem := range rareItems {
|
||||
|
||||
// convert from a dbModel item to Item entity
|
||||
item := items.ItemFromDbItem(dbItem)
|
||||
|
||||
// the lookup Item is a check to see if the item comes from a dungeon on higher difficulties (4,5) we only process dungeon items
|
||||
lookupItem, err := sqliteDb.GetItemFromDungeon(item.Entry)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "no rows in result set") {
|
||||
log.Printf("failed to lookup item %v from dungeon: %v", item.Entry, err)
|
||||
}
|
||||
}
|
||||
log.Printf("Lookup %v", lookupItem)
|
||||
// skip items not from a dungeon on higher difficulties
|
||||
if *difficulty > 3 {
|
||||
if lookupItem.Entry == 0 {
|
||||
log.Printf("Item %v Entry: %v is not from a dungeon\n", item.Name, item.Entry)
|
||||
continue
|
||||
} else {
|
||||
log.Printf("Item %v Entry: %v is from a dungeon\n", item.Name, item.Entry)
|
||||
}
|
||||
}
|
||||
|
||||
// if it is a rare item then we need to scale it up to epic
|
||||
if *item.Quality < 5 {
|
||||
*item.Quality = 4
|
||||
}
|
||||
|
||||
statsList, err := item.GetStatList()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("Item: %v Entry: %v StatsList: %v\n", item.Name, item.Entry, statsList)
|
||||
rndItem, err := sqliteDb.GetRandItem(*item.Class, *item.Subclass, statsList, false)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if rndItem == (sqlite.HighLevelItem{}) {
|
||||
log.Fatalf("Failed to get random item for %v Entry: %v\n", item.Name, item.Entry)
|
||||
}
|
||||
log.Printf("Item: %v Entry: %v StatsList: %v\n", item.Name, item.Entry, statsList)
|
||||
|
||||
log.Printf("Random Item: %v Entry: %v\n", rndItem.Name, rndItem.Entry)
|
||||
var highLevelItem mysql.DbItem
|
||||
if *difficulty == 3 {
|
||||
rndItem, err := sqliteDb.GetRandItem(*item.Class, *item.Subclass, statsList, false)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
|
||||
highLevelItem, err := mysqlDb.GetItem(rndItem.Entry)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
continue
|
||||
}
|
||||
if rndItem == (sqlite.HighLevelItem{}) {
|
||||
log.Fatalf("Failed to get random item for %v Entry: %v\n", item.Name, item.Entry)
|
||||
}
|
||||
|
||||
// Take the high level item that has been selected for stats and remap to current item
|
||||
log.Printf("Random Item: %v Entry: %v\n", rndItem.Name, rndItem.Entry)
|
||||
|
||||
// Now apply logic build out the different difficulties and item levels based on source of item
|
||||
lookupItem, err := sqliteDb.GetItemFromDungeon(item.Entry)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "no rows in result set") {
|
||||
log.Fatalf("failed to lookup item %v from dungeon: %v", item.Entry, err)
|
||||
// Take the high level item that has been selected for stats and remap to current item
|
||||
highLevelItem, err = mysqlDb.GetItem(rndItem.Entry)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
|
||||
highLevelItem, err = mysqlDb.GetByNameAndDifficulty(item.Name, *difficulty-1)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Start at the item level and scale up based details about the source of the item
|
||||
// difficulty is used to tweak things in the scaling proces specifically modifiers so stats are not inflated twice by quality multiples
|
||||
item.SetDifficulty(*difficulty)
|
||||
|
||||
// if the item is from a dungeon and not a boss and is a craftable / world item so set to base level
|
||||
// if the item is not from a dungeon and we made it here, then just scale to mythic which can be used for weekly loot chests or new recipes.
|
||||
if lookupItem.Entry == 0 {
|
||||
|
||||
Scale(highLevelItem, &item, *itemLevel, 3)
|
||||
Scale(highLevelItem, &item, *itemLevel, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
continue
|
||||
}
|
||||
@@ -129,80 +158,92 @@ func main() {
|
||||
// if the item is from a dungeon and not a boss item
|
||||
if lookupItem.CreatureId == 0 {
|
||||
|
||||
if lookupItem.DungeonLevel < 60 {
|
||||
Scale(highLevelItem, &item, *itemLevel+5, 3)
|
||||
if lookupItem.DungeonLevel < 60 && lookupItem.Expansion == 0 {
|
||||
Scale(highLevelItem, &item, *itemLevel+5, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 60 && lookupItem.Expansion == 0 {
|
||||
Scale(highLevelItem, &item, *itemLevel+10, 3)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
Scale(highLevelItem, &item, *itemLevel+10, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+7, 3)
|
||||
Scale(highLevelItem, &item, *itemLevel+7, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+10, 3)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
Scale(highLevelItem, &item, *itemLevel+10, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+7, 3)
|
||||
Scale(highLevelItem, &item, *itemLevel+7, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+10, 3)
|
||||
Scale(highLevelItem, &item, *itemLevel+10, *item.Quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
}
|
||||
} else {
|
||||
|
||||
var finalBonus int = 0
|
||||
var quality int = 4
|
||||
// check if it is the final boss
|
||||
|
||||
// adjust qualities and levels required based on power and difficulty
|
||||
if mysql.IsFinalBoss(lookupItem.CreatureId) {
|
||||
fmt.Printf("-- Final Boss Item: %v Entry: %v difficulty %v\n", item.Name, item.Entry, *difficulty)
|
||||
finalBonus = 5
|
||||
|
||||
if *difficulty >= 4 {
|
||||
quality = 5
|
||||
}
|
||||
}
|
||||
|
||||
var reqLevel int
|
||||
if *difficulty == 4 || *difficulty == 5 {
|
||||
reqLevel = *baselevel + 5
|
||||
} else {
|
||||
reqLevel = *baselevel + 2
|
||||
}
|
||||
|
||||
// if the item is from a boss fight
|
||||
if lookupItem.DungeonLevel < 60 {
|
||||
if lookupItem.DungeonLevel < 60 && lookupItem.Expansion == 0 {
|
||||
Scale(highLevelItem, &item, *itemLevel+9+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
fmt.Print(items.ItemToSql(item, reqLevel-1, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 60 && lookupItem.Expansion == 0 {
|
||||
Scale(highLevelItem, &item, *itemLevel+17+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
Scale(highLevelItem, &item, *itemLevel+23+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, reqLevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+10+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
fmt.Print(items.ItemToSql(item, reqLevel-1, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+19+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
Scale(highLevelItem, &item, *itemLevel+23+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, reqLevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+12+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, reqLevel-1, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+22+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+3, *difficulty))
|
||||
Scale(highLevelItem, &item, *itemLevel+25+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, reqLevel, *difficulty))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n -- Item Updated: %v Entry: %v\n", item.Name, item.Entry)
|
||||
if itr >= 300 {
|
||||
// os.exit(0)
|
||||
// os.Exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user