; Immolator's OpenBot Frost Mage Routine ; ; History: ; Legend: E = Enhancement, F = Fix, C = Change ; v1.0.0 ; E: First version, put up a skeleton for all the necessary functions ; E: Faces mob while casting ; E: Eats, drinks and buffs ; E: Combat added, pulls and fights ; E: Uses Ice Barrier ; E: Uses Evocation ; E: Uses Water Elemental ; v1.0.1 ; F: Fixed constant unnecessary downtime ; F: Removed an unused variable ; F: Fixed major bug in alpha version that made routine unusable ; E: Rewrote rest routine (stability/intelligence) ; E: Rewrote combat routine (stability/intelligence) ; E: Rewrote pull routine (stability/intelligence) ; v1.0.2 ; E: Added Counterspell support ; E: Improved Water Elemental support ; E: Simplified a whole bunch of code whilst maintaining functionality ; E: Added mana gem support ; v1.0.3 ; E: Commented a lot more of the code ; F: Fixed a bug with the water elemental ; F: Fixed Evocation (Large bug) ; v1.0.4 ; F: Removed some unnecessary code (oToon updates) ; E: Improved Water Elemental casting ; C: Changed the way casting/buffing is done (oToon updates) ; E: Added in range checks (oToon updates) ; ; Todo: ; Better combat sequence ; Bandages ; Potions ; Scrolls ; Polymorph ; Better Water Elemental ; Better Evocation ; Fix buggy downtime sequence ; Wards ; Immunity detection ; Mana shield on panic ; Trinkets ; Racials objectdef oClass inherits oBase { ; Customize these variables to suit your needs: variable int PullRange = 35 ; The spell used to pull mobs variable string PullSpell = "Frostbolt" ; The armour spell used (Ice Armour, Frost Armour, Mage Armour) variable string ArmourBuff = "Ice Armor" ; Whether to use Dampen Magic or not variable bool UseDampen = TRUE ; Whether to use Polymorph or not - Not used yet variable bool UsePoly = TRUE ; Whether to use spell wards (Fire/Frost) - Not used yet variable bool UseWards = TRUE ; Rest when at this amount of mana variable int MinMana = 70 ; Stop resting when at this amount of mana variable int MaxMana = 90 ; Rest when at this amount of health variable int MinHealth = 70 ; Stop resting when at this amount of health variable int MaxHealth = 90 ; Do not change the variables below this line, they are set by the routine variable string ManaGem = NULL variable bool UseFireWard = FALSE variable bool UseFrostWard = FALSE variable bool ImmuneFrost = FALSE variable bool ImmuneFire = FALSE variable bool NeedRegen = FALSE method Initialize() { ; Get the latest mana gem and store it for later use This.ManaGem:Set[${This.GetManaGem}] } method CastingPulse() { } method RestPulse() { ; Stand up when we're full, so we can cast if (${Me.PctMana} > ${This.MaxMana}) && (${Me.PctHPs} > ${This.MaxHealth}) { Toon:Standup } ; Don't attempt to do anything while eating/drinking if ${Me.Buff[Drink](exists)} || ${Me.Buff[Eat](exists)} { return } ; Check if we have water, if we don't, and we have free bag slots, then conjure some if !${Consumable.HasDrink} && (${Inventory.GetBagsInfo[RETRIEVE_FREESLOTS,"normal"]} > 0 ) && ${Toon.CastSpellOnSelf[Conjure Water]} { return } ; Check if we have food, if we don't, and we have free bag slots, then conjure some if !${Consumable.HasFood} && (${Inventory.GetBagsInfo[RETRIEVE_FREESLOTS,"normal"]} > 0 ) && ${Toon.CastSpellOnSelf[Conjure Food]} { return } ; Check if we have the highest available mana gem, if we don't, and we have free bag slots, then conjure one if !${Item[${This.ManaGem}](exists)} && (${Inventory.GetBagsInfo[RETRIEVE_FREESLOTS,"normal"]} > 0 ) && ${Toon.CastSpellOnSelf[Conjure ${This.ManaGem}]} { return } ; Make sure we our the desired armour buff if ${Toon.EnsureBuffOnSelf[${This.ArmourBuff}]} { return } ; Make sure we have AI if ${Toon.EnsureBuffOnSelf[Arcane Intellect]} { return } ; If we want to use dampen magic, then make sure we're using it if ${This.UseDampen} && ${Toon.EnsureBuffOnSelf[Dampen Magic]} { return } if (${Consumable.HasDrink} && !${Me.Buff[Drink](exists)} && (${Me.PctMana} < ${This.MaxMana})) || (${Consumable.HasFood} && !${Me.Buff[Food](exists)} && (${Me.PctHPs} < ${This.MaxHealth})) { ; Drink if we need to if ${Consumable.HasDrink} && !${Me.Buff[Drink](exists)} && (${Me.PctMana} < ${This.MaxMana}) { Consumable:useDrink } ; Eat if we need to if ${Consumable.HasFood} && !${Me.Buff[Food](exists)} && (${Me.PctHPs} < ${This.MaxHealth}) { Consumable:useFood } return } } member NeedRest() { ; Rest if we don't have any drinks, and we have a conjure spell if !${Consumable.HasDrink} && ${Spell[Conjure Water](exists)} { return TRUE } ; Rest if we don't have any food, and we have a conjure spell if !${Consumable.HasFood} && ${Spell[Conjure Food](exists)} { return TRUE } ; Rest if we don't have a mana gem, and we have a conjure spell if !${Item[${This.ManaGem}](exists)} && ${This.CheckSpell[Conjure ${This.ManaGem}]} { return TRUE } ; Rest if we need our desired armour buff if ${Toon.NeedBuffOnSelf[${This.ArmourBuff}]} { return TRUE } ; Rest if we need AI if ${Toon.NeedBuffOnSelf[Arcane Intellect]} { return TRUE } ; Rest if we want to use dampen, and we need it if ${This.UseDampen} && ${Toon.NeedBuffOnSelf[Dampen Magic]} { return TRUE } ; Rest if we're below the desired health/mana threshold if (${Me.PctMana} < ${This.MaxMana}) || (${Me.PctHPs} < ${This.MaxHealth}) { return TRUE } ; If we get to here then we don't need to rest, so we can return false return FALSE } method PullPulse() { if ${Toon.InMelee} { ; Make sure we have Ice Barrier on pull if ${Toon.CastSpellOnTarget[Ice Barrier]} { return } ; Make sure we have our Water Elemental on pull if ${Toon.CastSpellOnTarget[Summon Water Elemental]} { return } ; Cast our pull spell on the target if ${Toon.CastSpellGUID[${Targeting.TargetCollection.Get[1]},${PullSpell}]} { return } ; Get our pet to attack if ${Me.Pet(exists)} && !${Me.Pet.Aggro} && !${Me.Pet.Casting(exists)} { Toon:PetSkillByName[Waterbolt] return } } if ${Toon.InRanged} { ; Make sure we have Ice Barrier on pull if ${Toon.CastSpellOnTarget[Ice Barrier]} { return } ; Make sure we have our Water Elemental on pull if ${Toon.CastSpellOnTarget[Summon Water Elemental]} { return } ; Cast our pull spell on the target if ${Toon.CastSpellGUID[${Targeting.TargetCollection.Get[1]},${PullSpell}]} { return } ; Get our pet to attack if ${Me.Pet(exists)} && !${Me.Pet.Aggro} && !${Me.Pet.Casting(exists)} { Toon:PetSkillByName[Waterbolt] return } } } method AttackPulse() { if ${Toon.InMelee} { ; If our target is casting, then try to Counterspell it if ${Target.Casting(exists)} && ${Toon.CastSpellOnTarget[Counterspell]} { return } ; If we have Water Elemental out, then tell it to attack if ${Me.Pet(exists)} && !${Me.Pet.Aggro} && !${Me.Pet.Casting(exists)} { Toon:PetSkillByName[Waterbolt] } ; If we're out of mana, and Frost Nova and Evocation are ready, then attempt to Nova, back up, and Evocate if (${Target.Distance} < 10) && (${Me.PctMana} < 5) && ${This.CheckSpell[Frost Nova] } && ${This.CheckSpell[Evocation]} { if ${Toon.CastSpellOnTarget[Frost Nova]} { if ${Target.Distance} < 10 { Move Backward if ${Toon.CastSpellOnTarget[Evocation]} { return } return } return } return } ; If we're close enough to our target, then Frost Nova it if (${Target.Distance} < 10) && ${Toon.CastSpellOnTarget[Frost Nova]} { return } ; If we're out of range of our main nuke, then face our target get in range if (${Target.Distance} > 34) { Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}] Move Forward return } ; If the mob is frozen (by Nova or Frostbite) and we're close to it, then back up if (${Target.Buff[Frost Nova](exists)} || ${Target.Buff[Frostbite](exists)}) && (${Target.Distance} < 10) { Move Backward return } ; If we don't have Ice Barrier up then try to cast it if !${Me.Buff[Ice Barrier](exists)} && ${Toon.CastSpellOnTarget[Ice Barrier]} { return } ; If we're low on mana and we have a usable gem, then use it if ${Me.PctMana}<5 && ${Item[${This.ManaGem}].Usable} { Item[${This.ManaGem}]:Use return } ; If we're low on mana or the mob is low on health then Wand it if (${Me.PctMana}<5 || ${Target.PctHPs}<10) { if ${Toon.CastSpellOnTarget[Shoot]} { return } } ; If we're in range then use Cone of Cold if (${Target.Distance} < 8) && ${Toon.CastSpellOnTarget[Cone of Cold]} { return } ; If we're in range then use Fire Blast if (${Target.Distance} < 20) && ${Toon.CastSpellOnTarget[Fire Blast]} { return } ; If everything else has been done then use Frostbolt if ${Toon.CastSpellOnTarget[Frostbolt]} { return } } if ${Toon.InRanged} { ; If our target is casting, then try to Counterspell it if ${Target.Casting(exists)} && ${Toon.CastSpellOnTarget[Counterspell]} { return } ; If we have Water Elemental out, then tell it to attack if ${Me.Pet(exists)} && !${Me.Pet.Aggro} && !${Me.Pet.Casting(exists)} { Toon:PetSkillByName[Waterbolt] } ; If we're out of mana, and Frost Nova and Evocation are ready, then attempt to Nova, back up, and Evocate if (${Target.Distance} < 10) && (${Me.PctMana} < 5) && ${This.CheckSpell[Frost Nova] } && ${This.CheckSpell[Evocation]} { if ${Toon.CastSpellOnTarget[Frost Nova]} { if ${Target.Distance} < 10 { Move Backward if ${Toon.CastSpellOnTarget[Evocation]} { return } return } return } return } ; If we're close enough to our target, then Frost Nova it if (${Target.Distance} < 10) && ${Toon.CastSpellOnTarget[Frost Nova]} { return } ; If we're out of range of our main nuke, then face our target get in range if (${Target.Distance} > 34) { Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}] Move Forward return } ; If the mob is frozen (by Nova or Frostbite) and we're close to it, then back up if (${Target.Buff[Frost Nova](exists)} || ${Target.Buff[Frostbite](exists)}) && (${Target.Distance} < 10) { Move Backward return } ; If we don't have Ice Barrier up then try to cast it if !${Me.Buff[Ice Barrier](exists)} && ${Toon.CastSpellOnTarget[Ice Barrier]} { return } ; If we're low on mana and we have a usable gem, then use it if ${Me.PctMana}<5 && ${Item[${This.ManaGem}].Usable} { Item[${This.ManaGem}]:Use return } ; If we're low on mana or the mob is low on health then Wand it if (${Me.PctMana}<5 || ${Target.PctHPs}<10) { if ${Toon.CastSpellOnTarget[Shoot]} { return } } ; If we're in range then use Cone of Cold if (${Target.Distance} < 8) && ${Toon.CastSpellOnTarget[Cone of Cold]} { return } ; If we're in range then use Fire Blast if (${Target.Distance} < 20) && ${Toon.CastSpellOnTarget[Fire Blast]} { return } ; If everything else has been done then use Frostbolt if ${Toon.CastSpellOnTarget[Frostbolt]} { return } } } ; +-----------------------------------------------------------------------------------------------------+ ; | Name: CheckSpell | ; | Arguments: String (Spell to check) | ; | Returns: Bool(If spell is ready or not) | ; | Description: Checks if a spell is ready for casting. | ; +-----------------------------------------------------------------------------------------------------+ member CheckSpell(string spellname) { ; Check if the spell exists, is not on cooldown, we have the required mana, and the spell is usable. If so, then return true. if ${Spell[${spellname}](exists)} && !${Spell[${spellname}].Cooldown} && (${Me.CurrentMana} >= ${Spell[${SpellName}].Mana}) && ${Spell[${spellname}].Action.Usable} { return TRUE } ; If any of the above return false, then the spell isn't ready for one or more reasons, so return false return FALSE } ; +-----------------------------------------------------------------------------------------------------+ ; | Name: GetManaGem | ; | Arguments: None | ; | Returns: String (Mana Gem name) | ; | Description: Finds highest available mana gem. | ; +-----------------------------------------------------------------------------------------------------+ member GetManaGem() { if ${Spell[Conjure Mana Emerald](exists)} { return "Mana Emerald" } if ${Spell[Conjure Mana Ruby](exists)} { return "Mana Ruby" } if ${Spell[Conjure Mana Citrine](exists)} { return "Mana Citrine" } if ${Spell[Conjure Mana Jade](exists)} { return "Mana Jade" } if ${Spell[Conjure Mana Agate](exists)} { return "Mana Agate" } ; If we don't have any mana gem spells available, then just return NULL return NULL } }