Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Explosives to SoD and add new ones from P2 #126

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions proto/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ enum Explosive {
ExplosiveSolidDynamite = 1;
ExplosiveDenseDynamite = 2;
ExplosiveThoriumGrenade = 3;
ExplosiveEzThroRadiationBomb = 4;
ExplosiveHighYieldRadiationBomb = 5;
}

enum Potions {
Expand Down
2 changes: 1 addition & 1 deletion sim/core/apl_actions_casting.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (rot *APLRotation) newActionCastSpell(config *proto.APLActionCastSpell) APL
}
}
func (action *APLActionCastSpell) IsReady(sim *Simulation) bool {
return action.spell.CanCast(sim, action.target.Get()) && (!action.spell.Flags.Matches(SpellFlagMCD) || action.spell.Unit.GCD.IsReady(sim))
return action.spell.CanCast(sim, action.target.Get()) && (!action.spell.Flags.Matches(SpellFlagMCD) || action.spell.Unit.GCD.IsReady(sim) || action.spell.DefaultCast.GCD == 0)
}
func (action *APLActionCastSpell) Execute(sim *Simulation) {
action.spell.Cast(sim, action.target.Get())
Expand Down
4 changes: 2 additions & 2 deletions sim/core/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc {
}

if effectiveTime := spell.CurCast.EffectiveTime(); effectiveTime != 0 {
if spell.Flags.Matches(SpellFlagHunterRanged) {
effectiveTime = min(effectiveTime, spell.Unit.GCD.TimeToReady(sim))
if spell.Flags.Matches(SpellFlagCastTimeNoGCD) {
effectiveTime = max(effectiveTime, spell.Unit.GCD.TimeToReady(sim))
}
spell.SpellMetrics[target.UnitIndex].TotalCastTime += effectiveTime
spell.Unit.SetGCDTimer(sim, sim.CurrentTime+effectiveTime)
Expand Down
118 changes: 108 additions & 10 deletions sim/core/consumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func applyConsumeEffects(agent Agent, partyBuffs *proto.PartyBuffs) {
})
}

if consumes.EnchantedSigil != proto.EnchantedSigil_UnknownSigil {
if character.HasProfession(proto.Profession_Enchanting) && consumes.EnchantedSigil != proto.EnchantedSigil_UnknownSigil {
switch consumes.EnchantedSigil {
case proto.EnchantedSigil_InnovationSigil:
character.AddStats(stats.Stats{
Expand Down Expand Up @@ -240,20 +240,19 @@ var SapperActionID = ActionID{ItemID: 10646}
var SolidDynamiteActionID = ActionID{ItemID: 10507}
var DenseDynamiteActionID = ActionID{ItemID: 18641}
var ThoriumGrenadeActionID = ActionID{ItemID: 15993}
var EzThroRadiationBombActionID = ActionID{ItemID: 215168}
var HighYieldRadiationBombActionID = ActionID{ItemID: 215127}

func registerExplosivesCD(agent Agent, consumes *proto.Consumes) {
character := agent.GetCharacter()
hasFiller := consumes.FillerExplosive != proto.Explosive_ExplosiveUnknown

if !character.HasProfession(proto.Profession_Engineering) {
return
}
if !consumes.Sapper && !hasFiller {
return
}
sharedTimer := character.NewTimer()

if consumes.Sapper {
if consumes.Sapper && character.HasProfession(proto.Profession_Engineering) {
character.AddMajorCooldown(MajorCooldown{
Spell: character.newSapperSpell(sharedTimer),
Type: CooldownTypeDPS | CooldownTypeExplosive,
Expand All @@ -262,6 +261,10 @@ func registerExplosivesCD(agent Agent, consumes *proto.Consumes) {
}

if hasFiller {
if consumes.FillerExplosive != proto.Explosive_ExplosiveEzThroRadiationBomb && !character.HasProfession(proto.Profession_Engineering) {
return
}

var filler *Spell
switch consumes.FillerExplosive {
case proto.Explosive_ExplosiveSolidDynamite:
Expand All @@ -270,6 +273,10 @@ func registerExplosivesCD(agent Agent, consumes *proto.Consumes) {
filler = character.newDenseDynamiteSpell(sharedTimer)
case proto.Explosive_ExplosiveThoriumGrenade:
filler = character.newThoriumGrenadeSpell(sharedTimer)
case proto.Explosive_ExplosiveEzThroRadiationBomb:
filler = character.newEzThroRadiationBombSpell(sharedTimer)
case proto.Explosive_ExplosiveHighYieldRadiationBomb:
filler = character.newHighYieldRadiationBombSpell(sharedTimer)
}

character.AddMajorCooldown(MajorCooldown{
Expand All @@ -281,16 +288,26 @@ func registerExplosivesCD(agent Agent, consumes *proto.Consumes) {
}

// Creates a spell object for the common explosive case.
func (character *Character) newBasicExplosiveSpellConfig(sharedTimer *Timer, actionID ActionID, school SpellSchool, minDamage float64, maxDamage float64, cooldown Cooldown, _ float64, _ float64) SpellConfig {
dealSelfDamage := actionID.SameAction(SapperActionID)
func (character *Character) newBasicExplosiveSpellConfig(sharedTimer *Timer, actionID ActionID, school SpellSchool, minDamage float64, maxDamage float64, cooldown Cooldown, selfMinDamage float64, selfMaxDamage float64) SpellConfig {
isSapper := actionID.SameAction(SapperActionID)

var defaultCast Cast
if !isSapper {
defaultCast = Cast{
CastTime: time.Second,
}
}

return SpellConfig{
ActionID: actionID,
SpellSchool: school,
ProcMask: ProcMaskEmpty,
Flags: SpellFlagCastTimeNoGCD,

Cast: CastConfig{
CD: cooldown,
DefaultCast: defaultCast,
CD: cooldown,
IgnoreHaste: true,
SharedCD: Cooldown{
Timer: sharedTimer,
Duration: time.Minute,
Expand All @@ -309,8 +326,8 @@ func (character *Character) newBasicExplosiveSpellConfig(sharedTimer *Timer, act
spell.CalcAndDealDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicHitAndCrit)
}

if dealSelfDamage {
baseDamage := sim.Roll(minDamage, maxDamage)
if isSapper {
baseDamage := sim.Roll(selfMinDamage, selfMaxDamage)
spell.CalcAndDealDamage(sim, &character.Unit, baseDamage, spell.OutcomeMagicHitAndCrit)
}
},
Expand All @@ -329,6 +346,87 @@ func (character *Character) newThoriumGrenadeSpell(sharedTimer *Timer) *Spell {
return character.GetOrRegisterSpell(character.newBasicExplosiveSpellConfig(sharedTimer, ThoriumGrenadeActionID, SpellSchoolFire, 300, 500, Cooldown{}, 0, 0))
}

// Creates a spell object for the common explosive case.
func (character *Character) newRadiationBombSpellConfig(sharedTimer *Timer, actionID ActionID, minDamage float64, maxDamage float64, dotDamage float64, cooldown Cooldown) SpellConfig {
return SpellConfig{
ActionID: actionID,
SpellSchool: SpellSchoolFire,
ProcMask: ProcMaskEmpty,
Flags: SpellFlagCastTimeNoGCD,

Cast: CastConfig{
DefaultCast: Cast{
CastTime: time.Second,
},
IgnoreHaste: true,
CD: cooldown,
SharedCD: Cooldown{
Timer: sharedTimer,
Duration: time.Minute,
},
},

// Explosives always have 1% resist chance, so just give them hit cap.
BonusHitRating: 100 * SpellHitRatingPerHitChance,
DamageMultiplier: 1,
CritMultiplier: 2,
ThreatMultiplier: 1,

Dot: DotConfig{
Aura: Aura{
Label: actionID.String(),
},

NumberOfTicks: 5,
TickLength: time.Second * 2,

OnSnapshot: func(sim *Simulation, target *Unit, dot *Dot, isRollover bool) {
// Use nature school for dot modifiers
dot.Spell.SpellSchool = SpellSchoolNature
dot.Spell.SchoolIndex = stats.SchoolIndexNature

dot.SnapshotBaseDamage = dotDamage

dot.SnapshotCritChance = dot.Spell.SpellCritChance(target)
dot.SnapshotAttackerMultiplier = dot.Spell.AttackerDamageMultiplier(dot.Spell.Unit.AttackTables[target.UnitIndex])

// Revert to fire school
dot.Spell.SpellSchool = SpellSchoolFire
dot.Spell.SchoolIndex = stats.SchoolIndexFire
},
OnTick: func(sim *Simulation, target *Unit, dot *Dot) {
// Use nature school for dot ticks
dot.Spell.SpellSchool = SpellSchoolNature
dot.Spell.SchoolIndex = stats.SchoolIndexNature

dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick)

// Revert to fire school
dot.Spell.SpellSchool = SpellSchoolFire
dot.Spell.SchoolIndex = stats.SchoolIndexFire
},
},

ApplyEffects: func(sim *Simulation, target *Unit, spell *Spell) {
for _, aoeTarget := range sim.Encounter.TargetUnits {
baseDamage := sim.Roll(minDamage, maxDamage) * sim.Encounter.AOECapMultiplier()

result := spell.CalcAndDealDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicHitAndCrit)

if result.Landed() {
spell.Dot(aoeTarget).Apply(sim)
}
}
},
}
}
func (character *Character) newEzThroRadiationBombSpell(sharedTimer *Timer) *Spell {
return character.GetOrRegisterSpell(character.newRadiationBombSpellConfig(sharedTimer, EzThroRadiationBombActionID, 112, 188, 10, Cooldown{}))
}
func (character *Character) newHighYieldRadiationBombSpell(sharedTimer *Timer) *Spell {
return character.GetOrRegisterSpell(character.newRadiationBombSpellConfig(sharedTimer, HighYieldRadiationBombActionID, 150, 250, 25, Cooldown{}))
}

func registerPotionCD(agent Agent, consumes *proto.Consumes) {
character := agent.GetCharacter()
defaultPotion := consumes.DefaultPotion
Expand Down
2 changes: 1 addition & 1 deletion sim/core/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ const (
SpellFlagPrepullPotion // Indicates this spell is the prepull potion.
SpellFlagCombatPotion // Indicates this spell is the combat potion.
SpellFlagResetAttackSwing // Indicates this spell resets the melee swing timer.
SpellFlagHunterRanged // Indicates this spell is hunters Auto shot spell
SpellFlagCastTimeNoGCD // Indicates this spell is hunters Auto shot spell
SpellFlagPureDot // Indicates this spell is a dot with no initial damage component

// Used to let agents categorize their spells.
Expand Down
2 changes: 1 addition & 1 deletion sim/hunter/hunter.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func NewHunter(character *core.Character, options *proto.Player) *Hunter {
AutoSwingMelee: true,
})

hunter.AutoAttacks.RangedConfig().Flags |= core.SpellFlagHunterRanged
hunter.AutoAttacks.RangedConfig().Flags |= core.SpellFlagCastTimeNoGCD
hunter.AutoAttacks.RangedConfig().Cast = core.CastConfig{
DefaultCast: core.Cast{
CastTime: time.Millisecond * 500,
Expand Down
Loading
Loading