mirror of
https://github.com/araxiaonline/wow-item-generator.git
synced 2026-06-13 03:02:22 -04:00
Tuned modifiers more and fixed bugs with how quality was being handled for legendaries
This commit is contained in:
@@ -9,20 +9,19 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/mysql"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/sqlite"
|
||||
"github.com/joho/godotenv"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
type DungeonItem struct {
|
||||
Entry int `db:"entry"`
|
||||
MapId int `db:"mapId"`
|
||||
CreatureId int `db:"creatureId"`
|
||||
Quality int `db:"Quality"`
|
||||
Expansion int `db:"expansion"`
|
||||
DungeonLevel int `db:"dungeonLevel"`
|
||||
}
|
||||
|
||||
func createTable(db *sql.DB) {
|
||||
|
||||
droptable := `DROP TABLE IF EXISTS dungeon_items`
|
||||
_, err := db.Exec(droptable)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
createTable := `CREATE TABLE IF NOT EXISTS dungeon_items (
|
||||
entry int unsigned NOT NULL DEFAULT '0',
|
||||
mapId tinyint unsigned NOT NULL DEFAULT '0',
|
||||
@@ -33,7 +32,7 @@ func createTable(db *sql.DB) {
|
||||
PRIMARY KEY (entry)
|
||||
)`
|
||||
|
||||
_, err := db.Exec(createTable)
|
||||
_, err = db.Exec(createTable)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -96,7 +95,7 @@ func main() {
|
||||
|
||||
for _, dungItem := range dbItems {
|
||||
|
||||
insertItem := DungeonItem{
|
||||
insertItem := sqlite.DungeonItem{
|
||||
Entry: dungItem.Entry,
|
||||
MapId: dungeon.Id,
|
||||
Quality: *dungItem.Quality,
|
||||
@@ -117,7 +116,7 @@ func main() {
|
||||
}
|
||||
|
||||
for _, dungItem := range dbItems {
|
||||
insertItem := DungeonItem{
|
||||
insertItem := sqlite.DungeonItem{
|
||||
Entry: dungItem.Entry,
|
||||
MapId: dungeon.Id,
|
||||
Quality: *dungItem.Quality,
|
||||
|
||||
@@ -52,7 +52,7 @@ func ConvertIntSliceToString(slice []int) string {
|
||||
|
||||
func main() {
|
||||
godotenv.Load("../../.env")
|
||||
liteDb, err := sql.Open("sqlite3", "./items.db")
|
||||
liteDb, err := sql.Open("sqlite3", "../../data/items.db")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -79,11 +79,12 @@ func main() {
|
||||
sql := `
|
||||
SELECT ` + mysql.GetItemFields("") + `
|
||||
from acore_world.item_template
|
||||
where ItemLevel >= 200 and Quality >= 3 and ItemLevel < 290
|
||||
where ItemLevel >= 220 and Quality >= 3 and ItemLevel < 290
|
||||
AND name NOT LIKE 'NPC Equip%' and name NOT LIKE 'OLD%'
|
||||
AND name NOT LIKE '%(test)%' AND name NOT LIKE '%Deprecated%'
|
||||
AND name NOT LIKE '%Monster - %'
|
||||
AND ((class = 2 and subclass IN(0,1,2,3,4,5,6,7,8,10,11,12,13,15,16,17,18,19)) or ((class = 4 AND subclass IN (0,1,2,3,4,6))))
|
||||
AND stat_type1 != 32 AND stat_type2 != 32 AND stat_type3 != 32 AND stat_type4 != 32 AND stat_type5 != 32 AND stat_type6 != 32 AND stat_type7 != 32 AND stat_type8 != 32 AND stat_type9 != 32 AND stat_type10 != 32
|
||||
`
|
||||
err = mysqlDb.Select(&dbItems, sql)
|
||||
if err != nil {
|
||||
|
||||
@@ -12,14 +12,14 @@ var InvTypeModifiers = map[int]float64{
|
||||
10: 0.625, // Hands
|
||||
11: 1.0, // Finger
|
||||
13: 0.42, // One-Hand (not to confuse with Off-Hand = 22)
|
||||
14: 0.56, // Shield (class = armor, not weapon even if in weapon slot)
|
||||
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.56, // Back
|
||||
16: 0.66, // Back
|
||||
17: 1.0, // Two-Hand
|
||||
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: 1.0, // Main hand
|
||||
21: 0.85, // 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)
|
||||
@@ -29,12 +29,12 @@ var InvTypeModifiers = map[int]float64{
|
||||
}
|
||||
|
||||
var QualityModifiers = map[int]float64{
|
||||
0: 1.0, // Common
|
||||
1: 1.1, // Uncommon
|
||||
2: 1.2, // Rare
|
||||
3: 1.3, // Epic
|
||||
4: 1.5, // Legendary
|
||||
5: 1.7, // Artifact
|
||||
0: 0.8, // Poor
|
||||
1: 0.9, // Common
|
||||
2: 1.0, // UnCommon
|
||||
3: 1.2, // Rare
|
||||
4: 1.4, // Epic
|
||||
5: 5.0, // Legendary
|
||||
}
|
||||
|
||||
var MaterialModifiers = map[int]float64{
|
||||
@@ -93,48 +93,48 @@ var StatModifiers = map[int]float64{
|
||||
}
|
||||
|
||||
var ScalingFactor = map[int]float64{
|
||||
0: 1.1, // ITEM_MOD_MANA
|
||||
1: 1.1, // ITEM_MOD_HEALTH
|
||||
3: 1.1, // ITEM_MOD_AGILITY
|
||||
4: 1.1, // ITEM_MOD_STRENGTH
|
||||
5: 1.1, // ITEM_MOD_INTELLECT
|
||||
6: 1.1, // ITEM_MOD_SPIRIT
|
||||
7: 2.0, // 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
|
||||
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.1, // ITEM_MOD_CRIT_MELEE_RATING
|
||||
20: 1.1, // ITEM_MOD_CRIT_RANGED_RATING
|
||||
21: 1.1, // ITEM_MOD_CRIT_SPELL_RATING
|
||||
22: 1.1, // ITEM_MOD_HIT_TAKEN_MELEE_RATING
|
||||
23: 1.1, // ITEM_MOD_HIT_TAKEN_RANGED_RATING
|
||||
24: 1.1, // ITEM_MOD_HIT_TAKEN_SPELL_RATING
|
||||
25: 1.1, // ITEM_MOD_CRIT_TAKEN_MELEE_RATING
|
||||
26: 1.1, // ITEM_MOD_CRIT_TAKEN_RANGED_RATING
|
||||
27: 1.1, // ITEM_MOD_CRIT_TAKEN_SPELL_RATING
|
||||
28: 1.1, // ITEM_MOD_HASTE_MELEE_RATING
|
||||
29: 1.1, // ITEM_MOD_HASTE_RANGED_RATING
|
||||
30: 1.1, // ITEM_MOD_HASTE_SPELL_RATING
|
||||
31: 1.1, // ITEM_MOD_HIT_RATING
|
||||
32: 1.1, // ITEM_MOD_CRIT_RATING
|
||||
33: 1.1, // ITEM_MOD_HIT_TAKEN_RATING
|
||||
34: 1.1, // ITEM_MOD_CRIT_TAKEN_RATING
|
||||
35: 1.1, // ITEM_MOD_RESILIENCE_RATING
|
||||
36: 1.1, // ITEM_MOD_HASTE_RATING
|
||||
37: 1.1, // ITEM_MOD_EXPERTISE_RATING
|
||||
38: 1.5, // ITEM_MOD_ATTACK_POWER
|
||||
39: 1.1, // ITEM_MOD_RANGED_ATTACK_POWER
|
||||
40: 1.1, // ITEM_MOD_FERAL_ATTACK_POWER (not used as of 3.3)
|
||||
41: 1.7, // ITEM_MOD_SPELL_HEALING_DONE
|
||||
42: 1.7, // ITEM_MOD_SPELL_DAMAGE_DONE
|
||||
43: 1.5, // ITEM_MOD_MANA_REGENERATION
|
||||
44: 1.0, // ITEM_MOD_ARMOR_PENETRATION_RATING
|
||||
45: 1.7, // ITEM_MOD_SPELL_POWER
|
||||
46: 1.1, // ITEM_MOD_HEALTH_REGEN
|
||||
47: 1.0, // ITEM_MOD_SPELL_PENETRATION
|
||||
48: 1.1, // ITEM_MOD_BLOCK_VALUE
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
37: 0.8, // ITEM_MOD_EXPERTISE_RATING
|
||||
38: 1.45, // ITEM_MOD_ATTACK_POWER
|
||||
39: 1.45, // ITEM_MOD_RANGED_ATTACK_POWER
|
||||
40: 1.45, // ITEM_MOD_FERAL_ATTACK_POWER (not used as of 3.3)
|
||||
41: 1.4, // ITEM_MOD_SPELL_HEALING_DONE
|
||||
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
|
||||
46: 1.3, // ITEM_MOD_HEALTH_REGEN
|
||||
47: 1.0, // ITEM_MOD_SPELL_PENETRATION
|
||||
48: 1.0, // ITEM_MOD_BLOCK_VALUE
|
||||
}
|
||||
|
||||
@@ -12,6 +12,70 @@ type Boss struct {
|
||||
ExperienceModifier int `db:"ExperienceModifier"`
|
||||
}
|
||||
|
||||
var BossIDs = map[int]bool{
|
||||
11520: true, // Taragaman the Hungerer (Ragefire Chasm)
|
||||
3654: true, // Mutanus the Devourer (Wailing Caverns)
|
||||
639: true, // Edwin VanCleef (The Deadmines)
|
||||
4275: true, // Archmage Arugal (Shadowfang Keep)
|
||||
4829: true, // Aku'mai (Blackfathom Deeps)
|
||||
1716: true, // Bazil Thredd (Stormwind Stockade)
|
||||
7800: true, // Mekgineer Thermaplugg (Gnomeregan)
|
||||
4421: true, // Charlga Razorflank (Razorfen Kraul)
|
||||
4543: true, // Bloodmage Thalnos (Scarlet Monastery Graveyard)
|
||||
6487: true, // Arcanist Doan (Scarlet Monastery Library)
|
||||
3975: true, // Herod (Scarlet Monastery Armory)
|
||||
3977: true, // High Inquisitor Whitemane (Scarlet Monastery Cathedral)
|
||||
7358: true, // Amnennar the Coldbringer (Razorfen Downs)
|
||||
2748: true, // Archaedas (Uldaman)
|
||||
7267: true, // Chief Ukorz Sandscalp (Zul'Farrak)
|
||||
12201: true, // Princess Theradras (Maraudon)
|
||||
8443: true, // Avatar of Hakkar (Sunken Temple)
|
||||
9019: true, // Emperor Dagran Thaurissan (Blackrock Depths)
|
||||
9568: true, // Overlord Wyrmthalak (Lower Blackrock Spire)
|
||||
10363: true, // General Drakkisath (Upper Blackrock Spire)
|
||||
11492: true, // Alzzin the Wildshaper (Dire Maul East)
|
||||
11489: true, // Tendris Warpwood (Dire Maul West)
|
||||
11501: true, // King Gordok (Dire Maul North)
|
||||
10440: true, // Baron Rivendare (Stratholme Undead Side)
|
||||
10813: true, // Balnazzar (Stratholme Live Side)
|
||||
1853: true, // Darkmaster Gandling (Scholomance)
|
||||
|
||||
17307: true, // Vazruden (Hellfire Ramparts)
|
||||
17536: true, // Nazan (Hellfire Ramparts)
|
||||
17377: true, // Keli'dan the Breaker (The Blood Furnace)
|
||||
16808: true, // Warchief Kargath Bladefist (The Shattered Halls)
|
||||
17942: true, // Quagmirran (The Slave Pens)
|
||||
17826: true, // Swamplord Musel'ek (The Underbog)
|
||||
17798: true, // Warlord Kalithresh (The Steamvault)
|
||||
18344: true, // Nexus-Prince Shaffar (Mana-Tombs)
|
||||
18373: true, // Exarch Maladaar (Auchenai Crypts)
|
||||
18473: true, // Talon King Ikiss (Sethekk Halls)
|
||||
18708: true, // Murmur (Shadow Labyrinth)
|
||||
19220: true, // Pathaleon the Calculator (The Mechanar)
|
||||
17977: true, // Warp Splinter (The Botanica)
|
||||
20912: true, // Harbinger Skyriss (The Arcatraz)
|
||||
17881: true, // Aeonus (The Black Morass)
|
||||
18096: true, // Epoch Hunter (Old Hillsbrad Foothills)
|
||||
24664: true, // Kael'thas Sunstrider (Magisters' Terrace)
|
||||
|
||||
23954: true, // Ingvar the Plunderer (Utgarde Keep)
|
||||
26723: true, // Keristrasza (The Nexus)
|
||||
29120: true, // Anub'arak (Azjol-Nerub)
|
||||
29311: true, // Herald Volazj (Ahn'kahet: The Old Kingdom)
|
||||
26632: true, // The Prophet Tharon'ja (Drak'Tharon Keep)
|
||||
31134: true, // Cyanigosa (Violet Hold)
|
||||
29306: true, // Gal'darah (Gundrak)
|
||||
27978: true, // Sjonnir the Ironshaper (Halls of Stone)
|
||||
28923: true, // Loken (Halls of Lightning)
|
||||
27656: true, // Ley-Guardian Eregos (The Oculus)
|
||||
26533: true, // Mal'Ganis (Culling of Stratholme)
|
||||
26861: true, // King Ymiron (Utgarde Pinnacle)
|
||||
35451: true, // The Black Knight (Trial of the Champion)
|
||||
36502: true, // Devourer of Souls (Forge of Souls)
|
||||
36658: true, // Scourgelord Tyrannus (Pit of Saron)
|
||||
37226: true, // The Lich King (Halls of Reflection)
|
||||
}
|
||||
|
||||
func (db *MySqlDb) GetBosses(mapId int) ([]Boss, error) {
|
||||
|
||||
if mapId == 0 {
|
||||
@@ -101,3 +165,7 @@ func (db *MySqlDb) GetBossLoot(bossId int) ([]DbItem, error) {
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func IsFinalBoss(bossId int) bool {
|
||||
return BossIDs[bossId]
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ func (db *MySqlDb) GetItem(entry int) (DbItem, error) {
|
||||
|
||||
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)"
|
||||
sql := "SELECT " + GetItemFields("") + " FROM item_template WHERE Quality >= 3 and Quality <= 5 and (class = 2 or class = 4) "
|
||||
sql += "and subclass != 20 AND entry < 20000000 ORDER BY entry ASC"
|
||||
|
||||
if limit != 0 && offset != 0 {
|
||||
sql += fmt.Sprintf("LIMIT %v OFFSET %v", limit, offset)
|
||||
|
||||
@@ -19,6 +19,15 @@ type HighLevelItem struct {
|
||||
StatsList string `db:"stats_list"`
|
||||
}
|
||||
|
||||
type DungeonItem struct {
|
||||
Entry int `db:"entry"`
|
||||
MapId int `db:"mapId"`
|
||||
CreatureId int `db:"creatureId"`
|
||||
Quality int `db:"Quality"`
|
||||
Expansion int `db:"expansion"`
|
||||
DungeonLevel int `db:"dungeonLevel"`
|
||||
}
|
||||
|
||||
func (db *SqlLite) GetItem(entry int) (HighLevelItem, error) {
|
||||
if entry == 0 {
|
||||
return HighLevelItem{}, fmt.Errorf("entry cannot be 0")
|
||||
@@ -79,6 +88,18 @@ func (db *SqlLite) GetRandItem(class, subclass int, statsList []int, end bool) (
|
||||
return rndItem, nil
|
||||
}
|
||||
|
||||
func (db *SqlLite) GetItemFromDungeon(itemEntry int) (DungeonItem, error) {
|
||||
item := DungeonItem{}
|
||||
sql := "SELECT * FROM dungeon_items WHERE entry = ?"
|
||||
|
||||
err := db.Get(&item, sql, itemEntry)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func intSliceToString(slice []int) string {
|
||||
str := fmt.Sprint(slice)
|
||||
str = strings.Trim(str, "[]")
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"math/rand/v2"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/config"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/mysql"
|
||||
@@ -151,12 +152,12 @@ func (i Item) GetDpsModifier() (float64, error) {
|
||||
typeModifier := 0.0
|
||||
// Is a One-Handed Weapon
|
||||
if *i.Subclass == 0 || *i.Subclass == 4 || *i.Subclass == 13 || *i.Subclass == 15 || *i.Subclass == 7 {
|
||||
typeModifier = 0.64
|
||||
typeModifier = 0.58
|
||||
}
|
||||
|
||||
// Is a Two-Handed Weapon
|
||||
if *i.Subclass == 1 || *i.Subclass == 5 || *i.Subclass == 6 || *i.Subclass == 8 || *i.Subclass == 10 || *i.Subclass == 17 {
|
||||
typeModifier = 0.80
|
||||
typeModifier = 0.85
|
||||
}
|
||||
|
||||
// Ranged Weapons
|
||||
@@ -172,15 +173,7 @@ func (i Item) GetDpsModifier() (float64, error) {
|
||||
qualityModifier := 1.0
|
||||
|
||||
// Add the quality modifier for the DPS calculation
|
||||
if *i.Quality == 2 {
|
||||
qualityModifier = 1.25
|
||||
}
|
||||
if *i.Quality == 3 {
|
||||
qualityModifier = 1.38
|
||||
}
|
||||
if *i.Quality == 4 {
|
||||
qualityModifier = 1.5
|
||||
}
|
||||
qualityModifier = config.QualityModifiers[*i.Quality]
|
||||
|
||||
if typeModifier == 0 {
|
||||
return 0, fmt.Errorf("Item subclass is not a weapon %v", *i.Subclass)
|
||||
@@ -221,17 +214,14 @@ func (item *Item) ScaleDPS(oldLevel, level int) (float64, error) {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
scalingFactor := math.Pow(float64(level)/float64(oldLevel), 1.1)
|
||||
scalingFactor := math.Pow(float64(level)/float64(oldLevel), 1.012)
|
||||
|
||||
dps := modifier * float64(level) * scalingFactor
|
||||
adjDps := (dps * (*item.Delay / 1000) / 100)
|
||||
|
||||
//(((Y8*Y4)/100))*((100 - Y5)) Forumula from Weapon Item Genertor
|
||||
minimum := adjDps * float64(100-(rand.IntN(25)+22))
|
||||
maximum := adjDps * float64(100+(rand.IntN(25)+28))
|
||||
|
||||
minimum = math.Ceil(minimum)
|
||||
maximum = math.Ceil(maximum)
|
||||
minimum := adjDps * float64(100-(rand.IntN(15)+22))
|
||||
maximum := adjDps * float64(100+(rand.IntN(15)+28))
|
||||
|
||||
// If the weapon has secondary damage, scale that as well based on the ratio of the primary damage
|
||||
if *item.MinDmg2 != 0 && *item.MaxDmg2 != 0 {
|
||||
@@ -240,6 +230,9 @@ func (item *Item) ScaleDPS(oldLevel, level int) (float64, error) {
|
||||
minimum2 := ratioMin * float64(minimum)
|
||||
maximum2 := ratioMax * float64(maximum)
|
||||
|
||||
minimum2 = math.Ceil(minimum2)
|
||||
maximum2 = math.Ceil(maximum2)
|
||||
|
||||
item.MinDmg2 = &minimum2
|
||||
item.MaxDmg2 = &maximum2
|
||||
|
||||
@@ -248,6 +241,9 @@ func (item *Item) ScaleDPS(oldLevel, level int) (float64, error) {
|
||||
maximum = maximum - float64(maximum2)*0.85
|
||||
}
|
||||
|
||||
minimum = math.Ceil(minimum)
|
||||
maximum = math.Ceil(maximum)
|
||||
|
||||
// item.MinDmg1 = &minimum
|
||||
// var min int = int(minimum)
|
||||
// var max int = int(maximum)
|
||||
@@ -444,7 +440,7 @@ func (item *Item) ScaleItem(itemLevel int, itemQuality int) (bool, error) {
|
||||
*item.ItemLevel = itemLevel
|
||||
|
||||
// if an item quality is being forced than use it intead
|
||||
if itemQuality != 0 {
|
||||
if *item.Quality < itemQuality {
|
||||
*item.Quality = itemQuality
|
||||
}
|
||||
|
||||
@@ -469,6 +465,7 @@ func (item *Item) ScaleItem(itemLevel int, itemQuality int) (bool, error) {
|
||||
|
||||
if len(convStats) != 0 {
|
||||
item.UpdateField(fmt.Sprintf("SpellId%v", i+1), 0)
|
||||
item.UpdateField(fmt.Sprintf("SpellTrigger%v", i+1), 0)
|
||||
}
|
||||
|
||||
allSpellStats = append(allSpellStats, convStats...)
|
||||
@@ -859,6 +856,9 @@ func ItemToSql(item Item, reqLevel int, difficulty int) string {
|
||||
spellid_1 = %v,
|
||||
spellid_2 = %v,
|
||||
spellid_3 = %v,
|
||||
spelltrigger_1 = %v,
|
||||
spelltrigger_2 = %v,
|
||||
spelltrigger_3 = %v,
|
||||
socketColor_1 = %v,
|
||||
socketContent_1 = %v,
|
||||
socketColor_2 = %v,
|
||||
@@ -872,11 +872,12 @@ func ItemToSql(item Item, reqLevel int, difficulty int) string {
|
||||
SellPrice = FLOOR(100000 + (RAND() * 400001)),
|
||||
Armor = %v
|
||||
WHERE entry = %v;
|
||||
`, *item.Quality, name, *item.ItemLevel, reqLevel, *item.MinDmg1, *item.MaxDmg1, *item.MinDmg2, *item.MaxDmg2, *item.StatsCount,
|
||||
`, *item.Quality, strings.ReplaceAll(name, "'", "''"), *item.ItemLevel, reqLevel, *item.MinDmg1, *item.MaxDmg1, *item.MinDmg2, *item.MaxDmg2, *item.StatsCount,
|
||||
*item.StatType1, *item.StatValue1, *item.StatType2, *item.StatValue2, *item.StatType3, *item.StatValue3, *item.StatType4, *item.StatValue4,
|
||||
*item.StatType5, *item.StatValue5, *item.StatType6, *item.StatValue6, *item.StatType7, *item.StatValue7, *item.StatType8, *item.StatValue8,
|
||||
*item.StatType9, *item.StatValue9, *item.StatType10, *item.StatValue10, *item.SpellId1, *item.SpellId2, *item.SpellId3, *item.SocketColor1, *item.SocketContent1,
|
||||
*item.SocketColor2, *item.SocketContent2, *item.SocketColor3, *item.SocketContent3, *item.SocketBonus, *item.GemProperties,
|
||||
*item.StatType9, *item.StatValue9, *item.StatType10, *item.StatValue10, *item.SpellId1, *item.SpellId2, *item.SpellId3, *item.SpellTrigger1, *item.SpellTrigger2,
|
||||
*item.SpellTrigger3, *item.SocketColor1, *item.SocketContent1, *item.SocketColor2, *item.SocketContent2,
|
||||
*item.SocketColor3, *item.SocketContent3, *item.SocketBonus, *item.GemProperties,
|
||||
375, 68, *item.Armor, entryBump+item.Entry)
|
||||
|
||||
return fmt.Sprintf("%s %s \n %s \n %s", spellList, delete, clone, update)
|
||||
|
||||
228
main.go
228
main.go
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/mysql"
|
||||
"github.com/araxiaonline/endgame-item-generator/internal/db/sqlite"
|
||||
@@ -22,7 +23,7 @@ func main() {
|
||||
// database.models.Connect()
|
||||
|
||||
debug := flag.Bool("debug", false, "Enable verbose logging inside generator")
|
||||
itemLevel := flag.Int("ilvl", 305, "Specify the item level to start scaling from, expansion and difficulty modifiers scale up.")
|
||||
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")
|
||||
@@ -75,6 +76,11 @@ func main() {
|
||||
for itr, dbItem := range rareItems {
|
||||
item := items.ItemFromDbItem(dbItem)
|
||||
|
||||
// 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)
|
||||
@@ -84,7 +90,7 @@ func main() {
|
||||
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.Fatal(err)
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -100,131 +106,107 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Print all the status for the item that was copied
|
||||
// log.Printf("Item Name: %v Stat1: %v Stat2: %v Stat3: %v Stat4: %v Stat5: %v Stat6: %v Stat7: %v Stat8: %v \n",
|
||||
// item.Entry, *item.StatValue1, *item.StatValue2, *item.StatValue3, *item.StatValue4, *item.StatValue5, *item.StatValue6, *item.StatValue7, *item.StatValue8)
|
||||
// Take the high level item that has been selected for stats and remap to current item
|
||||
|
||||
item.ApplyStats(items.ItemFromDbItem(highLevelItem))
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
item.ScaleItem(*itemLevel, 3)
|
||||
// log.Printf("Item Name: %v Stat1: %v Stat2: %v Stat3: %v Stat4: %v Stat5: %v Stat6: %v Stat7: %v Stat8: %v \n",
|
||||
// item.Name, *item.StatValue1, *item.StatValue2, *item.StatValue3, *item.StatValue4, *item.StatValue5, *item.StatValue6, *item.StatValue7, *item.StatValue8)
|
||||
// Start at the item level and scale up based details about the source of the item
|
||||
|
||||
fmt.Print(items.ItemToSql(item, 80, 3))
|
||||
// if the item is from a dungeon and not a boss and is a craftable / world item so set to base level
|
||||
if lookupItem.Entry == 0 {
|
||||
|
||||
if itr > 600 {
|
||||
break
|
||||
Scale(highLevelItem, &item, *itemLevel, 3)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
continue
|
||||
}
|
||||
|
||||
// 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)
|
||||
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))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+7, 3)
|
||||
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))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+7, 3)
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+10, 3)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
}
|
||||
} else {
|
||||
|
||||
var finalBonus int = 0
|
||||
var quality int = 4
|
||||
// check if it is the final boss
|
||||
if mysql.IsFinalBoss(lookupItem.CreatureId) {
|
||||
finalBonus = 5
|
||||
quality = 5
|
||||
}
|
||||
// if the item is from a boss fight
|
||||
if lookupItem.DungeonLevel < 60 {
|
||||
Scale(highLevelItem, &item, *itemLevel+9+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 60 && lookupItem.Expansion == 0 {
|
||||
Scale(highLevelItem, &item, *itemLevel+17+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+10+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 70 && lookupItem.Expansion == 1 {
|
||||
Scale(highLevelItem, &item, *itemLevel+19+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+2, *difficulty))
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel < 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+12+finalBonus, quality)
|
||||
}
|
||||
|
||||
if lookupItem.DungeonLevel == 80 && lookupItem.Expansion == 2 {
|
||||
Scale(highLevelItem, &item, *itemLevel+22+finalBonus, quality)
|
||||
fmt.Print(items.ItemToSql(item, *baselevel+3, *difficulty))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n -- Item Updated: %v Entry: %v\n", item.Name, item.Entry)
|
||||
if itr >= 300 {
|
||||
// os.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// // main loop
|
||||
// dungeons, err := models.DB.GetDungeons(-1)
|
||||
// if err != nil {
|
||||
// log.Panicf("failed to get dungeons for expansion %v error: %v", 0, err)
|
||||
// }
|
||||
|
||||
// for _, dungeon := range dungeons {
|
||||
|
||||
// log.Printf("+++++Dungeon: %s ID: %v level %v \n", dungeon.Name, dungeon.Id, dungeon.Level)
|
||||
|
||||
// bosses, err := models.DB.GetBosses(dungeon.Id)
|
||||
// if err != nil {
|
||||
// log.Fatal("failed to get bosses")
|
||||
// }
|
||||
|
||||
// // Determine the scale value of the item based on expansion and dungeon level
|
||||
// scaleValue := *itemLevel
|
||||
// endGameDung := false
|
||||
// if dungeon.Level == 60 {
|
||||
// scaleValue += 10
|
||||
// endGameDung = true
|
||||
// }
|
||||
|
||||
// if dungeon.ExpansionId == 1 && dungeon.Level <= 70 {
|
||||
// scaleValue += 3
|
||||
// }
|
||||
|
||||
// if dungeon.ExpansionId == 1 && dungeon.Level == 70 {
|
||||
// scaleValue += 12
|
||||
// endGameDung = true
|
||||
// }
|
||||
|
||||
// if dungeon.ExpansionId == 2 && dungeon.Level <= 80 {
|
||||
// scaleValue += 4
|
||||
// }
|
||||
|
||||
// if dungeon.ExpansionId == 2 && dungeon.Level == 80 {
|
||||
// scaleValue += 15
|
||||
// endGameDung = true
|
||||
// }
|
||||
|
||||
// // Apply difficuly modifiers for gear scale
|
||||
// // mythic: Bosses-Epic Gear (Purple) drops and Rare (Blue) for random drops (BOE)
|
||||
// // legendary: Bosses-Epic Gear (Purple) drops and Epic (Purple) for random drops (BOE)
|
||||
// // ascendant: Bosses-Legendary Gear (Yellow) drops and Epic (Purple) for random drops (BOE)
|
||||
// var bossQuality int
|
||||
// var boeQuality int
|
||||
|
||||
// if *difficulty == 4 {
|
||||
// bossQuality = 4
|
||||
// boeQuality = 4
|
||||
// } else if *difficulty == 5 {
|
||||
// bossQuality = 5
|
||||
// boeQuality = 4
|
||||
// } else {
|
||||
// bossQuality = 4
|
||||
// boeQuality = 3
|
||||
// }
|
||||
|
||||
// for _, boss := range bosses {
|
||||
|
||||
// items, err := models.DB.GetBossLoot(boss.Entry)
|
||||
// log.Printf("++++++++++ Boss: %s Entry: %v has %v items\n", boss.Name, boss.Entry, len(items))
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// continue
|
||||
// }
|
||||
|
||||
// for _, item := range items {
|
||||
|
||||
// _, error := item.ScaleItem(scaleValue, bossQuality)
|
||||
// if error != nil {
|
||||
// log.Printf("Failed to scale item: %v", error)
|
||||
// continue
|
||||
// }
|
||||
|
||||
// fmt.Printf("\n-- Item %v Entry: %v ItemLevel %v \n", item.Name, item.Entry, *item.ItemLevel)
|
||||
// if *levelUp && endGameDung {
|
||||
// fmt.Print(ItemToSql(item, *baselevel+1, *difficulty))
|
||||
// } else {
|
||||
// fmt.Print(ItemToSql(item, *baselevel, *difficulty))
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// items2, err := models.DB.GetAddlDungeonDrops(dungeon.Id)
|
||||
// if err != nil {
|
||||
// log.Printf("failed to get additional loot for dungeon %v - err: %v", dungeon.Id, err)
|
||||
// }
|
||||
|
||||
// for _, item := range items2 {
|
||||
|
||||
// // reduce item level of dungeon random drops since they are not boss fights
|
||||
// adjScaleValue := scaleValue - 4
|
||||
|
||||
// _, error := item.ScaleItem(adjScaleValue, boeQuality)
|
||||
// if error != nil {
|
||||
// log.Printf("Failed to scale item: %v", error)
|
||||
// continue
|
||||
// }
|
||||
|
||||
// fmt.Printf("\n-- Item %v Entry: %v ItemLevel %v \n", item.Name, item.Entry, *item.ItemLevel)
|
||||
// fmt.Print(ItemToSql(item, *baselevel, *difficulty))
|
||||
|
||||
// }
|
||||
// log.Printf("++++++++++ Additional Count: %v\n", len(items2))
|
||||
// }
|
||||
|
||||
// defer models.DB.Close()
|
||||
}
|
||||
|
||||
func Scale(highLevelItem mysql.DbItem, item *items.Item, itemLevel, quality int) {
|
||||
item.ApplyStats(items.ItemFromDbItem(highLevelItem))
|
||||
item.ScaleItem(itemLevel, quality)
|
||||
log.Printf("Item Name: %v Stat1: %v Stat2: %v Stat3: %v Stat4: %v Stat5: %v Stat6: %v Stat7: %v Stat8: %v \n",
|
||||
item.Name, *item.StatValue1, *item.StatValue2, *item.StatValue3, *item.StatValue4, *item.StatValue5, *item.StatValue6, *item.StatValue7, *item.StatValue8)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user