Advertisement
krilton

Smn Gear

Sep 27th, 2014
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.60 KB | None | 0 0
  1. -------------------------------------------------------------------------------------------------------------------
  2. -- Setup functions for this job. Generally should not be modified.
  3. -------------------------------------------------------------------------------------------------------------------
  4.  
  5. -- Also, you'll need the Shortcuts addon to handle the auto-targetting of the custom pact commands.
  6.  
  7. --[[
  8. Custom commands:
  9.  
  10. gs c petweather
  11. Automatically casts the storm appropriate for the current avatar, if possible.
  12.  
  13. gs c siphon
  14. Automatically run the process to: dismiss the current avatar; cast appropriate
  15. weather; summon the appropriate spirit; Elemental Siphon; release the spirit;
  16. and re-summon the avatar.
  17.  
  18. Will not cast weather you do not have access to.
  19. Will not re-summon the avatar if one was not out in the first place.
  20. Will not release the spirit if it was out before the command was issued.
  21.  
  22. gs c pact [PactType]
  23. Attempts to use the indicated pact type for the current avatar.
  24. PactType can be one of:
  25. cure
  26. curaga
  27. buffOffense
  28. buffDefense
  29. buffSpecial
  30. debuff1
  31. debuff2
  32. sleep
  33. nuke2
  34. nuke4
  35. bp70
  36. bp75 (merits and lvl 75-80 pacts)
  37. astralflow
  38.  
  39. --]]
  40.  
  41.  
  42. -- Initialization function for this job file.
  43. function get_sets()
  44. mote_include_version = 2
  45.  
  46. -- Load and initialize the include file.
  47. include('Mote-Include.lua')
  48. end
  49.  
  50. -- Setup vars that are user-independent. state.Buff vars initialized here will automatically be tracked.
  51. function job_setup()
  52. state.Buff["Avatar's Favor"] = buffactive["Avatar's Favor"] or false
  53. state.Buff["Astral Conduit"] = buffactive["Astral Conduit"] or false
  54.  
  55. spirits = S{"LightSpirit", "DarkSpirit", "FireSpirit", "EarthSpirit", "WaterSpirit", "AirSpirit", "IceSpirit", "ThunderSpirit"}
  56. avatars = S{"Carbuncle", "Fenrir", "Diabolos", "Ifrit", "Titan", "Leviathan", "Garuda", "Shiva", "Ramuh", "Odin", "Alexander", "Cait Sith"}
  57.  
  58. magicalRagePacts = S{
  59. 'Inferno','Earthen Fury','Tidal Wave','Aerial Blast','Diamond Dust','Judgment Bolt','Searing Light','Howling Moon','Ruinous Omen',
  60. 'Fire II','Stone II','Water II','Aero II','Blizzard II','Thunder II',
  61. 'Fire IV','Stone IV','Water IV','Aero IV','Blizzard IV','Thunder IV',
  62. 'Thunderspark','Burning Strike','Meteorite','Nether Blast','Flaming Crush',
  63. 'Meteor Strike','Heavenly Strike','Wind Blade','Geocrush','Grand Fall','Thunderstorm',
  64. 'Holy Mist','Lunar Bay','Night Terror','Level ? Holy'}
  65.  
  66.  
  67. pacts = {}
  68. pacts.cure = {['Carbuncle']='Healing Ruby'}
  69. pacts.curaga = {['Carbuncle']='Healing Ruby II', ['Garuda']='Whispering Wind', ['Leviathan']='Spring Water'}
  70. pacts.buffoffense = {['Carbuncle']='Glittering Ruby', ['Ifrit']='Crimson Howl', ['Garuda']='Hastega', ['Ramuh']='Rolling Thunder',
  71. ['Fenrir']='Ecliptic Growl'}
  72. pacts.buffdefense = {['Carbuncle']='Shining Ruby', ['Shiva']='Frost Armor', ['Garuda']='Aerial Armor', ['Titan']='Earthen Ward',
  73. ['Ramuh']='Lightning Armor', ['Fenrir']='Ecliptic Howl', ['Diabolos']='Noctoshield', ['Cait Sith']='Reraise II'}
  74. pacts.buffspecial = {['Ifrit']='Inferno Howl', ['Garuda']='Fleet Wind', ['Titan']='Earthen Armor', ['Diabolos']='Dream Shroud',
  75. ['Carbuncle']='Soothing Ruby', ['Fenrir']='Heavenward Howl', ['Cait Sith']='Raise II'}
  76. pacts.debuff1 = {['Shiva']='Diamond Storm', ['Ramuh']='Shock Squall', ['Leviathan']='Tidal Roar', ['Fenrir']='Lunar Cry',
  77. ['Diabolos']='Pavor Nocturnus', ['Cait Sith']='Eerie Eye'}
  78. pacts.debuff2 = {['Shiva']='Sleepga', ['Leviathan']='Slowga', ['Fenrir']='Lunar Roar', ['Diabolos']='Somnolence'}
  79. pacts.sleep = {['Shiva']='Sleepga', ['Diabolos']='Nightmare', ['Cait Sith']='Mewing Lullaby'}
  80. pacts.nuke2 = {['Ifrit']='Fire II', ['Shiva']='Blizzard II', ['Garuda']='Aero II', ['Titan']='Stone II',
  81. ['Ramuh']='Thunder II', ['Leviathan']='Water II'}
  82. pacts.nuke4 = {['Ifrit']='Fire IV', ['Shiva']='Blizzard IV', ['Garuda']='Aero IV', ['Titan']='Stone IV',
  83. ['Ramuh']='Thunder IV', ['Leviathan']='Water IV'}
  84. pacts.bp70 = {['Ifrit']='Flaming Crush', ['Shiva']='Rush', ['Garuda']='Predator Claws', ['Titan']='Mountain Buster',
  85. ['Ramuh']='Chaotic Strike', ['Leviathan']='Spinning Dive', ['Carbuncle']='Meteorite', ['Fenrir']='Eclipse Bite',
  86. ['Diabolos']='Nether Blast',['Cait Sith']='Regal Scratch'}
  87. pacts.bp75 = {['Ifrit']='Meteor Strike', ['Shiva']='Heavenly Strike', ['Garuda']='Wind Blade', ['Titan']='Geocrush',
  88. ['Ramuh']='Thunderstorm', ['Leviathan']='Grand Fall', ['Carbuncle']='Holy Mist', ['Fenrir']='Lunar Bay',
  89. ['Diabolos']='Night Terror', ['Cait Sith']='Level ? Holy'}
  90. pacts.astralflow = {['Ifrit']='Inferno', ['Shiva']='Diamond Dust', ['Garuda']='Aerial Blast', ['Titan']='Earthen Fury',
  91. ['Ramuh']='Judgment Bolt', ['Leviathan']='Tidal Wave', ['Carbuncle']='Searing Light', ['Fenrir']='Howling Moon',
  92. ['Diabolos']='Ruinous Omen', ['Cait Sith']="Altana's Favor"}
  93.  
  94. -- Wards table for creating custom timers
  95. wards = {}
  96. -- Base duration for ward pacts.
  97. wards.durations = {
  98. ['Crimson Howl'] = 60, ['Earthen Armor'] = 60, ['Inferno Howl'] = 60, ['Heavenward Howl'] = 60,
  99. ['Rolling Thunder'] = 120, ['Fleet Wind'] = 120,
  100. ['Shining Ruby'] = 180, ['Frost Armor'] = 180, ['Lightning Armor'] = 180, ['Ecliptic Growl'] = 180,
  101. ['Glittering Ruby'] = 180, ['Hastega'] = 180, ['Noctoshield'] = 180, ['Ecliptic Howl'] = 180,
  102. ['Dream Shroud'] = 180,
  103. ['Reraise II'] = 3600
  104. }
  105. -- Icons to use when creating the custom timer.
  106. wards.icons = {
  107. ['Earthen Armor'] = 'spells/00299.png', -- 00299 for Titan
  108. ['Shining Ruby'] = 'spells/00043.png', -- 00043 for Protect
  109. ['Dream Shroud'] = 'spells/00304.png', -- 00304 for Diabolos
  110. ['Noctoshield'] = 'spells/00106.png', -- 00106 for Phalanx
  111. ['Inferno Howl'] = 'spells/00298.png', -- 00298 for Ifrit
  112. ['Hastega'] = 'spells/00358.png', -- 00358 for Hastega
  113. ['Rolling Thunder'] = 'spells/00104.png', -- 00358 for Enthunder
  114. ['Frost Armor'] = 'spells/00250.png', -- 00250 for Ice Spikes
  115. ['Lightning Armor'] = 'spells/00251.png', -- 00251 for Shock Spikes
  116. ['Reraise II'] = 'spells/00135.png', -- 00135 for Reraise
  117. ['Fleet Wind'] = 'abilities/00074.png', --
  118. }
  119. -- Flags for code to get around the issue of slow skill updates.
  120. wards.flag = false
  121. wards.spell = ''
  122.  
  123. end
  124.  
  125. -------------------------------------------------------------------------------------------------------------------
  126. -- User setup functions for this job. Recommend that these be overridden in a sidecar file.
  127. -------------------------------------------------------------------------------------------------------------------
  128.  
  129. -- Setup vars that are user-dependent. Can override this function in a sidecar file.
  130. function user_setup()
  131. state.OffenseMode:options('None', 'Normal', 'Acc')
  132. state.CastingMode:options('Normal', 'Resistant')
  133. state.IdleMode:options('Normal', 'PDT')
  134.  
  135. gear.perp_staff = {name=""}
  136.  
  137. end
  138.  
  139.  
  140. -- Define sets and vars used by this job file.
  141. function init_gear_sets()
  142. --------------------------------------
  143. -- Precast Sets
  144. --------------------------------------
  145.  
  146. -- Precast sets to enhance JAs
  147. sets.precast.JA['Astral Flow'] = {head="Glyphic Horn"}
  148.  
  149. sets.precast.JA['Elemental Siphon'] = {main="Chatoyant Staff",Sub="Bugard Leather Strap +1",
  150. head="Caller's Horn +2",neck="Caller's Pendant",body="Caller's Doublet +2",hands="Glyphic Bracers",
  151. ring2="Evoker's Ring",legs="Convoker's Spats",feet="Caller's Pigaches +2"}
  152.  
  153. sets.precast.JA['Mana Cede'] = {hands="Caller's Bracers +2"}
  154.  
  155. -- Pact delay reduction gear
  156. sets.precast.BloodPactWard = {ammo="Seraphicaller",head="Convoker's Horn",body="Glyphic Doublet",
  157. hands="Glyphic Bracers",back="Samanisi Cape"}
  158.  
  159. sets.precast.BloodPactRage = sets.precast.BloodPactWard
  160.  
  161. -- Fast cast sets for spells
  162.  
  163. sets.precast.FC = {
  164. head="Nahtirah Hat",ear2="Loquacious Earring",body="Vanir Cotehardie",ring1="Prolix Ring",
  165. back="Swith Cape +1",waist="Witful Belt",legs="Orvail Pants +1",feet="Chelona Boots +1"}
  166.  
  167. sets.precast.FC['Enhancing Magic'] = set_combine(sets.precast.FC, {waist="Siegel Sash"})
  168.  
  169.  
  170. -- Weaponskill sets
  171. -- Default set for any weaponskill that isn't any more specifically defined
  172. sets.precast.WS = {
  173. head="Nahtirah Hat",neck="Asperity Necklace",ear1="Bladeborn Earring",ear2="Steelflash Earring",
  174. body="Vanir Cotehardie",hands="Yaoyotl Gloves",ring1="Rajas Ring",ring2="K'ayres Ring",
  175. back="Pahtli Cape",waist="Cascade Belt",legs="Hagondes Pants",feet="Hagondes Sabots"}
  176.  
  177. -- Specific weaponskill sets. Uses the base set if an appropriate WSMod version isn't found.
  178. sets.precast.WS['Myrkr'] = {
  179. head="Nahtirah Hat",ear1="Gifted Earring",ear2="Loquacious Earring",
  180. body="Convoker's Doublet",hands="Caller's Bracers +2",ring1="Evoker's Ring",ring2="Sangoma Ring",
  181. back="Pahtli Cape",waist="Fucho-no-Obi",legs="Nares Trews",feet="Chelona Boots +1"}
  182.  
  183.  
  184. --------------------------------------
  185. -- Midcast sets
  186. --------------------------------------
  187.  
  188. sets.midcast.FastRecast = {
  189. head="Nahtirah Hat",ear2="Loquacious Earring",
  190. body="Vanir Cotehardie",hands="Bokwus Gloves",ring1="Prolix Ring",
  191. back="Swith Cape +1",waist="Witful Belt",legs="Hagondes Pants",feet="Hagondes Sabots"}
  192.  
  193. sets.midcast.Cure = {main="Tamaxchi",sub="Genbu's Shield",
  194. head="Nahtirah Hat",ear2="Loquacious Earring",
  195. body="Heka's Kalasiris",hands="Bokwus Gloves",ring1="Prolix Ring",ring2="Sirona's Ring",
  196. back="Swith Cape +1",waist="Witful Belt",legs="Hagondes Pants",feet="Hagondes Sabots"}
  197.  
  198. sets.midcast.Stoneskin = {waist="Siegel Sash"}
  199.  
  200. sets.midcast['Elemental Magic'] = {main="Lehbrailg +2",sub="Wizzan Grip",
  201. head="Hagondes Hat",neck="Stoicheion Medal",ear1="Friomisi Earring",ear2="Hecate's Earring",
  202. body="Hagondes Coat",hands="Yaoyotl Gloves",ring1="Icesoul Ring",ring2="Acumen Ring",
  203. back="Toro Cape",waist=gear.ElementalBelt,legs="Hagondes Pants",feet="Hagondes Sabots"}
  204.  
  205. sets.midcast['Dark Magic'] = {main="Lehbrailg +2",sub="Wizzan Grip",
  206. head="Nahtirah Hat",neck="Aesir Torque",ear1="Lifestorm Earring",ear2="Psystorm Earring",
  207. body="Vanir Cotehardie",hands="Yaoyotl Gloves",ring1="Excelsis Ring",ring2="Sangoma Ring",
  208. waist="Fuchi-no-Obi",legs="Bokwus Slops",feet="Bokwus Boots"}
  209.  
  210.  
  211. -- Avatar pact sets. All pacts are Ability type.
  212.  
  213. sets.midcast.Pet.BloodPactWard = {main="Soulscourge",ammo="Seraphicaller",
  214. head="Convoker's Horn",neck="Caller's Pendant",
  215. body="Caller's Doublet +2",hands="Glyphic Bracers",ring1="Evoker's Ring",ring2="Fervor Ring",
  216. waist="Diabolos's Rope",legs="Marduk's Shalwar +1"}
  217.  
  218. sets.midcast.Pet.DebuffBloodPactWard = {main="Soulscourge",ammo="Seraphicaller",
  219. head="Convoker's Horn",neck="Caller's Pendant",
  220. body="Caller's Doublet +2",hands="Glyphic Bracers",ring1="Evoker's Ring",ring2="Fervor Ring",
  221. waist="Diabolos's Rope",legs="Marduk's Shalwar +1"}
  222.  
  223. sets.midcast.Pet.DebuffBloodPactWard.Acc = sets.midcast.Pet.DebuffBloodPactWard
  224.  
  225. sets.midcast.Pet.PhysicalBloodPactRage = {main="Soulscourge",ammo="Seraphicaller",
  226. head="Convoker's Horn",neck="Caller's Pendant",
  227. body="Convoker's Doublet",hands="Glyphic Bracers",ring1="Evoker's Ring",ring2="Fervor Ring",
  228. waist="Diabolos's Rope",legs="Convoker's Spats",feet="Convoker's Pigaches"}
  229.  
  230. sets.midcast.Pet.PhysicalBloodPactRage.Acc = sets.midcast.Pet.PhysicalBloodPactRage
  231.  
  232. sets.midcast.Pet.MagicalBloodPactRage = {main="Eminent Pole",ammo="Seraphicaller",
  233. head="Glyphic Horn",neck="Caller's Pendant",
  234. body="Convoker's Doublet",hands="Glyphic Bracers",ring1="Evoker's Ring",ring2="Fervor Ring",
  235. back="Samanisi Cape",waist="Diabolos's Rope",legs="Caller's Spats +2",feet="Hagondes Sabots"}
  236.  
  237. sets.midcast.Pet.MagicalBloodPactRage.Acc = sets.midcast.Pet.MagicalBloodPactRage
  238.  
  239.  
  240. -- Spirits cast magic spells, which can be identified in standard ways.
  241.  
  242. sets.midcast.Pet.WhiteMagic = {legs="Summoner's Spats"}
  243.  
  244. sets.midcast.Pet['Elemental Magic'] = set_combine(sets.midcast.Pet.BloodPactRage, {legs="Summoner's Spats"})
  245.  
  246. sets.midcast.Pet['Elemental Magic'].Resistant = {}
  247.  
  248.  
  249. --------------------------------------
  250. -- Idle/resting/defense/etc sets
  251. --------------------------------------
  252.  
  253. -- Resting sets
  254. sets.resting = {main="Chatoyant Staff",sub="Bugard Strap +1",ammo="Clarus Stone",
  255. head="Caller's Horn +2",neck="Grandiose Chain",ear1="Magnetic Earring",ear2="Loquacious Earring",
  256. body="Errant Hpl.",hands="Serpentes Cuffs",ring1="Bifrost Ring",ring2="Evoker's Ring",
  257. back="Eloquence Cape +1",waist="Hierarch Belt",legs="Sagacity Lappas",feet="Goliard Clogs"}
  258.  
  259. -- Idle sets
  260. sets.idle = {main="Chatoyant Staff",sub="Bugard Strap +1",
  261. head="Caller's Horn +2",neck="Caller's Pendant",ear1="Loquacious Earring",ear2="Moonshade Earring",
  262. body="Yinyang Robe",hands="Serpentes Cuffs",ring1="Bifrost Ring",ring2="Evoker's Ring",
  263. back="Eloquence Cape +1",waist="Hierarch Belt",legs="Convoker's Spats",feet="Serpentes Sabots"}
  264.  
  265. -- perp costs:
  266. -- spirits: 7
  267. -- carby: 11 (5 with mitts)
  268. -- fenrir: 13
  269. -- others: 15
  270. -- avatar's favor: -4/tick
  271.  
  272. -- Max useful -perp gear is 1 less than the perp cost (can't be reduced below 1)
  273. -- Aim for -14 perp, and refresh in other slots.
  274.  
  275. -- -perp gear:
  276. -- Gridarvor: -5
  277. -- Glyphic Horn: -4
  278. -- Caller's Doublet +2/Glyphic Doublet: -4
  279. -- Evoker's Ring: -1
  280. -- Convoker's Pigaches: -4
  281. -- total: -18
  282.  
  283. -- Can make due without either the head or the body, and use +refresh items in those slots.
  284.  
  285. sets.idle.Avatar = {main="Chatoyant Staff",sub="Bugard Strap +1",ammo="Eminent Sachet",
  286. head="Glyphic Horn",neck="Caller's Pendant",ear1="Gifted Earring",ear2="Loquacious Earring",
  287. body="Caller's Doublet +2",hands="Glyphic Bracers",ring1="Bifrost Ring",ring2="Evoker's Ring",
  288. back="Eloquence Cape +1",waist="Hierarch Belt",legs="Convoker's Spats",feet="Caller's Pigaches +2"}
  289.  
  290. sets.idle.Spirit = {main="Chatoyant Staff",sub="Bugard Strap +1",ammo="Eminent Sachet",
  291. head="Glyphic Horn",neck="Caller's Pendant",ear1="Gifted Earring",ear2="Loquacious Earring",
  292. body="Caller's Doublet +2",hands="Glyphic Bracers",ring1="Bifrost Ring",ring2="Evoker's Ring",
  293. back="Eloquence Cape +1",waist="Hierarch Belt",legs="Convoker's Spats",feet="Caller's Pigaches +2"}
  294.  
  295. sets.idle.Town = {main="Chatoyant Staff",sub="Bugard Strap +1",
  296. head="Caller's Horn +2",neck="Caller's Pendant",ear1="Loquacious Earring",ear2="Moonshade Earring",
  297. body="Yinyang Robe",hands="Serpentes Cuffs",ring1="Bifrost Ring",ring2="Evoker's Ring",
  298. back="Eloquence Cape +1",waist="Hierarch Belt",legs="Wicca Subligar",feet="Serpentes Sabots"}
  299.  
  300. -- Favor uses Caller's Horn instead of Convoker's Horn for refresh
  301. sets.idle.Avatar.Favor = {head="Caller's Horn +2"}
  302. sets.idle.Avatar.Melee = {hands="Regimen Mittens",back="Samanisi Cape",waist="Kuku Stone",legs="Convoker's Spats"}
  303.  
  304. sets.perp = {}
  305. -- Caller's Bracer's halve the perp cost after other costs are accounted for.
  306. -- Using -10 (Gridavor, ring, Conv.feet), standard avatars would then cost 5, halved to 2.
  307. -- We can then use Hagondes Coat and end up with the same net MP cost, but significantly better defense.
  308. -- Weather is the same, but we can also use the latent on the pendant to negate the last point lost.
  309. -- Carby: Mitts+Conv.feet = 1/tick perp. Everything else should be +refresh
  310. sets.perp.Carbuncle = {main="Bolelabunga",sub="Genbu's Shield",head="Convoker's Horn",
  311. body="Hagondes Coat",hands="Carbuncle Mitts",legs="Nares Trews",feet="Convoker's Pigaches"}
  312. sets.perp.Diabolos = {main="Bolelabunga",sub="Genbu's Shield",head="Convoker's Horn",
  313. body="Hagondes Coat",hands="Augur's Gloves",legs="Nares Trews",feet="Convoker's Pigaches"}
  314. -- Diabolos's Rope doesn't gain us anything at this time
  315. -- sets.perp.Diabolos = {waist="Diabolos's Rope"}
  316. sets.perp.Alexander = sets.midcast.Pet.BloodPactWard
  317.  
  318. sets.perp.staff_and_grip = {main=gear.perp_staff,sub="Achaq Grip"}
  319.  
  320. --------------------------------------
  321. -- Engaged sets
  322. --------------------------------------
  323.  
  324. -- Normal melee group
  325. sets.engaged = {ammo="Seraphicaller",
  326. head="Zelus Tiara",neck="Asperity Necklace",ear1="Bladeborn Earring",ear2="Steelflash Earring",
  327. body="Vanir Cotehardie",hands="Bokwus Gloves",ring1="Rajas Ring",ring2="K'ayres Ring",
  328. back="Umbra Cape",waist="Goading Belt",legs="Hagondes Pants",feet="Hagondes Sabots"}
  329. end
  330.  
  331. -------------------------------------------------------------------------------------------------------------------
  332. -- Job-specific hooks for standard casting events.
  333. -------------------------------------------------------------------------------------------------------------------
  334.  
  335. -- Set eventArgs.handled to true if we don't want any automatic gear equipping to be done.
  336. -- Set eventArgs.useMidcastGear to true if we want midcast gear equipped on precast.
  337. function job_precast(spell, action, spellMap, eventArgs)
  338. if state.Buff['Astral Conduit'] and pet_midaction() then
  339. eventArgs.handled = true
  340. end
  341. end
  342.  
  343. function job_midcast(spell, action, spellMap, eventArgs)
  344. if state.Buff['Astral Conduit'] and pet_midaction() then
  345. eventArgs.handled = true
  346. end
  347. end
  348.  
  349. -- Runs when pet completes an action.
  350. function job_pet_aftercast(spell, action, spellMap, eventArgs)
  351. if not spell.interrupted and spell.type == 'BloodPactWard' and spellMap ~= 'DebuffBloodPactWard' then
  352. wards.flag = true
  353. wards.spell = spell.english
  354. send_command('wait 4; gs c reset_ward_flag')
  355. end
  356. end
  357.  
  358. -------------------------------------------------------------------------------------------------------------------
  359. -- Job-specific hooks for non-casting events.
  360. -------------------------------------------------------------------------------------------------------------------
  361.  
  362. -- Called when a player gains or loses a buff.
  363. -- buff == buff gained or lost
  364. -- gain == true if the buff was gained, false if it was lost.
  365. function job_buff_change(buff, gain)
  366. if state.Buff[buff] ~= nil then
  367. handle_equipping_gear(player.status)
  368. elseif storms:contains(buff) then
  369. handle_equipping_gear(player.status)
  370. end
  371. end
  372.  
  373.  
  374. -- Called when the player's pet's status changes.
  375. -- This is also called after pet_change after a pet is released. Check for pet validity.
  376. function job_pet_status_change(newStatus, oldStatus, eventArgs)
  377. if pet.isvalid and not midaction() and not pet_midaction() and (newStatus == 'Engaged' or oldStatus == 'Engaged') then
  378. handle_equipping_gear(player.status, newStatus)
  379. end
  380. end
  381.  
  382.  
  383. -- Called when a player gains or loses a pet.
  384. -- pet == pet structure
  385. -- gain == true if the pet was gained, false if it was lost.
  386. function job_pet_change(petparam, gain)
  387. classes.CustomIdleGroups:clear()
  388. if gain then
  389. if avatars:contains(pet.name) then
  390. classes.CustomIdleGroups:append('Avatar')
  391. elseif spirits:contains(pet.name) then
  392. classes.CustomIdleGroups:append('Spirit')
  393. end
  394. end
  395. end
  396.  
  397. -------------------------------------------------------------------------------------------------------------------
  398. -- User code that supplements standard library decisions.
  399. -------------------------------------------------------------------------------------------------------------------
  400.  
  401. -- Custom spell mapping.
  402. function job_get_spell_map(spell)
  403. if spell.type == 'BloodPactRage' then
  404. if magicalRagePacts:contains(spell.english) then
  405. return 'MagicalBloodPactRage'
  406. else
  407. return 'PhysicalBloodPactRage'
  408. end
  409. elseif spell.type == 'BloodPactWard' and spell.target.type == 'MONSTER' then
  410. return 'DebuffBloodPactWard'
  411. end
  412. end
  413.  
  414. -- Modify the default idle set after it was constructed.
  415. function customize_idle_set(idleSet)
  416. if pet.isvalid then
  417. if pet.element == world.day_element then
  418. idleSet = set_combine(idleSet, sets.perp.Day)
  419. end
  420. if pet.element == world.weather_element then
  421. idleSet = set_combine(idleSet, sets.perp.Weather)
  422. end
  423. gear.perp_staff.name = elements.perpetuance_staff_of[pet.element]
  424. if gear.perp_staff.name and (player.inventory[gear.perp_staff.name] or player.wardrobe[gear.perp_staff.name]) then
  425. idleSet = set_combine(idleSet, sets.perp.staff_and_grip)
  426. end
  427. if state.Buff["Avatar's Favor"] and avatars:contains(pet.name) then
  428. idleSet = set_combine(idleSet, sets.idle.Avatar.Favor)
  429. end
  430. if pet.status == 'Engaged' then
  431. idleSet = set_combine(idleSet, sets.idle.Avatar.Melee)
  432. end
  433. end
  434.  
  435. if player.mpp < 51 then
  436. idleSet = set_combine(idleSet, sets.latent_refresh)
  437. end
  438.  
  439. return idleSet
  440. end
  441.  
  442. -- Called by the 'update' self-command, for common needs.
  443. -- Set eventArgs.handled to true if we don't want automatic equipping of gear.
  444. function job_update(cmdParams, eventArgs)
  445. classes.CustomIdleGroups:clear()
  446. if pet.isvalid then
  447. if avatars:contains(pet.name) then
  448. classes.CustomIdleGroups:append('Avatar')
  449. elseif spirits:contains(pet.name) then
  450. classes.CustomIdleGroups:append('Spirit')
  451. end
  452. end
  453. end
  454.  
  455. -- Set eventArgs.handled to true if we don't want the automatic display to be run.
  456. function display_current_job_state(eventArgs)
  457.  
  458. end
  459.  
  460.  
  461. -------------------------------------------------------------------------------------------------------------------
  462. -- User self-commands.
  463. -------------------------------------------------------------------------------------------------------------------
  464.  
  465. -- Called for custom player commands.
  466. function job_self_command(cmdParams, eventArgs)
  467. if cmdParams[1]:lower() == 'petweather' then
  468. handle_petweather()
  469. eventArgs.handled = true
  470. elseif cmdParams[1]:lower() == 'siphon' then
  471. handle_siphoning()
  472. eventArgs.handled = true
  473. elseif cmdParams[1]:lower() == 'pact' then
  474. handle_pacts(cmdParams)
  475. eventArgs.handled = true
  476. elseif cmdParams[1] == 'reset_ward_flag' then
  477. wards.flag = false
  478. wards.spell = ''
  479. eventArgs.handled = true
  480. end
  481. end
  482.  
  483.  
  484. -------------------------------------------------------------------------------------------------------------------
  485. -- Utility functions specific to this job.
  486. -------------------------------------------------------------------------------------------------------------------
  487.  
  488. -- Cast the appopriate storm for the currently summoned avatar, if possible.
  489. function handle_petweather()
  490. if player.sub_job ~= 'SCH' then
  491. add_to_chat(122, "You can not cast storm spells")
  492. return
  493. end
  494.  
  495. if not pet.isvalid then
  496. add_to_chat(122, "You do not have an active avatar.")
  497. return
  498. end
  499.  
  500. local element = pet.element
  501. if element == 'Thunder' then
  502. element = 'Lightning'
  503. end
  504.  
  505. if S{'Light','Dark','Lightning'}:contains(element) then
  506. add_to_chat(122, 'You do not have access to '..elements.storm_of[element]..'.')
  507. return
  508. end
  509.  
  510. local storm = elements.storm_of[element]
  511.  
  512. if storm then
  513. send_command('@input /ma "'..elements.storm_of[element]..'" <me>')
  514. else
  515. add_to_chat(123, 'Error: Unknown element ('..tostring(element)..')')
  516. end
  517. end
  518.  
  519.  
  520. -- Custom uber-handling of Elemental Siphon
  521. function handle_siphoning()
  522. if areas.Cities:contains(world.area) then
  523. add_to_chat(122, 'Cannot use Elemental Siphon in a city area.')
  524. return
  525. end
  526.  
  527. local siphonElement
  528. local stormElementToUse
  529. local releasedAvatar
  530. local dontRelease
  531.  
  532. -- If we already have a spirit out, just use that.
  533. if pet.isvalid and spirits:contains(pet.name) then
  534. siphonElement = pet.element
  535. dontRelease = true
  536. -- If current weather doesn't match the spirit, but the spirit matches the day, try to cast the storm.
  537. if player.sub_job == 'SCH' and pet.element == world.day_element and pet.element ~= world.weather_element then
  538. if not S{'Light','Dark','Lightning'}:contains(pet.element) then
  539. stormElementToUse = pet.element
  540. end
  541. end
  542. -- If we're subbing /sch, there are some conditions where we want to make sure specific weather is up.
  543. -- If current (single) weather is opposed by the current day, we want to change the weather to match
  544. -- the current day, if possible.
  545. elseif player.sub_job == 'SCH' and world.weather_element ~= 'None' then
  546. -- We can override single-intensity weather; leave double weather alone, since even if
  547. -- it's partially countered by the day, it's not worth changing.
  548. if get_weather_intensity() == 1 then
  549. -- If current weather is weak to the current day, it cancels the benefits for
  550. -- siphon. Change it to the day's weather if possible (+0 to +20%), or any non-weak
  551. -- weather if not.
  552. -- If the current weather matches the current avatar's element (being used to reduce
  553. -- perpetuation), don't change it; just accept the penalty on Siphon.
  554. if world.weather_element == elements.weak_to[world.day_element] and
  555. (not pet.isvalid or world.weather_element ~= pet.element) then
  556. -- We can't cast lightning/dark/light weather, so use a neutral element
  557. if S{'Light','Dark','Lightning'}:contains(world.day_element) then
  558. stormElementToUse = 'Wind'
  559. else
  560. stormElementToUse = world.day_element
  561. end
  562. end
  563. end
  564. end
  565.  
  566. -- If we decided to use a storm, set that as the spirit element to cast.
  567. if stormElementToUse then
  568. siphonElement = stormElementToUse
  569. elseif world.weather_element ~= 'None' and (get_weather_intensity() == 2 or world.weather_element ~= elements.weak_to[world.day_element]) then
  570. siphonElement = world.weather_element
  571. else
  572. siphonElement = world.day_element
  573. end
  574.  
  575. local command = ''
  576. local releaseWait = 0
  577.  
  578. if pet.isvalid and avatars:contains(pet.name) then
  579. command = command..'input /pet "Release" <me>;wait 1.1;'
  580. releasedAvatar = pet.name
  581. releaseWait = 10
  582. end
  583.  
  584. if stormElementToUse then
  585. command = command..'input /ma "'..elements.storm_of[stormElementToUse]..'" <me>;wait 4;'
  586. releaseWait = releaseWait - 4
  587. end
  588.  
  589. if not (pet.isvalid and spirits:contains(pet.name)) then
  590. command = command..'input /ma "'..elements.spirit_of[siphonElement]..'" <me>;wait 4;'
  591. releaseWait = releaseWait - 4
  592. end
  593.  
  594. command = command..'input /ja "Elemental Siphon" <me>;'
  595. releaseWait = releaseWait - 1
  596. releaseWait = releaseWait + 0.1
  597.  
  598. if not dontRelease then
  599. if releaseWait > 0 then
  600. command = command..'wait '..tostring(releaseWait)..';'
  601. else
  602. command = command..'wait 1.1;'
  603. end
  604.  
  605. command = command..'input /pet "Release" <me>;'
  606. end
  607.  
  608. if releasedAvatar then
  609. command = command..'wait 1.1;input /ma "'..releasedAvatar..'" <me>'
  610. end
  611.  
  612. send_command(command)
  613. end
  614.  
  615.  
  616. -- Handles executing blood pacts in a generic, avatar-agnostic way.
  617. -- cmdParams is the split of the self-command.
  618. -- gs c [pact] [pacttype]
  619. function handle_pacts(cmdParams)
  620. if areas.Cities:contains(world.area) then
  621. add_to_chat(122, 'You cannot use pacts in town.')
  622. return
  623. end
  624.  
  625. if spirits:contains(pet.name) then
  626. add_to_chat(122,'Cannot use pacts with spirits.')
  627. return
  628. end
  629.  
  630. if not cmdParams[2] then
  631. add_to_chat(123,'No pact type given.')
  632. return
  633. end
  634.  
  635. local pact = cmdParams[2]:lower()
  636.  
  637. if not pacts[pact] then
  638. add_to_chat(123,'Unknown pact type: '..tostring(pact))
  639. return
  640. end
  641.  
  642. if pacts[pact][pet.name] then
  643. if pact == 'astralflow' and not buffactive['astral flow'] then
  644. add_to_chat(122,'Cannot use Astral Flow pacts at this time.')
  645. return
  646. end
  647.  
  648. -- Leave out target; let Shortcuts auto-determine it.
  649. send_command('@input /pet "'..pacts[pact][pet.name]..'"')
  650. else
  651. add_to_chat(122,pet.name..' does not have a pact of type ['..pact..'].')
  652. end
  653. end
  654.  
  655.  
  656. -- Event handler for updates to player skill, since we can't rely on skill being
  657. -- correct at pet_aftercast for the creation of custom timers.
  658. windower.raw_register_event('incoming chunk',
  659. function (id)
  660. if id == 0x62 then
  661. if wards.flag then
  662. create_pact_timer(wards.spell)
  663. wards.flag = false
  664. wards.spell = ''
  665. end
  666. end
  667. end)
  668.  
  669. -- Function to create custom timers using the Timers addon. Calculates ward duration
  670. -- based on player skill and base pact duration (defined in job_setup).
  671. function create_pact_timer(spell_name)
  672. -- Create custom timers for ward pacts.
  673. if wards.durations[spell_name] then
  674. local ward_duration = wards.durations[spell_name]
  675. if ward_duration < 181 then
  676. local skill = player.skills.summoning_magic
  677. if skill > 300 then
  678. skill = skill - 300
  679. if skill > 200 then skill = 200 end
  680. ward_duration = ward_duration + skill
  681. end
  682. end
  683.  
  684. local timer_cmd = 'timers c "'..spell_name..'" '..tostring(ward_duration)..' down'
  685.  
  686. if wards.icons[spell_name] then
  687. timer_cmd = timer_cmd..' '..wards.icons[spell_name]
  688. end
  689.  
  690. send_command(timer_cmd)
  691. end
  692. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement