Quantcast

Mage: Allow for Frostfire Bolt to replace Fireball for fire mages.

Johnny C. Lam [12-08-14 - 06:20]
Mage: Allow for Frostfire Bolt to replace Fireball for fire mages.

Various conditions checked for whether a Fireball spell was in flight.
Allow those conditions to be satisfied by an in-flight Frostfire Bolt
because those two spells have the same effect for a fire mage, especially
if using Glyph of Frostfire Bolt while soloing.
Filename
SimulationCraft.lua
scripts/ovale_mage.lua
scripts/ovale_mage_spells.lua
scripts/simulationcraft_mage_fire.lua
diff --git a/SimulationCraft.lua b/SimulationCraft.lua
index c0c626b..44b15e3 100644
--- a/SimulationCraft.lua
+++ b/SimulationCraft.lua
@@ -1961,14 +1961,15 @@ EmitOperandAction = function(operand, parseNode, nodeList, annotation, action, t
 		property = operand
 	end

-	name = Disambiguate(name, annotation.class, annotation.specialization)
+	local class, specialization = annotation.class, annotation.specialization
+	name = Disambiguate(name, class, specialization)
 	target = target and (target .. ".") or ""
 	local buffName = name .. "_debuff"
-	buffName = Disambiguate(buffName, annotation.class, annotation.specialization)
+	buffName = Disambiguate(buffName, class, specialization)
 	local prefix = strfind(buffName, "_buff$") and "Buff" or "Debuff"
 	local buffTarget = (prefix == "Debuff") and "target." or target
 	local talentName = name .. "_talent"
-	talentName = Disambiguate(talentName, annotation.class, annotation.specialization)
+	talentName = Disambiguate(talentName, class, specialization)
 	local symbol = name

 	local code
@@ -2692,6 +2693,13 @@ EmitOperandSpecial = function(operand, parseNode, nodeList, annotation, action,
 		-- The "careful_aim" buff is a fake SimulationCraft buff.
 		code = format("%sHealthPercent() > 80 or BuffPresent(rapid_fire_buff)", target)
 		AddSymbol(annotation, "rapid_fire_buff")
+	elseif class == "MAGE" and (operand == "in_flight" and action == "fireball" or operand == "action.fireball.in_flight") then
+		-- Frostfire Bolt can be substituted for Fireball when testing whether the spell is in flight.
+		local fbName = "fireball"
+		local ffbName = "frostfire_bolt"
+		code = format("InFlightToTarget(%s) or InFlightToTarget(%s)", fbName, ffbName)
+		AddSymbol(annotation, fbName)
+		AddSymbol(annotation, ffbName)
 	elseif class == "MAGE" and operand == "buff.rune_of_power.remains" then
 		code = "RuneOfPowerRemaining()"
 	elseif class == "MAGE" and operand == "dot.frozen_orb.ticking" then
diff --git a/scripts/ovale_mage.lua b/scripts/ovale_mage.lua
index 28e0a39..db550a9 100644
--- a/scripts/ovale_mage.lua
+++ b/scripts/ovale_mage.lua
@@ -453,7 +453,7 @@ AddFunction FireDefaultShortCdActions
 	#call_action_list,name=init_combust,if=!pyro_chain
 	if not GetState(pyro_chain) > 0 FireInitCombustShortCdActions()
 	#rune_of_power,if=buff.rune_of_power.remains<action.fireball.execute_time+gcd.max&!(buff.heating_up.up&action.fireball.in_flight)
-	if RuneOfPowerRemaining() < ExecuteTime(fireball) + GCD() and not { BuffPresent(heating_up_buff) and InFlightToTarget(fireball) } Spell(rune_of_power)
+	if RuneOfPowerRemaining() < ExecuteTime(fireball) + GCD() and not { BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } Spell(rune_of_power)
 	#call_action_list,name=aoe,if=active_enemies>=4
 	if Enemies() >= 4 FireAoeShortCdActions()
 	#call_action_list,name=single_target
@@ -477,10 +477,10 @@ AddFunction FireDefaultCdActions
 		#call_action_list,name=init_combust,if=!pyro_chain
 		if not GetState(pyro_chain) > 0 FireInitCombustCdActions()

-		unless RuneOfPowerRemaining() < ExecuteTime(fireball) + GCD() and not { BuffPresent(heating_up_buff) and InFlightToTarget(fireball) } and Spell(rune_of_power)
+		unless RuneOfPowerRemaining() < ExecuteTime(fireball) + GCD() and not { BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } and Spell(rune_of_power)
 		{
 			#mirror_image,if=!(buff.heating_up.up&action.fireball.in_flight)
-			if not { BuffPresent(heating_up_buff) and InFlightToTarget(fireball) } Spell(mirror_image)
+			if not { BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } Spell(mirror_image)
 			#call_action_list,name=aoe,if=active_enemies>=4
 			if Enemies() >= 4 FireAoeCdActions()
 			#call_action_list,name=single_target
@@ -561,7 +561,7 @@ AddFunction FireCombustSequenceActions
 	#inferno_blast,if=set_bonus.tier16_4pc_caster&(buff.pyroblast.up^buff.heating_up.up)
 	if ArmorSetBonus(T16_caster 4) and { BuffPresent(pyroblast_buff) xor BuffPresent(heating_up_buff) } Spell(inferno_blast)
 	#fireball,if=!dot.ignite.ticking&!in_flight
-	if not target.DebuffPresent(ignite_debuff) and not InFlightToTarget(fireball) Spell(fireball)
+	if not target.DebuffPresent(ignite_debuff) and not { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } Spell(fireball)
 	#pyroblast,if=buff.pyroblast.up
 	if BuffPresent(pyroblast_buff) Spell(pyroblast)
 	#inferno_blast,if=talent.meteor.enabled&cooldown.meteor.duration-cooldown.meteor.remains<gcd.max*3
@@ -579,7 +579,7 @@ AddFunction FireCombustSequenceShortCdActions

 	unless ArmorSetBonus(T17 4) and BuffPresent(pyromaniac_buff) and Spell(pyroblast)
 		or ArmorSetBonus(T16_caster 4) and BuffPresent(pyroblast_buff) xor BuffPresent(heating_up_buff) and Spell(inferno_blast)
-		or not target.DebuffPresent(ignite_debuff) and not InFlightToTarget(fireball) and Spell(fireball)
+		or not target.DebuffPresent(ignite_debuff) and not { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } and Spell(fireball)
 		or BuffPresent(pyroblast_buff) and Spell(pyroblast)
 		or Talent(meteor_talent) and SpellCooldownDuration(meteor) - SpellCooldown(meteor) < GCD() * 3 and Spell(inferno_blast)
 	{
@@ -643,13 +643,13 @@ AddFunction FireCrystalSequenceCdActions
 AddFunction FireInitCombustActions
 {
 	#start_pyro_chain,if=talent.meteor.enabled&cooldown.meteor.up&((cooldown.combustion.remains<gcd.max*3&buff.pyroblast.up&(buff.heating_up.up^action.fireball.in_flight))|(buff.pyromaniac.up&(cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*gcd.max)))
-	if Talent(meteor_talent) and not SpellCooldown(meteor) > 0 and { SpellCooldown(combustion) < GCD() * 3 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor InFlightToTarget(fireball) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
+	if Talent(meteor_talent) and not SpellCooldown(meteor) > 0 and { SpellCooldown(combustion) < GCD() * 3 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
 	#start_pyro_chain,if=talent.prismatic_crystal.enabled&cooldown.prismatic_crystal.up&((cooldown.combustion.remains<gcd.max*2&buff.pyroblast.up&(buff.heating_up.up^action.fireball.in_flight))|(buff.pyromaniac.up&(cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*gcd.max)))
-	if Talent(prismatic_crystal_talent) and not SpellCooldown(prismatic_crystal) > 0 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor InFlightToTarget(fireball) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
+	if Talent(prismatic_crystal_talent) and not SpellCooldown(prismatic_crystal) > 0 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
 	#start_pyro_chain,if=talent.prismatic_crystal.enabled&!glyph.combustion.enabled&cooldown.prismatic_crystal.remains>20&((cooldown.combustion.remains<gcd.max*2&buff.pyroblast.up&buff.heating_up.up&action.fireball.in_flight)|(buff.pyromaniac.up&(cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*gcd.max)))
-	if Talent(prismatic_crystal_talent) and not Glyph(glyph_of_combustion) and SpellCooldown(prismatic_crystal) > 20 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
+	if Talent(prismatic_crystal_talent) and not Glyph(glyph_of_combustion) and SpellCooldown(prismatic_crystal) > 20 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
 	#start_pyro_chain,if=!talent.prismatic_crystal.enabled&!talent.meteor.enabled&((cooldown.combustion.remains<gcd.max*4&buff.pyroblast.up&buff.heating_up.up&action.fireball.in_flight)|(buff.pyromaniac.up&cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*(gcd.max+talent.kindling.enabled)))
-	if not Talent(prismatic_crystal_talent) and not Talent(meteor_talent) and { SpellCooldown(combustion) < GCD() * 4 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * { GCD() + Talent(kindling_talent) } } SetState(pyro_chain 1)
+	if not Talent(prismatic_crystal_talent) and not Talent(meteor_talent) and { SpellCooldown(combustion) < GCD() * 4 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * { GCD() + Talent(kindling_talent) } } SetState(pyro_chain 1)
 }

 AddFunction FireInitCombustShortCdActions
@@ -721,13 +721,13 @@ AddFunction FireSingleTargetActions
 	#pyroblast,if=set_bonus.tier17_4pc&buff.pyromaniac.react
 	if ArmorSetBonus(T17 4) and BuffPresent(pyromaniac_buff) Spell(pyroblast)
 	#pyroblast,if=buff.pyroblast.up&buff.heating_up.up&action.fireball.in_flight
-	if BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) Spell(pyroblast)
+	if BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } Spell(pyroblast)
 	#inferno_blast,if=buff.pyroblast.down&buff.heating_up.up
 	if BuffExpires(pyroblast_buff) and BuffPresent(heating_up_buff) Spell(inferno_blast)
 	#call_action_list,name=active_talents
 	FireActiveTalentsActions()
 	#inferno_blast,if=buff.pyroblast.up&buff.heating_up.down&!action.fireball.in_flight
-	if BuffPresent(pyroblast_buff) and BuffExpires(heating_up_buff) and not InFlightToTarget(fireball) Spell(inferno_blast)
+	if BuffPresent(pyroblast_buff) and BuffExpires(heating_up_buff) and not { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } Spell(inferno_blast)
 	#fireball
 	Spell(fireball)
 	#scorch,moving=1
@@ -740,7 +740,7 @@ AddFunction FireSingleTargetShortCdActions
 		or BuffPresent(pyroblast_buff) and BuffRemaining(pyroblast_buff) < ExecuteTime(fireball) and Spell(pyroblast)
 		or ArmorSetBonus(T16_caster 2) and BuffPresent(pyroblast_buff) and BuffPresent(potent_flames_buff) and BuffRemaining(potent_flames_buff) < GCD() and Spell(pyroblast)
 		or ArmorSetBonus(T17 4) and BuffPresent(pyromaniac_buff) and Spell(pyroblast)
-		or BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) and Spell(pyroblast)
+		or BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } and Spell(pyroblast)
 		or BuffExpires(pyroblast_buff) and BuffPresent(heating_up_buff) and Spell(inferno_blast)
 	{
 		#call_action_list,name=active_talents
@@ -754,7 +754,7 @@ AddFunction FireSingleTargetCdActions
 		or BuffPresent(pyroblast_buff) and BuffRemaining(pyroblast_buff) < ExecuteTime(fireball) and Spell(pyroblast)
 		or ArmorSetBonus(T16_caster 2) and BuffPresent(pyroblast_buff) and BuffPresent(potent_flames_buff) and BuffRemaining(potent_flames_buff) < GCD() and Spell(pyroblast)
 		or ArmorSetBonus(T17 4) and BuffPresent(pyromaniac_buff) and Spell(pyroblast)
-		or BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) and Spell(pyroblast)
+		or BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } and Spell(pyroblast)
 		or BuffExpires(pyroblast_buff) and BuffPresent(heating_up_buff) and Spell(inferno_blast)
 	{
 		#call_action_list,name=active_talents
diff --git a/scripts/ovale_mage_spells.lua b/scripts/ovale_mage_spells.lua
index 3694722..a559c5e 100644
--- a/scripts/ovale_mage_spells.lua
+++ b/scripts/ovale_mage_spells.lua
@@ -115,6 +115,7 @@ Define(glyph_of_cone_of_cold 115705)
 Define(glyph_of_counterspell 115703)
 Define(glyph_of_deep_freeze 115710)
 Define(glyph_of_dragons_breath 159485)
+Define(glyph_of_frostfire_bolt 61205)
 Define(glyph_of_icy_veins 56364)
 Define(glyph_of_rapid_displacement 146659)
 Define(heating_up_buff 48107)
diff --git a/scripts/simulationcraft_mage_fire.lua b/scripts/simulationcraft_mage_fire.lua
index 5bd9ae2..6646b57 100644
--- a/scripts/simulationcraft_mage_fire.lua
+++ b/scripts/simulationcraft_mage_fire.lua
@@ -56,9 +56,9 @@ AddFunction FireDefaultActions
 	#call_action_list,name=init_combust,if=!pyro_chain
 	if not GetState(pyro_chain) > 0 FireInitCombustActions()
 	#rune_of_power,if=buff.rune_of_power.remains<action.fireball.execute_time+gcd.max&!(buff.heating_up.up&action.fireball.in_flight)
-	if RuneOfPowerRemaining() < ExecuteTime(fireball) + GCD() and not { BuffPresent(heating_up_buff) and InFlightToTarget(fireball) } Spell(rune_of_power)
+	if RuneOfPowerRemaining() < ExecuteTime(fireball) + GCD() and not { BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } Spell(rune_of_power)
 	#mirror_image,if=!(buff.heating_up.up&action.fireball.in_flight)
-	if not { BuffPresent(heating_up_buff) and InFlightToTarget(fireball) } Spell(mirror_image)
+	if not { BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } Spell(mirror_image)
 	#call_action_list,name=aoe,if=active_enemies>=4
 	if Enemies() >= 4 FireAoeActions()
 	#call_action_list,name=single_target
@@ -114,7 +114,7 @@ AddFunction FireCombustSequenceActions
 	#inferno_blast,if=set_bonus.tier16_4pc_caster&(buff.pyroblast.up^buff.heating_up.up)
 	if ArmorSetBonus(T16_caster 4) and { BuffPresent(pyroblast_buff) xor BuffPresent(heating_up_buff) } Spell(inferno_blast)
 	#fireball,if=!dot.ignite.ticking&!in_flight
-	if not target.DebuffPresent(ignite_debuff) and not InFlightToTarget(fireball) Spell(fireball)
+	if not target.DebuffPresent(ignite_debuff) and not { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } Spell(fireball)
 	#pyroblast,if=buff.pyroblast.up
 	if BuffPresent(pyroblast_buff) Spell(pyroblast)
 	#inferno_blast,if=talent.meteor.enabled&cooldown.meteor.duration-cooldown.meteor.remains<gcd.max*3
@@ -136,13 +136,13 @@ AddFunction FireCrystalSequenceActions
 AddFunction FireInitCombustActions
 {
 	#start_pyro_chain,if=talent.meteor.enabled&cooldown.meteor.up&((cooldown.combustion.remains<gcd.max*3&buff.pyroblast.up&(buff.heating_up.up^action.fireball.in_flight))|(buff.pyromaniac.up&(cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*gcd.max)))
-	if Talent(meteor_talent) and not SpellCooldown(meteor) > 0 and { SpellCooldown(combustion) < GCD() * 3 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor InFlightToTarget(fireball) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
+	if Talent(meteor_talent) and not SpellCooldown(meteor) > 0 and { SpellCooldown(combustion) < GCD() * 3 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
 	#start_pyro_chain,if=talent.prismatic_crystal.enabled&cooldown.prismatic_crystal.up&((cooldown.combustion.remains<gcd.max*2&buff.pyroblast.up&(buff.heating_up.up^action.fireball.in_flight))|(buff.pyromaniac.up&(cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*gcd.max)))
-	if Talent(prismatic_crystal_talent) and not SpellCooldown(prismatic_crystal) > 0 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor InFlightToTarget(fireball) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
+	if Talent(prismatic_crystal_talent) and not SpellCooldown(prismatic_crystal) > 0 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and { BuffPresent(heating_up_buff) xor { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
 	#start_pyro_chain,if=talent.prismatic_crystal.enabled&!glyph.combustion.enabled&cooldown.prismatic_crystal.remains>20&((cooldown.combustion.remains<gcd.max*2&buff.pyroblast.up&buff.heating_up.up&action.fireball.in_flight)|(buff.pyromaniac.up&(cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*gcd.max)))
-	if Talent(prismatic_crystal_talent) and not Glyph(glyph_of_combustion) and SpellCooldown(prismatic_crystal) > 20 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
+	if Talent(prismatic_crystal_talent) and not Glyph(glyph_of_combustion) and SpellCooldown(prismatic_crystal) > 20 and { SpellCooldown(combustion) < GCD() * 2 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * GCD() } SetState(pyro_chain 1)
 	#start_pyro_chain,if=!talent.prismatic_crystal.enabled&!talent.meteor.enabled&((cooldown.combustion.remains<gcd.max*4&buff.pyroblast.up&buff.heating_up.up&action.fireball.in_flight)|(buff.pyromaniac.up&cooldown.combustion.remains<ceil(buff.pyromaniac.remains%gcd.max)*(gcd.max+talent.kindling.enabled)))
-	if not Talent(prismatic_crystal_talent) and not Talent(meteor_talent) and { SpellCooldown(combustion) < GCD() * 4 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * { GCD() + Talent(kindling_talent) } } SetState(pyro_chain 1)
+	if not Talent(prismatic_crystal_talent) and not Talent(meteor_talent) and { SpellCooldown(combustion) < GCD() * 4 and BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } or BuffPresent(pyromaniac_buff) and SpellCooldown(combustion) < BuffRemaining(pyromaniac_buff) / GCD() * { GCD() + Talent(kindling_talent) } } SetState(pyro_chain 1)
 }

 AddFunction FireLivingBombActions
@@ -181,13 +181,13 @@ AddFunction FireSingleTargetActions
 	#pyroblast,if=set_bonus.tier17_4pc&buff.pyromaniac.react
 	if ArmorSetBonus(T17 4) and BuffPresent(pyromaniac_buff) Spell(pyroblast)
 	#pyroblast,if=buff.pyroblast.up&buff.heating_up.up&action.fireball.in_flight
-	if BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and InFlightToTarget(fireball) Spell(pyroblast)
+	if BuffPresent(pyroblast_buff) and BuffPresent(heating_up_buff) and { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } Spell(pyroblast)
 	#inferno_blast,if=buff.pyroblast.down&buff.heating_up.up
 	if BuffExpires(pyroblast_buff) and BuffPresent(heating_up_buff) Spell(inferno_blast)
 	#call_action_list,name=active_talents
 	FireActiveTalentsActions()
 	#inferno_blast,if=buff.pyroblast.up&buff.heating_up.down&!action.fireball.in_flight
-	if BuffPresent(pyroblast_buff) and BuffExpires(heating_up_buff) and not InFlightToTarget(fireball) Spell(inferno_blast)
+	if BuffPresent(pyroblast_buff) and BuffExpires(heating_up_buff) and not { InFlightToTarget(fireball) or InFlightToTarget(frostfire_bolt) } Spell(inferno_blast)
 	#fireball
 	Spell(fireball)
 	#scorch,moving=1
@@ -223,6 +223,7 @@ AddIcon specialization=fire help=aoe
 # fireball
 # flamestrike
 # flamestrike_debuff
+# frostfire_bolt
 # glyph_of_combustion
 # glyph_of_dragons_breath
 # heating_up_buff