Skip to content

Commit

Permalink
Merge pull request #3630 from vigo2/vigo/item-sets
Browse files Browse the repository at this point in the history
vigo/item-sets
  • Loading branch information
vigo2 authored Sep 9, 2023
2 parents 393f722 + 91e5988 commit 9344cd2
Show file tree
Hide file tree
Showing 20 changed files with 15,433 additions and 15,649 deletions.
30,418 changes: 15,209 additions & 15,209 deletions assets/db_inputs/wago_db2_items.csv

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/db_inputs/wowhead_gearplannerdb.txt

Large diffs are not rendered by default.

12 changes: 4 additions & 8 deletions sim/common/tbc/melee_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,9 @@ var ItemSetStormshroud = core.NewItemSet(core.ItemSet{
if !result.Landed() || !spell.ProcMask.Matches(core.ProcMaskMelee) {
return
}
chance := 0.05
if sim.RandomFloat("Stormshroud Armor 2pc") > chance {
return
if sim.RandomFloat("Stormshroud Armor 2pc") < 0.05 {
proc.Cast(sim, result.Target)
}
proc.Cast(sim, result.Target)
},
})
},
Expand Down Expand Up @@ -113,11 +111,9 @@ var ItemSetStormshroud = core.NewItemSet(core.ItemSet{
if !result.Landed() || !spell.ProcMask.Matches(core.ProcMaskMelee) {
return
}
chance := 0.02
if sim.RandomFloat("Stormshroud Armor 2pc") > chance {
return
if sim.RandomFloat("Stormshroud Armor 3pc") < 0.02 {
proc.Cast(sim, result.Target)
}
proc.Cast(sim, result.Target)
},
})

Expand Down
7 changes: 3 additions & 4 deletions sim/common/wotlk/nibelung.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,10 @@ func MakeNibelungTriggerAura(agent core.Agent, isHeroic bool) {
return
}

for _, pet := range character.PetAgents {
valkyr, ok := pet.(*ValkyrPet)
if ok && !valkyr.IsEnabled() {
for _, petAgent := range character.PetAgents {
if valkyr, ok := petAgent.(*ValkyrPet); ok && !valkyr.IsEnabled() {
valkyr.registerSmite(isHeroic)
valkyr.EnableWithTimeout(sim, pet, valkyrAura.Duration)
valkyr.EnableWithTimeout(sim, petAgent, valkyrAura.Duration)
break
}
}
Expand Down
13 changes: 7 additions & 6 deletions sim/core/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,26 @@ import (

var WITH_DB = false

var ItemsByID = map[int32]Item{}
var GemsByID = map[int32]Gem{}
var EnchantsByEffectID = map[int32]Enchant{}
var ItemsByID map[int32]Item
var GemsByID map[int32]Gem
var EnchantsByEffectID map[int32]Enchant

func addToDatabase(newDB *proto.SimDatabase) {
ItemsByID = make(map[int32]Item, len(newDB.Items))
for _, v := range newDB.Items {
if _, ok := ItemsByID[v.Id]; !ok {
item := ItemFromProto(v)
ItemsByID[v.Id] = item
AddItemToSets(item)
ItemsByID[v.Id] = ItemFromProto(v)
}
}

EnchantsByEffectID = make(map[int32]Enchant, len(newDB.Enchants))
for _, v := range newDB.Enchants {
if _, ok := EnchantsByEffectID[v.EffectId]; !ok {
EnchantsByEffectID[v.EffectId] = EnchantFromProto(v)
}
}

GemsByID = make(map[int32]Gem, len(newDB.Gems))
for _, v := range newDB.Gems {
if _, ok := GemsByID[v.Id]; !ok {
GemsByID[v.Id] = GemFromProto(v)
Expand Down
12 changes: 4 additions & 8 deletions sim/core/item_effects.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package core

import (
"fmt"
"golang.org/x/exp/slices"
"strconv"
"time"

Expand All @@ -15,15 +16,15 @@ import (
// but there are occasionally class-specific item effects.
type ApplyEffect func(Agent)

// Function for applying permenent effects to an agent's weapon
// Function for applying permanent effects to an agent's weapon
type ApplyWeaponEffect func(Agent, proto.ItemSlot)

var itemEffects = map[int32]ApplyEffect{}
var weaponEffects = map[int32]ApplyWeaponEffect{}
var enchantEffects = map[int32]ApplyEffect{}

// IDs of item effects which should be used for tests.
var itemEffectsForTest = []int32{}
var itemEffectsForTest []int32

// This value can be set before adding item effects, to control whether they are included in tests.
var AddEffectsToTest = true
Expand All @@ -33,12 +34,7 @@ func HasItemEffect(id int32) bool {
return ok
}
func HasItemEffectForTest(id int32) bool {
for _, itemID := range itemEffectsForTest {
if id == itemID {
return true
}
}
return false
return slices.Contains(itemEffectsForTest, id)
}

func HasWeaponEffect(id int32) bool {
Expand Down
134 changes: 52 additions & 82 deletions sim/core/item_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,44 @@ type ItemSet struct {
Name string
AlternativeName string

// IDs of items that are part of this set. map[key]struct{} is roughly a set in go.
Items map[int32]struct{}

// Maps set piece requirement to an ApplyEffect function that will be called
// before the Sim starts.
//
// The function should apply any benefits provided by the set bonus.
Bonuses map[int32]ApplyEffect
}

func (set ItemSet) ItemIDs() []int32 {
ids := make([]int32, 0, len(set.Items))
for id := range set.Items {
ids = append(ids, id)
func (set ItemSet) Items() []Item {
var items []Item
for _, item := range ItemsByID {
if item.SetName == "" {
continue
}
if item.SetName == set.Name || item.SetName == set.AlternativeName {
items = append(items, item)
}
}
// Sort so the order of IDs is always consistent, for tests.
slices.Sort(ids)
return ids
}

func (set ItemSet) ItemIsInSet(itemID int32) bool {
_, ok := set.Items[itemID]
return ok
slices.SortFunc(items, func(a, b Item) bool {
return a.ID < b.ID
})
return items
}

var sets []*ItemSet

func GetAllItemSets() []*ItemSet {
// Defensive copy to prevent modifications.
tmp := make([]*ItemSet, len(sets))
copy(tmp, sets)
return tmp
}

// cache for mapping item to set for fast resetting of sim.
var itemSetLookup = map[int32]*ItemSet{}

// Registers a new ItemSet with item IDs populated.
func NewItemSet(setStruct ItemSet) *ItemSet {
set := &ItemSet{}
*set = setStruct

if len(set.Items) > 0 {
panic(set.Name + " (" + set.AlternativeName + ") supplied item IDs, set items are detected automatically!")
}

set.Items = make(map[int32]struct{})
func NewItemSet(set ItemSet) *ItemSet {
foundName := false
foundAlternativeName := false
foundAlternativeName := set.AlternativeName == ""
for _, item := range ItemsByID {
if item.SetName == set.Name || (len(set.AlternativeName) > 0 && item.SetName == set.AlternativeName) {
//fmt.Printf("Adding item %s-%d to set %s\n", item.Name, item.ID, item.SetName)
set.Items[item.ID] = struct{}{}

if item.SetName == set.Name {
foundName = true
} else {
foundAlternativeName = true
}
if item.SetName == "" {
continue
}
foundName = foundName || item.SetName == set.Name
foundAlternativeName = foundAlternativeName || item.SetName == set.AlternativeName
if foundName && foundAlternativeName {
break
}
}

Expand All @@ -80,38 +59,25 @@ func NewItemSet(setStruct ItemSet) *ItemSet {
}
}

sets = append(sets, set)
for itemID := range set.Items {
itemSetLookup[itemID] = set
}
return set
}

func AddItemToSets(item Item) {
if item.SetName == "" {
return
}

for _, set := range sets {
if set.Name == item.SetName || set.AlternativeName == item.SetName {
set.Items[item.ID] = struct{}{}
itemSetLookup[item.ID] = set
}
}
sets = append(sets, &set)
return &set
}

func (character *Character) HasSetBonus(itemSet *ItemSet, numItems int32) bool {
func (character *Character) HasSetBonus(set *ItemSet, numItems int32) bool {
if character.Env != nil && character.Env.IsFinalized() {
panic("HasSetBonus is very slow and should never be called after finalization. Try caching the value during construction instead!")
}

if _, ok := itemSet.Bonuses[numItems]; !ok {
panic(fmt.Sprintf("Item set %s does not have a bonus with %d pieces.", itemSet.Name, numItems))
if _, ok := set.Bonuses[numItems]; !ok {
panic(fmt.Sprintf("Item set %s does not have a bonus with %d pieces.", set.Name, numItems))
}

var count int32
for _, item := range character.Equipment {
if itemSet.ItemIsInSet(item.ID) {
if item.SetName == "" {
continue
}
if item.SetName == set.Name || item.SetName == set.AlternativeName {
count++
if count >= numItems {
return true
Expand All @@ -135,19 +101,24 @@ type ActiveSetBonus struct {

// Returns a list describing all active set bonuses.
func (character *Character) GetActiveSetBonuses() []ActiveSetBonus {
activeBonuses := []ActiveSetBonus{}
setItemCount := map[string]int32{}

for _, i := range character.Equipment {
set := itemSetLookup[i.ID]
if set != nil {
setItemCount[set.Name]++
if setBonusFunc, ok := set.Bonuses[setItemCount[set.Name]]; ok {
activeBonuses = append(activeBonuses, ActiveSetBonus{
Name: set.Name,
NumPieces: setItemCount[set.Name],
BonusEffect: setBonusFunc,
})
var activeBonuses []ActiveSetBonus

setItemCount := make(map[*ItemSet]int32)
for _, item := range character.Equipment {
if item.SetName == "" {
continue
}
for _, set := range sets {
if set.Name == item.SetName || set.AlternativeName == item.SetName {
setItemCount[set]++
if bonusEffect, ok := set.Bonuses[setItemCount[set]]; ok {
activeBonuses = append(activeBonuses, ActiveSetBonus{
Name: set.Name,
NumPieces: setItemCount[set],
BonusEffect: bonusEffect,
})
}
break
}
}
}
Expand All @@ -167,11 +138,10 @@ func (character *Character) applyItemSetBonusEffects(agent Agent) {
// Returns the names of all active set bonuses.
func (character *Character) GetActiveSetBonusNames() []string {
activeSetBonuses := character.GetActiveSetBonuses()
names := []string{}

for _, activeSetBonus := range activeSetBonuses {
names = append(names, fmt.Sprintf("%s (%dpc)", activeSetBonus.Name, activeSetBonus.NumPieces))
names := make([]string, len(activeSetBonuses))
for i, activeSetBonus := range activeSetBonuses {
names[i] = fmt.Sprintf("%s (%dpc)", activeSetBonus.Name, activeSetBonus.NumPieces)
}

return names
}
Loading

0 comments on commit 9344cd2

Please sign in to comment.