From a6c0b166a82f0ddfe08330a58e53b80a6fa64a7d Mon Sep 17 00:00:00 2001 From: Borbrun Date: Sun, 26 Dec 2021 11:54:34 -0500 Subject: [PATCH 1/6] Correct the readme, single the "-single" part is not actually required. Various fixes and improvements to arcane mage rotation and consumables. Add Mage Armor to the mage ability list. Improvements to the arcane mage EP calculation. Restore the apparently missing ability to run EP for a chosen profile. Instead of applying a random 2% hit reduction, which messes with various proc chances, etc. switch the delta on the hit EP test to use a negative hit modifier. Add mage armor, which is used by arcane mages. Add a spirit buff mutex and scroll of spirit. Add Innervate. Add missing elixirs used by arcane mages. Frostbolt gets double benefit from Element Precision. (Who knows why?) --- README.md | 2 +- src/commonMain/kotlin/character/Mutex.kt | 1 + src/commonMain/kotlin/character/Spec.kt | 4 +- .../kotlin/character/classes/mage/Mage.kt | 1 + .../classes/mage/abilities/Frostbolt.kt | 2 +- .../character/classes/mage/specs/Arcane.kt | 7 ++- .../abilities/generic/GenericAbilities.kt | 4 ++ .../data/abilities/raid/DivineSpirit.kt | 2 + .../abilities/raid/ImprovedDivineSpirit.kt | 2 + src/jvmMain/kotlin/Main.kt | 15 ++--- ui/src/presets/samples/mage_arcane_phase2.yml | 63 +++++++++++++------ 11 files changed, 69 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 58d8a4a7f..6bf77b9bd 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Not yet implemented: To calculate EPs for a single character definition, use the following command: -`./tbcsim --calc-ep-single ` +`./tbcsim --calc-ep ` This uses the sim defaults of a step interval of 10ms and an iteration count of 10,000 - both can be adjusted to your preference. See the CLI usage below, or just run `./tbcsim`. diff --git a/src/commonMain/kotlin/character/Mutex.kt b/src/commonMain/kotlin/character/Mutex.kt index 848734f13..2b488b916 100644 --- a/src/commonMain/kotlin/character/Mutex.kt +++ b/src/commonMain/kotlin/character/Mutex.kt @@ -18,6 +18,7 @@ enum class Mutex { BUFF_EXPOSE_WEAKNESS, BUFF_FEROCIOUS_INSPIRATION, BUFF_FAERIE_FIRE, + BUFF_SPIRIT, // Hunter BUFF_HUNTER_ASPECT, diff --git a/src/commonMain/kotlin/character/Spec.kt b/src/commonMain/kotlin/character/Spec.kt index 03236eb99..76002d260 100644 --- a/src/commonMain/kotlin/character/Spec.kt +++ b/src/commonMain/kotlin/character/Spec.kt @@ -12,7 +12,7 @@ abstract class Spec { Triple("strength", Stats(strength = 50), 50.0), Triple("agility", Stats(agility = 50), 50.0), Triple("meleeCritRating", Stats(meleeCritRating = 5.0 * Rating.critPerPct), 5.0 * Rating.critPerPct), - Triple("physicalHitRating", Stats(physicalHitRating = 2.0 * Rating.physicalHitPerPct), 2.0 * Rating.physicalHitPerPct), + Triple("physicalHitRating", Stats(physicalHitRating = -5.0 * Rating.physicalHitPerPct), -5.0 * Rating.physicalHitPerPct), Triple("physicalHasteRating", Stats(physicalHasteRating = 5.0 * Rating.hastePerPct), 5.0 * Rating.hastePerPct), Triple("expertiseRating", Stats(expertiseRating = 2.0 * Rating.expertisePerPct), 2.0 * Rating.expertisePerPct), Triple("armorPen", Stats(armorPen = 100), 100.0), @@ -33,7 +33,7 @@ abstract class Spec { // AKA Enhancement Shaman val casterHybridDeltas = listOf( Triple("spellCritRating", Stats(spellCritRating = 5.0 * Rating.critPerPct), 5.0 * Rating.critPerPct), - Triple("spellHitRating", Stats(spellHitRating = 5.0 * Rating.spellHitPerPct), 5.0 * Rating.spellHitPerPct) + Triple("spellHitRating", Stats(spellHitRating = -5.0 * Rating.spellHitPerPct), -5.0 * Rating.spellHitPerPct) ) val defaultCasterDeltas: List = listOf( Triple("intellect", Stats(intellect = 50), 50.0), diff --git a/src/commonMain/kotlin/character/classes/mage/Mage.kt b/src/commonMain/kotlin/character/classes/mage/Mage.kt index 8152e8a32..d99d2dbbf 100644 --- a/src/commonMain/kotlin/character/classes/mage/Mage.kt +++ b/src/commonMain/kotlin/character/classes/mage/Mage.kt @@ -36,6 +36,7 @@ class Mage(talents: Map, spec: Spec) : Class(talents, spec) { IcyVeins.name -> IcyVeins() ManaEmerald.name -> ManaEmerald() MoltenArmor.name -> MoltenArmor() + MageArmor.name -> MageArmor() PresenceOfMind.name -> PresenceOfMind() Scorch.name -> Scorch() SummonWaterElemental.name -> SummonWaterElemental() diff --git a/src/commonMain/kotlin/character/classes/mage/abilities/Frostbolt.kt b/src/commonMain/kotlin/character/classes/mage/abilities/Frostbolt.kt index 512a0cf6e..62977d93c 100644 --- a/src/commonMain/kotlin/character/classes/mage/abilities/Frostbolt.kt +++ b/src/commonMain/kotlin/character/classes/mage/abilities/Frostbolt.kt @@ -49,7 +49,7 @@ class Frostbolt : Ability() { val spellPowerCoeff = Spell.spellPowerCoeff(baseCastTimeMs) override fun cast(sp: SimParticipant) { val elementalPrecision: ElementalPrecision? = sp.character.klass.talentInstance(ElementalPrecision.name) - val emHit = elementalPrecision?.bonusFireFrostHitPct() ?: 0.0 + val emHit = 2 * (elementalPrecision?.bonusFireFrostHitPct() ?: 0.0) val empFb: EmpoweredFrostbolt? = sp.character.klass.talentInstance(EmpoweredFrostbolt.name) val bonusFbCrit = empFb?.frostboltAddlCritPct() ?: 0.0 diff --git a/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt b/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt index 4a424a681..744979d0e 100644 --- a/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt +++ b/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt @@ -2,11 +2,14 @@ package character.classes.mage.specs import character.Spec import character.SpecEpDelta +import character.Stats class Arcane : Spec() { override val name: String = "Arcane" override val epBaseStat: SpecEpDelta = spellPowerBase - override val epStatDeltas: List = defaultCasterDeltas + override val epStatDeltas: List = listOf(Triple("spirit", Stats(spirit = 50), 50.0)) + + defaultCasterDeltas + override fun redSocketEp(deltas: Map): Double { // 12 spell dmg @@ -15,7 +18,7 @@ class Arcane : Spec() { override fun yellowSocketEp(deltas: Map): Double { // 5 spell haste rating / 6 spell damage - return ((deltas["spellHasteRating"] ?: 0.0) * 5.0) + 6.0 + return ((deltas["intellect"] ?: 0.0) * 10.0) } override fun blueSocketEp(deltas: Map): Double { diff --git a/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt b/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt index f98c30703..62df0bb28 100644 --- a/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt +++ b/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt @@ -6,19 +6,23 @@ import character.Ability object GenericAbilities { fun byName(name: String): Ability? { return when(name) { + AdeptsElixir.name -> AdeptsElixir() BlackenedBasilisk.name -> BlackenedBasilisk() CrunchySerpent.name -> CrunchySerpent() DarkRune.name -> DarkRune() DemonicRune.name -> DemonicRune() DestructionPotion.name -> DestructionPotion() + ElixirOfDraenicWisdom.name -> ElixirOfDraenicWisdom() ElixirOfMajorAgility.name -> ElixirOfMajorAgility() ElixirOfMajorStrength.name -> ElixirOfMajorStrength() FlaskOfBlindingLight.name -> FlaskOfBlindingLight() FlaskOfPureDeath.name -> FlaskOfPureDeath() FlaskOfRelentlessAssault.name -> FlaskOfRelentlessAssault() HastePotion.name -> HastePotion() + Innervate.name -> Innervate() InsaneStrengthPotion.name -> InsaneStrengthPotion() RoastedClefthoof.name -> RoastedClefthoof() + ScrollOfSpiritV.name -> ScrollOfSpiritV() SpicyHotTalbuk.name -> SpicyHotTalbuk() SuperManaPotion.name -> SuperManaPotion() UseActiveTrinket.name -> UseActiveTrinket() diff --git a/src/commonMain/kotlin/data/abilities/raid/DivineSpirit.kt b/src/commonMain/kotlin/data/abilities/raid/DivineSpirit.kt index 9499dd93c..a0ca69bdc 100644 --- a/src/commonMain/kotlin/data/abilities/raid/DivineSpirit.kt +++ b/src/commonMain/kotlin/data/abilities/raid/DivineSpirit.kt @@ -2,6 +2,7 @@ package data.abilities.raid import character.Ability import character.Buff +import character.Mutex import character.Stats import mechanics.Rating import sim.SimParticipant @@ -20,6 +21,7 @@ class DivineSpirit : Ability() { override val name: String = Companion.name override val icon: String = "spell_holy_prayerofspirit.jpg" override val durationMs: Int = -1 + override val mutex: List = listOf(Mutex.BUFF_SPIRIT) override fun modifyStats(sp: SimParticipant): Stats { return Stats(spirit = 50) diff --git a/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt b/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt index 09b42d1cb..f95814682 100644 --- a/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt +++ b/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt @@ -2,6 +2,7 @@ package data.abilities.raid import character.Ability import character.Buff +import character.Mutex import character.Stats import mechanics.Rating import sim.SimParticipant @@ -20,6 +21,7 @@ class ImprovedDivineSpirit : Ability() { override val name: String = Companion.name override val icon: String = "spell_holy_prayerofspirit.jpg" override val durationMs: Int = -1 + override val mutex: List = listOf(Mutex.BUFF_SPIRIT) override fun modifyStats(sp: SimParticipant): Stats { // assumes max rank diff --git a/src/jvmMain/kotlin/Main.kt b/src/jvmMain/kotlin/Main.kt index cb4d85478..0e8b4c952 100644 --- a/src/jvmMain/kotlin/Main.kt +++ b/src/jvmMain/kotlin/Main.kt @@ -153,15 +153,8 @@ class TBCSim : CliktCommand() { ) fun singleEpSim(config: Config, opts: SimOptions, epDelta: SpecEpDelta? = null) : Pair { - // Most presets are hit capped, so apply a universal -2% hit buff so the hit has something to sim against - val hitReduction = Stats( - physicalHitRating = -2.0 * Rating.physicalHitPerPct, - expertiseRating = -2.0 * Rating.expertisePerPct, - spellHitRating = -5.0 * Rating.spellHitPerPct, - ) - val epStatMod = epDelta?.second ?: Stats() - val totalStatMod = Stats().add(epStatMod).add(hitReduction) + val totalStatMod = Stats().add(epStatMod)//.add(hitReduction) val iterations = runBlocking { Sim(config, opts, totalStatMod) {}.sim() } return Pair(epDelta, SimStats.dps(iterations).entries.sumByDouble { it.value?.mean ?: 0.0 }) @@ -265,7 +258,11 @@ class TBCSim : CliktCommand() { val specFilter = specFilterStr?.split(",") val categoryFilter = categoryFilterStr?.split(",") - if (calcEP) { + if (calcEP && configFile?.exists() == true) { + val config = ConfigMaker.fromYml(configFile!!.readText()) + println("Starting EP run") + val deltas = computeEpDeltas(config, opts) + } else if (calcEP) { val epTypeRef = object : TypeReference(){} val existing = mapper.readValue(File(epOutputPath).readText(), epTypeRef) // EP calculation sim diff --git a/ui/src/presets/samples/mage_arcane_phase2.yml b/ui/src/presets/samples/mage_arcane_phase2.yml index b174bb103..e1fb0acad 100644 --- a/ui/src/presets/samples/mage_arcane_phase2.yml +++ b/ui/src/presets/samples/mage_arcane_phase2.yml @@ -53,7 +53,7 @@ gear: mainHand: name: The Nexus Key enchant: Major Spellpower (Weapon) - tempEnchant: Superior Wizard Oil + tempEnchant: Brilliant Wizard Oil rangedTotemLibram: name: Eredar Wand of Obliteration head: @@ -112,14 +112,28 @@ gear: rotation: autoAttack: false precombat: - - name: Flask of Blinding Light + - name: Elixir of Draenic Wisdom + - name: Adept's Elixir - name: Crunchy Serpent - name: Arcane Intellect - - name: Molten Armor + - name: Mage Armor + - name: Scroll of Spirit V combat: + - name: Evocation + criteria: + - type: RESOURCE_PCT_LTE + pct: 30 + resourceType: MANA + - type: FIGHT_TIME_REMAINING_GTE + seconds: 30 - name: Blood Fury - name: Berserking + - name: Bloodlust + criteria: + - type: FIGHT_DURATION_GTE + seconds: 15 + - name: Drums of Battle - name: Mana Emerald criteria: - type: RESOURCE_MISSING_GTE @@ -131,31 +145,40 @@ rotation: - type: RESOURCE_MISSING_GTE amount: 3000 resourceType: MANA - - name: Evocation + - type: ABILITY_COOLDOWN_GTE + ability: Mana Emerald + seconds: 1 + - name: Innervate criteria: - type: RESOURCE_PCT_LTE - pct: 20 + pct: 35 resourceType: MANA - - type: FIGHT_TIME_REMAINING_GTE - seconds: 30 - name: Cold Snap criteria: + - type: ABILITY_COOLDOWN_LTE + ability: Mana Emerald + seconds: 5 - type: ABILITY_COOLDOWN_GTE - ability: Icy Veins + ability: Mana Emerald seconds: 1 - name: Icy Veins criteria: - - type: FIGHT_TIME_ELAPSED_GTE - seconds: 5 + - type: RESOURCE_MISSING_GTE + # Account for Serpent-Coil Braid bonus potential over the regular mana gem amount + amount: 3125 + resourceType: MANA - name: Arcane Power criteria: - - type: FIGHT_TIME_ELAPSED_GTE - seconds: 5 + - type: RESOURCE_MISSING_GTE + # Account for Serpent-Coil Braid bonus potential over the regular mana gem amount + amount: 3125 + resourceType: MANA - name: Presence of Mind - criteria: - - type: FIGHT_TIME_ELAPSED_GTE - seconds: 5 - name: Use Active Trinket + criteria: + - type: RESOURCE_MISSING_GTE + amount: 3125 + resourceType: MANA # Cast AB if we're using cooldowns, have high mana, or have low mana and low stacks - name: Arcane Blast criteria: @@ -170,16 +193,18 @@ rotation: - name: Arcane Blast criteria: - type: RESOURCE_PCT_GTE - pct: 20 + pct: 25 resourceType: MANA - name: Arcane Blast criteria: - type: BUFF_STACKS_LTE buff: Arcane Blast stacks: 2 - - type: RESOURCE_PCT_LTE - pct: 20 - resourceType: MANA + - name: Arcane Blast + criteria: + - type: BUFF_DURATION_LTE + buff: Arcane Blast + seconds: 1 - name: Frostbolt raidBuffs: From b0c9032ea282617eaccade3eb8de6bfc4f3cd38a Mon Sep 17 00:00:00 2001 From: borbrunpagle Date: Sun, 26 Dec 2021 21:30:31 -0500 Subject: [PATCH 2/6] Add mage armor, elixirs, innervate, scroll of spirit. --- .../kotlin/character/classes/mage/abilities/MageArmor.kt | 5 +++++ src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt | 5 +++++ .../kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt | 2 ++ src/commonMain/kotlin/data/abilities/generic/Innervate.kt | 2 ++ .../kotlin/data/abilities/generic/ScrollOfSpiritV.kt | 2 ++ 5 files changed, 16 insertions(+) create mode 100644 src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt create mode 100644 src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt create mode 100644 src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt create mode 100644 src/commonMain/kotlin/data/abilities/generic/Innervate.kt create mode 100644 src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt diff --git a/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt b/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt new file mode 100644 index 000000000..ec79c96b2 --- /dev/null +++ b/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt @@ -0,0 +1,5 @@ +package character.classes.mage + +class MageArmor { + +} diff --git a/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt b/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt new file mode 100644 index 000000000..3d12e3dce --- /dev/null +++ b/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt @@ -0,0 +1,5 @@ +package data.abilities.generic + +class AdeptsElixir : Ability() { + +} diff --git a/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt b/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt new file mode 100644 index 000000000..684e3a314 --- /dev/null +++ b/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt @@ -0,0 +1,2 @@ +package data.abilities.generic + diff --git a/src/commonMain/kotlin/data/abilities/generic/Innervate.kt b/src/commonMain/kotlin/data/abilities/generic/Innervate.kt new file mode 100644 index 000000000..684e3a314 --- /dev/null +++ b/src/commonMain/kotlin/data/abilities/generic/Innervate.kt @@ -0,0 +1,2 @@ +package data.abilities.generic + diff --git a/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt b/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt new file mode 100644 index 000000000..684e3a314 --- /dev/null +++ b/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt @@ -0,0 +1,2 @@ +package data.abilities.generic + From f26d68772ac9aa25c99df37c09a68ccaebf7e2e8 Mon Sep 17 00:00:00 2001 From: borbrunpagle Date: Thu, 6 Jan 2022 23:01:11 -0500 Subject: [PATCH 3/6] Add missing implementations. --- .../classes/mage/abilities/MageArmor.kt | 33 +++++++++++++++-- .../data/abilities/generic/AdeptsElixir.kt | 27 +++++++++++++- .../generic/ElixirOfDraenicWisdom.kt | 30 +++++++++++++++- .../kotlin/data/abilities/generic/FlameCap.kt | 33 +++++++++++++++++ .../abilities/generic/GenericAbilities.kt | 1 + .../data/abilities/generic/Innervate.kt | 35 ++++++++++++++++++- .../data/abilities/generic/ScrollOfSpiritV.kt | 30 +++++++++++++++- 7 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 src/commonMain/kotlin/data/abilities/generic/FlameCap.kt diff --git a/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt b/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt index ec79c96b2..e188e0eae 100644 --- a/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt +++ b/src/commonMain/kotlin/character/classes/mage/abilities/MageArmor.kt @@ -1,5 +1,32 @@ -package character.classes.mage +package character.classes.mage.abilities -class MageArmor { +import character.Ability +import character.Buff +import character.Stats +import mechanics.General +import sim.SimParticipant -} +class MageArmor : Ability() { + companion object { + const val name = "Mage Armor" + } + override val id: Int = 22783 + override val name: String = Companion.name + override val icon: String = "spell_magearmor.jpg" + override fun gcdMs(sp: SimParticipant): Int = sp.spellGcd().toInt() + override fun resourceCost(sp: SimParticipant): Double = 630.0 + + val buff = object : Buff() { + override val name: String = Companion.name + override val icon: String = "spell_magearmor.jpg" + override val durationMs: Int = 30 * 60 * 1000 + + override fun modifyStats(sp: SimParticipant): Stats { + return Stats(manaPer5Seconds = (General.mp5FromSpiritNotCasting(sp) * .3).toInt()) + } + } + + override fun cast(sp: SimParticipant) { + sp.addBuff(buff) + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt b/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt index 3d12e3dce..8fef490d3 100644 --- a/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt +++ b/src/commonMain/kotlin/data/abilities/generic/AdeptsElixir.kt @@ -1,5 +1,30 @@ package data.abilities.generic +import character.* +import sim.SimParticipant + class AdeptsElixir : Ability() { + companion object { + const val name = "Adept's Elixir" + } + + override val id: Int = 28103 + override val name: String = Companion.name + override val icon: String = "inv_potion_96.jpg" + override fun gcdMs(sp: SimParticipant): Int = 0 + + val buff = object : Buff() { + override val name: String = "Adept's Elixir" + override val icon: String = "inv_potion_96.jpg" + override val durationMs: Int = 60 * 60 * 1000 + override val mutex: List = listOf(Mutex.GUARDIAN_ELIXIR) + + override fun modifyStats(sp: SimParticipant): Stats { + return Stats(spellDamage = 24, spellCritRating = 24.0) + } + } -} + override fun cast(sp: SimParticipant) { + sp.addBuff(buff) + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt b/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt index 684e3a314..02b0ce347 100644 --- a/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt +++ b/src/commonMain/kotlin/data/abilities/generic/ElixirOfDraenicWisdom.kt @@ -1,2 +1,30 @@ -package data.abilities.generic +package data.abilities.generic +import character.* +import sim.SimParticipant + +class ElixirOfDraenicWisdom : Ability() { + companion object { + const val name = "Elixir of Draenic Wisdom" + } + + override val id: Int = 32067 + override val name: String = Companion.name + override val icon: String = "inv_potion_155.jpg" + override fun gcdMs(sp: SimParticipant): Int = 0 + + val buff = object : Buff() { + override val name: String = "Elixir of Draenic Wisdom" + override val icon: String = "inv_potion_155.jpg" + override val durationMs: Int = 60 * 60 * 1000 + override val mutex: List = listOf(Mutex.GUARDIAN_ELIXIR) + + override fun modifyStats(sp: SimParticipant): Stats { + return Stats(intellect = 30, spirit = 30) + } + } + + override fun cast(sp: SimParticipant) { + sp.addBuff(buff) + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/data/abilities/generic/FlameCap.kt b/src/commonMain/kotlin/data/abilities/generic/FlameCap.kt new file mode 100644 index 000000000..e034c37b5 --- /dev/null +++ b/src/commonMain/kotlin/data/abilities/generic/FlameCap.kt @@ -0,0 +1,33 @@ +package data.abilities.generic + +import character.* +import sim.SimParticipant + +class FlameCap : Ability() { + companion object { + const val name = "Flame Cap" + const val icon: String = "inv_misc_herb_flamecap.jpg" + } + + override val id: Int = 22788 + override val name: String = Companion.name + override val icon: String = Companion.icon + override fun gcdMs(sp: SimParticipant): Int = 0 + override val castableOnGcd = true + override val sharedCooldown: SharedCooldown = SharedCooldown.RUNE_OR_MANA_GEM + override fun cooldownMs(sp: SimParticipant): Int = 180000 + + val buff = object : Buff() { + override val name: String = Companion.name + override val icon: String = Companion.icon + override val durationMs: Int = 60000 + + override fun modifyStats(sp: SimParticipant): Stats { + return Stats(fireDamage = 80) + } + } + + override fun cast(sp: SimParticipant) { + sp.addBuff(buff) + } +} diff --git a/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt b/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt index 62df0bb28..ca2ca9b1e 100644 --- a/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt +++ b/src/commonMain/kotlin/data/abilities/generic/GenericAbilities.kt @@ -15,6 +15,7 @@ object GenericAbilities { ElixirOfDraenicWisdom.name -> ElixirOfDraenicWisdom() ElixirOfMajorAgility.name -> ElixirOfMajorAgility() ElixirOfMajorStrength.name -> ElixirOfMajorStrength() + FlameCap.name -> FlameCap() FlaskOfBlindingLight.name -> FlaskOfBlindingLight() FlaskOfPureDeath.name -> FlaskOfPureDeath() FlaskOfRelentlessAssault.name -> FlaskOfRelentlessAssault() diff --git a/src/commonMain/kotlin/data/abilities/generic/Innervate.kt b/src/commonMain/kotlin/data/abilities/generic/Innervate.kt index 684e3a314..228966b16 100644 --- a/src/commonMain/kotlin/data/abilities/generic/Innervate.kt +++ b/src/commonMain/kotlin/data/abilities/generic/Innervate.kt @@ -1,2 +1,35 @@ -package data.abilities.generic +package data.abilities.generic +import character.Ability +import character.Buff +import character.Stats +import mechanics.General +import sim.SimParticipant + +class Innervate : Ability() { + companion object { + const val name = "Innervate" + } + + override val id: Int = 29166 + override val name: String = Companion.name + override val icon: String = "spell_nature_lightning.jpg" + override fun gcdMs(sp: SimParticipant): Int = 0 + override val castableOnGcd = true + override fun cooldownMs(sp: SimParticipant): Int = 720000 + + val buff = object : Buff() { + override val name: String = Companion.name + override val icon: String = "spell_nature_lightning.jpg" + override val durationMs: Int = 20000 + + //NOTE: This assumes arcane meditation and mage armor. Unsure how to detect actual value. + override fun modifyStats(sp: SimParticipant): Stats { + return Stats(manaPer5Seconds = (General.mp5FromSpiritNotCasting(sp) * 4.4).toInt()) + } + } + + override fun cast(sp: SimParticipant) { + sp.addBuff(buff) + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt b/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt index 684e3a314..14d1edc58 100644 --- a/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt +++ b/src/commonMain/kotlin/data/abilities/generic/ScrollOfSpiritV.kt @@ -1,2 +1,30 @@ -package data.abilities.generic +package data.abilities.generic +import character.* +import sim.SimParticipant + +class ScrollOfSpiritV : Ability() { + companion object { + const val name = "Scroll of Spirit V" + } + + override val id: Int = 27501 + override val name: String = Companion.name + override val icon: String = "inv_scroll_01.jpg" + override fun gcdMs(sp: SimParticipant): Int = 0 + + val buff = object : Buff() { + override val name: String = "Scroll of Spirit V" + override val icon: String = "inv_scroll_01.jpg" + override val durationMs: Int = 30 * 60 * 1000 + override val mutex: List = listOf(Mutex.BUFF_SPIRIT) + + override fun modifyStats(sp: SimParticipant): Stats { + return Stats(spirit = 30) + } + } + + override fun cast(sp: SimParticipant) { + sp.addBuff(buff) + } +} From c56e79419133ebe4b5c505b8e31d67cf19fea66c Mon Sep 17 00:00:00 2001 From: borbrunpagle Date: Thu, 6 Jan 2022 23:04:03 -0500 Subject: [PATCH 4/6] Make other hit deltas negative. --- src/commonMain/kotlin/character/Spec.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commonMain/kotlin/character/Spec.kt b/src/commonMain/kotlin/character/Spec.kt index 76002d260..84d2e1214 100644 --- a/src/commonMain/kotlin/character/Spec.kt +++ b/src/commonMain/kotlin/character/Spec.kt @@ -14,7 +14,7 @@ abstract class Spec { Triple("meleeCritRating", Stats(meleeCritRating = 5.0 * Rating.critPerPct), 5.0 * Rating.critPerPct), Triple("physicalHitRating", Stats(physicalHitRating = -5.0 * Rating.physicalHitPerPct), -5.0 * Rating.physicalHitPerPct), Triple("physicalHasteRating", Stats(physicalHasteRating = 5.0 * Rating.hastePerPct), 5.0 * Rating.hastePerPct), - Triple("expertiseRating", Stats(expertiseRating = 2.0 * Rating.expertisePerPct), 2.0 * Rating.expertisePerPct), + Triple("expertiseRating", Stats(expertiseRating = -2.0 * Rating.expertisePerPct), -2.0 * Rating.expertisePerPct), Triple("armorPen", Stats(armorPen = 100), 100.0), ) @@ -23,7 +23,7 @@ abstract class Spec { val defaultRangedDeltas: List = listOf( Triple("agility", Stats(agility = 50), 50.0), Triple("rangedCritRating", Stats(rangedCritRating = 5.0 * Rating.critPerPct), 5.0 * Rating.critPerPct), - Triple("physicalHitRating", Stats(physicalHitRating = 2.0 * Rating.physicalHitPerPct), 2.0 * Rating.physicalHitPerPct), + Triple("physicalHitRating", Stats(physicalHitRating = -2.0 * Rating.physicalHitPerPct), -2.0 * Rating.physicalHitPerPct), Triple("physicalHasteRating", Stats(physicalHasteRating = 5.0 * Rating.hastePerPct), 5.0 * Rating.hastePerPct), Triple("armorPen", Stats(armorPen = 100), 100.0) ) @@ -37,7 +37,7 @@ abstract class Spec { ) val defaultCasterDeltas: List = listOf( Triple("intellect", Stats(intellect = 50), 50.0), - Triple("spellHasteRating", Stats(spellHasteRating = 10.0 * Rating.hastePerPct), 10.0 * Rating.hastePerPct), + Triple("spellHasteRating", Stats(spellHasteRating = 5.0 * Rating.hastePerPct), 5.0 * Rating.hastePerPct), ) + casterHybridDeltas } abstract val name: String From f90648f7dc511d994c8b4e0d92365ba584773faa Mon Sep 17 00:00:00 2001 From: borbrunpagle Date: Thu, 6 Jan 2022 23:10:30 -0500 Subject: [PATCH 5/6] Comment updates and blue socket ep adjustment. --- .../kotlin/character/classes/mage/specs/Arcane.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt b/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt index 744979d0e..6018910e6 100644 --- a/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt +++ b/src/commonMain/kotlin/character/classes/mage/specs/Arcane.kt @@ -3,6 +3,7 @@ package character.classes.mage.specs import character.Spec import character.SpecEpDelta import character.Stats +import kotlin.math.max class Arcane : Spec() { override val name: String = "Arcane" @@ -17,12 +18,12 @@ class Arcane : Spec() { } override fun yellowSocketEp(deltas: Map): Double { - // 5 spell haste rating / 6 spell damage + // 10 int return ((deltas["intellect"] ?: 0.0) * 10.0) } override fun blueSocketEp(deltas: Map): Double { - // 6 spell dmg - return 6.0 + // 5 int (+mp5, worth nearly nothing) or 10 spirit, whichever turns out to be better. + return max((deltas["intellect"] ?: 0.0) * 5.0, (deltas["spirit"] ?: 0.0) * 10.0) } } From 9866b48b2aa3a0790c52a2f34206287ea6816c0c Mon Sep 17 00:00:00 2001 From: borbrunpagle Date: Thu, 6 Jan 2022 23:24:38 -0500 Subject: [PATCH 6/6] Remove imp spirit from mutex, since it's not implemented as a self-contained spirit buff. --- .../kotlin/data/abilities/raid/ImprovedDivineSpirit.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt b/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt index f95814682..62df67ddf 100644 --- a/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt +++ b/src/commonMain/kotlin/data/abilities/raid/ImprovedDivineSpirit.kt @@ -21,7 +21,6 @@ class ImprovedDivineSpirit : Ability() { override val name: String = Companion.name override val icon: String = "spell_holy_prayerofspirit.jpg" override val durationMs: Int = -1 - override val mutex: List = listOf(Mutex.BUFF_SPIRIT) override fun modifyStats(sp: SimParticipant): Stats { // assumes max rank