Skip to content
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d61878c
Add itemeffects
neteyesking May 7, 2025
a59e4d7
Hi
neteyesking May 7, 2025
0c5033d
Fixes
neteyesking May 6, 2025
1a7da20
Add rppm and maxstacks
neteyesking May 7, 2025
1189160
Run item effects and enchants from DB
neteyesking May 8, 2025
bbe6768
Correct scaling selector
neteyesking May 8, 2025
026e1b3
Clean up
neteyesking May 8, 2025
6f4b4b5
Fix imports
neteyesking May 8, 2025
858a8c1
Fixes
ToxicKevinFerm May 13, 2025
d7b778f
Trying something
ToxicKevinFerm May 14, 2025
98f4799
Cleanup and fix tests
ToxicKevinFerm May 17, 2025
ea33d9a
Fix build errors
NerdEgghead May 17, 2025
29f8547
Update test files
NerdEgghead May 17, 2025
765f258
Merge branch 'master' into test/itemeffects
NerdEgghead May 17, 2025
6da8bea
Merge branch 'master' into test/itemeffects
NerdEgghead May 18, 2025
afc3866
Revert to using the item name rather than the buff name as the
NerdEgghead May 18, 2025
17b6d03
Merge branch 'master' into test/itemeffects
NerdEgghead May 19, 2025
4130f78
Merge branch 'master' into test/itemeffects
NerdEgghead May 20, 2025
3015a4e
Fix ppm
ToxicKevinFerm May 24, 2025
e1b1471
Merge branch 'master' into test/itemeffects
ToxicKevinFerm May 24, 2025
dc1c2ef
Remake db
ToxicKevinFerm May 24, 2025
10b9217
Fix scaling
ToxicKevinFerm May 25, 2025
883e24a
Fix issues
ToxicKevinFerm May 25, 2025
378976f
Merge branch 'master' into test/itemeffects
NerdEgghead May 25, 2025
fca85a2
Fix test passing and remove coefficient scaling
ToxicKevinFerm May 25, 2025
d1ee7ac
Merge branch 'master' into test/itemeffects
NerdEgghead May 25, 2025
fea5316
Merge branch 'test/itemeffects' of https://github.com/wowsims/cata in…
NerdEgghead May 25, 2025
6d957b7
Delete deprecated on-use factory functions
NerdEgghead May 26, 2025
074a114
Deleted deprecated fields from shared.ProcStatBonusEffect
NerdEgghead May 26, 2025
8661a52
Addressed PR comments
ToxicKevinFerm May 27, 2025
a7e910d
Fixes
ToxicKevinFerm May 27, 2025
b18d574
Fix comments
ToxicKevinFerm May 27, 2025
89ac11b
Fix RPPM
ToxicKevinFerm May 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified assets/database/db.bin
Binary file not shown.
9,527 changes: 4,759 additions & 4,768 deletions assets/database/db.json

Large diffs are not rendered by default.

Binary file modified assets/database/leftover_db.bin
Binary file not shown.
22,195 changes: 11,099 additions & 11,096 deletions assets/database/leftover_db.json

Large diffs are not rendered by default.

13 changes: 4 additions & 9 deletions proto/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ message ProtoVersion {
// protos need to define an api_version field so that the UI code knows
// to up-convert these protos to the new format whenever api_version is
// missing (0) or lower than current_version_number.
option (current_version_number) = 4;
option (current_version_number) = 5;

// The actual field value is only used within unit tests.
int32 saved_version_number = 1;
}

enum ItemLevelState {
Base = 0;
ChallengeMode = -1;
Expand All @@ -38,13 +39,15 @@ enum ItemLevelState {
UpgradeStepThree = 3;
UpgradeStepFour = 4;
}

message ScalingItemProperties {
int32 rand_prop_points = 1;
double weapon_damage_min = 2;
double weapon_damage_max = 3;
map<int32, double> stats = 4; // for compactness
int32 ilvl = 6;
}

enum Spec {
SpecUnknown = 0;

Expand Down Expand Up @@ -925,14 +928,6 @@ enum EnchantType {
EnchantTypeOffHand = 5;
}

// Contains only the Enchant info needed by the sim.
message SimEnchant {
int32 effect_id = 1;
repeated double stats = 2;
string name = 3; // Only needed for unit tests.
ItemType type = 4; // Only needed for unit tests.
}

// Contains only the Gem info needed by the sim.
message SimGem {
int32 id = 1;
Expand Down
10 changes: 10 additions & 0 deletions proto/db.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ message SimDatabase {

}

// Contains only the Enchant info needed by the sim.
message SimEnchant {
int32 effect_id = 1;
string name = 2; // Only needed for unit tests.
ItemType type = 3; // Only needed for unit tests.
repeated double stats = 4;
ItemEffect enchant_effect = 5;
}

// Contains only the Item info needed by the sim.
message SimItem {
int32 id = 1;
Expand All @@ -36,6 +45,7 @@ message SimItem {
int32 set_id = 12;

map<int32, ScalingItemProperties> scaling_options = 13; // keys are the all ItemLevelState variants that this item could potentially have
ItemEffect item_effect = 14;
}

message Consumable {
Expand Down
36 changes: 36 additions & 0 deletions proto/spell.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,42 @@ option go_package = "./proto";

import "common.proto";


message ScalingItemEffectProperties {
// keys are the numeric values of proto.common.Stat
map<int32, double> stats = 1;
double rppm_ilvl_modifier = 2;
}
message ItemEffect {
int32 buff_id = 1;
string buff_name = 6;
int32 effect_duration = 2; // seconds

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call this one effect_duration_ms as well so that the units are consistent across the message.

map<int32, ScalingItemEffectProperties> scaling_options = 3;

oneof effect {
ProcEffect proc = 4;
OnUseEffect on_use = 5;
}
}

message ProcEffect {
double proc_chance = 1; // e.g. 0.20 = 20%
double ppm = 3;
int32 rppm_scale = 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is rppm_scale here intended to represent a core.RppmModifier? If so, then it would be cleaner to make RppmScalingType a proto enum rather than a back-end type.

// The key represents a Spec
map<int32, double> spec_modifiers = 5;
int32 icd_ms = 2; // internal cooldown in milliseconds
}

message OnUseEffect {
int32 cooldown_ms = 1; // milliseconds between uses

int32 category_id = 11;

int32 category_cooldown_ms = 8; // category cooldown in milliseconds
}

message SpellEffect {
int32 id = 1;
int32 spell_id = 2;
Expand Down
2 changes: 2 additions & 0 deletions proto/ui.proto
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ message UIItem {

FactionRestriction faction_restriction = 25;
map<int32, ScalingItemProperties> scaling_options = 29; // keys are the other ilvl variants that this item could potentially have
ItemEffect item_effect = 30;
}

enum Expansion {
Expand Down Expand Up @@ -205,6 +206,7 @@ message UIEnchant {
// Classes that are allowed to use the enchant. Empty indicates no special class restrictions.
repeated Class class_allowlist = 11;
Profession required_profession = 12;
ItemEffect enchant_effect = 14;
}

message UIGem {
Expand Down
5 changes: 3 additions & 2 deletions sim/common/cata/damage_procs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/wowsims/cata/sim/common/shared"
"github.com/wowsims/cata/sim/core"
"github.com/wowsims/cata/sim/core/proto"
)

func init() {
Expand Down Expand Up @@ -42,7 +43,7 @@ func init() {
},
})

core.NewItemEffect(68925, func(agent core.Agent) {
core.NewItemEffect(68925, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
// Proc chance determined to be p=.48 by video research - Researched by InDebt & Frostbitten
// Research: https://github.com/wowsims/cata/pull/1009#issuecomment-2348700653
Expand Down Expand Up @@ -96,7 +97,7 @@ func init() {
character.ItemSwap.RegisterProc(68925, aura)
})

core.NewItemEffect(69110, func(agent core.Agent) {
core.NewItemEffect(69110, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
// Proc chance determined to be p=.48 by video research - Researched by InDebt & Frostbitten
// Research: https://github.com/wowsims/cata/pull/1009#issuecomment-2348700653
Expand Down
2 changes: 1 addition & 1 deletion sim/common/cata/dragonwrath.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func GetDRTSpellConfig(spell *core.Spell) core.SpellConfig {
}

func init() {
core.NewItemEffect(71086, func(a core.Agent) {
core.NewItemEffect(71086, func(a core.Agent, _ proto.ItemLevelState) {
character := a.GetCharacter()
unit := &character.Unit
registerSpells(unit)
Expand Down
117 changes: 38 additions & 79 deletions sim/common/cata/enchant_effects.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
func init() {

// Enchant: 4066, Spell: 74195 - Enchant Weapon - Mending
core.NewEnchantEffect(4066, func(agent core.Agent) {
core.NewEnchantEffect(4066, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
healthMetrics := character.NewHealthMetrics(core.ActionID{SpellID: 74194})

Expand Down Expand Up @@ -51,7 +51,7 @@ func init() {
// Enchant: 4067, Spell: 74197 - Enchant Weapon - Avalanche
// http://elitistjerks.com/f79/t110302-enhsim_cataclysm/p4/#post1832162
// Research indicates that the proc itself does not behave as game tables suggest <.<
core.NewEnchantEffect(4067, func(agent core.Agent) {
core.NewEnchantEffect(4067, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
procSpell := character.RegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: 74196},
Expand Down Expand Up @@ -118,7 +118,7 @@ func init() {
})

// Enchant: 4074, Spell: 74211 - Enchant Weapon - Elemental Slayer
core.NewEnchantEffect(4074, func(agent core.Agent) {
core.NewEnchantEffect(4074, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
procSpell := character.RegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: 74208},
Expand Down Expand Up @@ -153,7 +153,7 @@ func init() {
})

// Enchant: 4083, Spell: 74223 - Enchant Weapon - Hurricane
core.NewEnchantEffect(4083, func(agent core.Agent) {
core.NewEnchantEffect(4083, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()

procBuilder := func(name string, tag int32) *core.StatBuffAura {
Expand Down Expand Up @@ -249,46 +249,32 @@ func init() {

// Enchant: 4084, Spell: 74225 - Enchant Weapon - Heartsong
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Heartsong",
EnchantID: 4084,
AuraID: 74224,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
ICD: time.Second * 20,
ProcChance: 0.15,
Bonus: stats.Stats{stats.Spirit: 200},
Duration: time.Second * 15,
Name: "Heartsong",
EnchantID: 4084,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
})

// Enchant: 4097, Spell: 74242 - Enchant Weapon - Power Torrent
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Power Torrent",
EnchantID: 4097,
AuraID: 74241,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
ICD: time.Second * 45,
ProcChance: 0.2,
Bonus: stats.Stats{stats.Intellect: 500},
Duration: time.Second * 12,
Name: "Power Torrent",
EnchantID: 4097,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
})

// Enchant: 4098, Spell: 74244 - Enchant Weapon - Windwalk
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Windwalk",
EnchantID: 4098,
AuraID: 74243,
Callback: core.CallbackOnSpellHitDealt,
Outcome: core.OutcomeLanded,
PPM: 1, // based on old Wowhead comments, TODO: measure in Classic
Bonus: stats.Stats{stats.DodgeRating: 600},
Duration: time.Second * 10,
})

// Enchant: 4099, Spell: 74246 - Enchant Weapon - Landslide
core.NewEnchantEffect(4099, func(agent core.Agent) {
core.NewEnchantEffect(4099, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()

mainHand := character.NewTemporaryStatsAura(
Expand Down Expand Up @@ -328,68 +314,47 @@ func init() {

// Enchant: 4115, Spell: 75172 - Lightweave Embroidery
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Lightweave Embroidery Cata",
EnchantID: 4115,
AuraID: 75170,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt | core.CallbackOnHealDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
ICD: time.Second * 64,
ProcChance: 0.25,
Bonus: stats.Stats{stats.Intellect: 580},
Duration: time.Second * 15,
Name: "Lightweave Embroidery Cata",
EnchantID: 4115,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt | core.CallbackOnHealDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
})

// Enchant: 4116, Spell: 75175 - Darkglow Embroidery
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Darkglow Embroidery Cata",
EnchantID: 4116,
AuraID: 75173,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt | core.CallbackOnHealDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
ICD: time.Second * 57,
ProcChance: 0.30,
Bonus: stats.Stats{stats.Spirit: 580},
Duration: time.Second * 15,
Name: "Darkglow Embroidery Cata",
EnchantID: 4116,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt | core.CallbackOnHealDealt,
ProcMask: core.ProcMaskSpellDamage | core.ProcMaskSpellHealing,
Outcome: core.OutcomeLanded,
})

// Enchant: 4118, Spell: 75178 - Swordguard Embroidery
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Swordguard Embroidery Cata",
EnchantID: 4118,
AuraID: 75178,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt | core.CallbackOnHealDealt,
ProcMask: core.ProcMaskMeleeOrRanged,
Outcome: core.OutcomeLanded,
ICD: time.Second * 55,
ProcChance: 0.15,
Bonus: stats.Stats{stats.AttackPower: 1000, stats.RangedAttackPower: 1000},
Duration: time.Second * 15,
Name: "Swordguard Embroidery Cata",
EnchantID: 4118,
Callback: core.CallbackOnSpellHitDealt | core.CallbackOnPeriodicDamageDealt | core.CallbackOnHealDealt,
ProcMask: core.ProcMaskMeleeOrRanged,
Outcome: core.OutcomeLanded,
})

// Enchant: 4175, Spell: 81932, Item: 59594 - Gnomish X-Ray Scope
shared.NewProcStatBonusEffect(shared.ProcStatBonusEffect{
Name: "Gnomish X-Ray Scope",
EnchantID: 4175,
ItemID: 59594,
AuraID: 95712,
Callback: core.CallbackOnSpellHitDealt,
ProcMask: core.ProcMaskRanged,
Outcome: core.OutcomeLanded,
ICD: time.Second * 40,
PPM: 1,
Bonus: stats.Stats{stats.RangedAttackPower: 800},
Duration: time.Second * 10,
})

// Enchant: 4176, Item: 59595 - R19 Threatfinder
core.NewEnchantEffect(4176, func(agent core.Agent) {
core.NewEnchantEffect(4176, func(agent core.Agent, _ proto.ItemLevelState) {
agent.GetCharacter().AddBonusRangedHitPercent(88 / core.PhysicalHitRatingPerHitPercent)
})

// Enchant: 4177, Item: 59596 - Safety Catch Removal Kit
core.NewEnchantEffect(4177, func(agent core.Agent) {
core.NewEnchantEffect(4177, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
// TODO: This should be ranged-only haste. For now just make it hunter-only.
if character.Class == proto.Class_ClassHunter {
Expand Down Expand Up @@ -433,17 +398,11 @@ func init() {

// Enchant: 4267, Spell: 99623, Item: 70139 - Flintlocke's Woodchucker
shared.NewProcStatBonusEffectWithDamageProc(shared.ProcStatBonusEffect{
Name: "Flintlocke's Woodchucker",
EnchantID: 4267,
ItemID: 70139,
AuraID: 99621,
Callback: core.CallbackOnSpellHitDealt,
ProcMask: core.ProcMaskRanged,
Outcome: core.OutcomeLanded,
ICD: time.Second * 40,
ProcChance: 0.1,
Bonus: stats.Stats{stats.Agility: 300},
Duration: time.Second * 10,
Name: "Flintlocke's Woodchucker",
EnchantID: 4267,
Callback: core.CallbackOnSpellHitDealt,
ProcMask: core.ProcMaskRanged,
Outcome: core.OutcomeLanded,
},
shared.DamageEffect{
SpellID: 99621,
Expand All @@ -463,7 +422,7 @@ func init() {
}

for _, enchantID := range movementSpeedEnchants {
core.NewEnchantEffect(enchantID, func(agent core.Agent) {
core.NewEnchantEffect(enchantID, func(agent core.Agent, _ proto.ItemLevelState) {
character := agent.GetCharacter()
aura := character.NewMovementSpeedAura("Minor Run Speed", core.ActionID{SpellID: 13889}, 0.08)

Expand Down
2 changes: 1 addition & 1 deletion sim/common/cata/gurthalak.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func init() {
gurthalakItemID := gurthalakItemIDs[version]
summonSpellID := []int32{109838, 107818, 109840}[version]

core.NewItemEffect(gurthalakItemID, func(agent core.Agent) {
core.NewItemEffect(gurthalakItemID, func(agent core.Agent, _ proto.ItemLevelState) {
var gurthalak GurthalakAgent
if gurth, canEquip := agent.(GurthalakAgent); canEquip {
gurthalak = gurth
Expand Down
Loading
Loading