Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Copyright (c) 2013, Registry
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of stunner nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL Registry BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ]]
- -- NOTE: Escaping horizontal tabs seems to not work in a text box.
- -- NOTE: Spells/abils/targets are currently set for Morimar. If possible, find a way to load different settings files for different zones.
- -- NOTE: Order implementation has not yet been tested.
- require 'luau'
- _addon = _addon or {}
- _addon.name = 'stunner'
- _addon.command = 'stunner'
- _addon.short_command = 'stunner'
- _addon.version = 1.1
- settings = T{}
- settings.abilityList = {'Incinerating Lahar', 'Volcanic Stasis', 'Tyrannical Blow', 'Blistering Roar', 'Searing Serration', 'Batholithic Shell', 'Pyroclastic Surge', 'Testudo Tremor', 'Calcifying Mist', 'Torpefying Charge'}
- settings.spellList = {'Dispelga', 'Breakga', 'Thundaga V', 'Thundaja', 'Aeroga V', 'Aeroja', 'Firaga V', 'Firaja', 'Stonega V', 'Stoneja', 'Kaustra', 'Meteor'}
- settings.targetList = {'Tojil', 'Kurma', 'Tutewehiwehi'}
- settings.stun = true
- settings.useAlacrity = true
- settings.order = false
- settings.afterWho = '(none)'
- settings.beforeWho = '(none)'
- settings.sendMessage = false
- settings.messageToSend = "Casting stun now! you're next!"
- settings.messsageToWatch = '(none)'
- settings.display = true
- settings.showTargets = true
- settings.showAbilities = false
- settings.showSpells = false
- settings.xPos = 700
- settings.yPos = 50
- settings.debug = false
- -- Statuses that stop you from reactions.
- statusblock = S{
- 'Dead', 'Event', 'Charmed'
- }
- -- Aliases for reactions on/off
- on = T{'on', 'yes', 'true'}
- off = T{'off', 'no', 'false'}
- function event_load()
- settings = config.load(settings)
- spells = {}
- job_abilities = {}
- mob_abilities = {}
- spell_file_name = '../../plugins/resources/spells.xml'
- ja_file_name = '../../plugins/resources/abils.xml'
- ma_file_name = '../libs/resources/mabils.xml'
- spell_file = files.new(spell_file_name)
- ja_file = files.new(ja_file_name)
- mob_abil_file = files.new(ma_file_name)
- spells = parse_resources(spell_file:readlines())
- job_abilities = parse_resources(ja_file:readlines())
- mob_abilities = parse_resources(mob_abil_file:readlines())
- can_stun = true
- last_abil = '(none)'
- last_spell = '(none)'
- last_target = '(none)'
- create_display()
- send_command('alias stunner lua c stunner')
- log('Stunner is now loaded! For a list of commands please type //stunner help.')
- log('There may still be bugs with this program, it was written quite quickly. If you find anything and would like to let me know, please send me a PM on ffxiah.com or guildwork.com or, additionally, you can post on github.com/r3g1stry/Lua/issues. If you post a bug report on GitHub (make sure it\'s my fork), please title it Stunner and list the issue you\'re having as a comment. Also, If you would like any sort of functionality added, feel free to ask.')
- end
- function event_addon_command(command, ...)
- command = command and command:lower() or 'status'
- local args = T{...}
- -- prints help message
- if command == 'help' then
- write('stunner available commands:')
- write('stunner help : Shows this help message')
- write('stunner [off|on]: Turns stunner on or off')
- write('stunner order [on|off]: Turns stun order on or off, if no mode specified it will toggle on or off')
- write('stunner order [next|prev]: Sets next true or false - this is to be used in case something breaks')
- write('stunner [before|after] [player]: Changes the player you are before or after in the stun order')
- write('stunner message [on|off]: Turns message after stunning on or off')
- write('stunner lists: Prints Target List, TP List, and Spell List to chat log')
- write('stunner display [on|off]: Turns the display on or off, if no mode specified it will toggle on or off')
- write('stunner [show|hide] [abilities|spells|targets]: Shows or hides specified list on display')
- write('stunner xpos [x position]: Changes the x position of the display')
- write('stunner ypos [y position]: Changes the y position of the display')
- -- Turns stunner off
- elseif command == 'off' then
- settings.stun = false
- log('You have turned stunner off.')
- -- turns stunner on
- elseif command == 'on' then
- settings.stun = true
- log('You have turned stunner on.')
- -- turns order on or off - or, alternatively, sets you next in order just in case.
- elseif command == 'order' then
- local status = args[1] or 'status'
- if status:isin(on) then
- settings.order = true
- log('Order turned on.')
- elseif status:isin(off) then
- settings.order = false
- log('Order turned off.')
- elseif string.lower(status) == 'next' then
- if settings.order == true then
- can_stun = true
- log('You are now next in the stun order.')
- else
- log('Please set order on to use this command.')
- end
- elseif string.lower(status) == 'prev' then
- if settings.order == true then
- can_stun = false
- log('You no longer next in the stun order.')
- else
- log('Please set order on to use this command.')
- end
- elseif status == 'status' then
- if settings.order then
- if can_stun == true then
- can_stun = false
- log('You no longer next in the stun order.')
- else
- can_stun = true
- log('You are now next in the stun order.')
- end
- else
- log('Please set order on to use this command.')
- end
- else
- error('Invalid status:', args[1])
- return
- end
- -- changes who you are before in stun order
- elseif command == 'before' then
- local player = args[1] or 'player'
- if player == 'player' then
- log('Currently before '..settings.beforeWho..' in the stun order.')
- else
- settings.beforeWho = player
- log('You are now before '..settings.beforeWho..' in the stun order.')
- end
- -- changes who you are after in stun order
- elseif command == 'after' then
- local player = args[1] or 'player'
- if player == 'player' then
- log('Currently after '..settings.afterWho..' in the stun order.')
- else
- settings.afterWho = player
- log('You are now after '..settings.afterWho..' in the stun order.')
- end
- -- changes x-position
- elseif command == 'xpos' then
- local xpos = args[1] or 'xpos'
- if xpos == 'xpos' then
- log('X position: '..settings.xPos)
- else
- settings.xPos = tonumber(xpos)
- log('X position changed to: '..settings.xPos)
- end
- -- changes y-position
- elseif command == 'ypos' then
- local ypos = args[1] or 'ypos'
- if ypos == 'ypos' then
- log('Y position: '..settings.yPos)
- else
- settings.yPos = tonumber(ypos)
- log('Y position changed to: '..settings.yPos)
- end
- -- shows or hides specified list on display
- elseif command == 'show' or command == 'hide' then
- if not args[1] then
- log('List not specified - please specify abilities, spells, or targets.')
- return
- end
- if command == 'show' then
- if args[1] == 'abilities' then
- settings.showAbilities = true
- elseif args[1] == 'spells' then
- settings.showSpells = true
- elseif args[1] == 'targets' then
- settings.showTargets = true
- else
- log('Please specify abilities, targets, or spells.')
- return
- end
- else
- if args[1] == 'abilities' then
- settings.showAbilities = false
- elseif args[1] == 'spells' then
- settings.showSpells = false
- elseif args[1] == 'targets' then
- settings.showTargets = false
- else
- log('Please specify abilities, targets, or spells.')
- return
- end
- end
- -- turns display on or off
- elseif command == 'display' then
- local status = args[1] or 'status'
- if status:isin(on) then
- settings.display = true
- toggle_display()
- log('Display turned on.')
- elseif status:isin(off) then
- settings.display = false
- toggle_display()
- log('Display turned off.')
- elseif status == 'status' then
- if settings.display == true then
- settings.display = false
- toggle_display()
- log('Display turned off.')
- else
- settings.display = true
- toggle_display()
- log('Display turned on.')
- end
- else
- error('Invalid status:', args[1])
- return
- end
- -- turns option to send message after stunning on or off
- elseif command == 'message' then
- local status = args[1] or 'status'
- if status:isin(on) then
- settings.sendMessage = true
- log('Now sending message: '..settings.messageToSend)
- elseif status:isin(off) then
- settings.sendMessage = false
- log('Message is now turned off.')
- elseif status == 'status' then
- if settings.sendMessage == false then
- settings.sendMessage = true
- log('Now sending message: '..settings.messageToSend)
- else
- settings.sendMessage = false
- log('Message is now turned off.')
- end
- else
- error('Invalid status:', tostring(args[1]))
- return
- end
- -- prints current lists
- elseif command == 'lists' then
- log('TP List:', settings.abilityList:empty() and '(empty)' or settings.abilityList:format('csv'))
- log('Spell List:', settings.spellList:empty() and '(empty)' or settings.spellList:format('csv'))
- log('Target List:', settings.targetList:empty() and '(empty)' or settings.targetList:format('csv'))
- -- ignores (and prints a warning) if unknown command is passed.
- else
- warning('Unkown command \''..command..'.\' Command ignored.')
- end
- update_display()
- settings:save()
- end
- function event_action(act)
- local actor_table = get_mob_by_id(act['actor_id'])
- local actor = actor_table['name']
- local abil_id, spell_id, abil, spell, player
- -- 8 is player and npc spells
- if act['category'] == 8 then
- if act['param'] ~= 24931 then -- 24931 is start, 28787 is interrupt
- return
- end
- if act['targets'][1]['actions'][1]['param'] then
- spell_id = tonumber(act['targets'][1]['actions'][1]['param'])
- spell = string.lower(tostring(spells[spell_id]['english']))
- --[[DEBUG]] if settings.debug == true then if is_mob(tonumber(act['actor_id'])) == true then log('DEBUG: Spell just used (by mob) was: '..spell..'.') else log('DEBUG: Spell just used (by player) was: '..spell..'.') end end
- end
- -- 7 is player and npc abilities/weaponskills
- elseif act['category'] == 7 and is_mob(tonumber(act['actor_id'])) then
- if act['param'] ~= 24931 then -- 24931 is start, 28787 is interrupt
- return
- end
- if act['targets'][1]['actions'][1]['param'] then
- abil_id = tonumber(act['targets'][1]['actions'][1]['param']) - 256 -- have to subtract 256 from param to get ID for mabils.xml
- if abil_id < 1 then
- error('Ability ID was below 1 after subtracting 256 - returning.') -- this should not happen
- return
- end
- abil = string.lower(tostring(mob_abilities[abil_id]['english']))
- --[[DEBUG]] if settings.debug == true then log('DEBUG: Ability just used (by mob) was: '..abil..'.') end
- end
- else
- --[[DEBUG]] if settings.debug == true then log('DEBUG: Not ability or spell - returning.') end
- return
- end
- --[[DEBUG]] if settings.debug == true and settings.order == true then log('DEBUG: Order is currently turned on.') end
- --[[DEBUG]] if settings.debug == true and string.lower(tostring(spell)) == 'stun' then log('DEBUG: Stun was just cast by '..actor..'.') end
- --[[DEBUG]] if settings.debug == true and string.lower(tostring(actor)) == string.lower(tostring(settings.afterWho)) then log('DEBUG: Action was performed by '..settings.afterWho..'. They are before you in the stun order.') end
- if settings.order == true and string.lower(tostring(actor)) == string.lower(tostring(settings.afterWho)) and string.lower(tostring(spell)) == 'stun' then
- can_stun = true
- end
- if string_in_table(actor, settings.targetList) == true then
- last_target = string.capitalize(actor)
- if abil then
- if string_in_table(abil, settings.abilityList) == true then
- try_stun()
- end
- last_abil = string.capitalize(abil)
- end
- if spell then
- if string_in_table(spell, settings.spellList) == true then
- try_stun()
- end
- last_spell = string.capitalize(spell)
- end
- end
- update_display()
- end
- -- Tries to stun
- function try_stun()
- local player_status = get_player()['status']
- local command_to_send
- if settings.stun == false then
- notice('Stunner is inactive.')
- return
- end
- if settings.order == true and can_stun == false then
- --[[DEBUG]] if settings.debug == true then log('DEBUG: It is not your turn in the stun order.') end
- return
- end
- if statusblock:contains(get_player()['status_id']) == true or string_in_table(player_status, statusblock) == true then
- log('Currently unable to stun.')
- return
- end
- command_to_send = 'input /ma "Stun" <bt>'
- if settings.useAlacrity == true then
- --[[DEBUG]] if settings.debug == true then log('DEBUG: Using Alacrity.') end
- command_to_send = command_to_send..';wait4;input /ja "Alacrity" <me>'
- else
- --[[DEBUG]] if settings.debug == true then log('DEBUG: Not using Alacrity.') end
- end
- send_command(command_to_send)
- if settings.order == true then
- --[[DEBUG]] if settings.debug == true then log('DEBUG: Attempting to set can_stun variable to false.') end
- can_stun = false
- if settings.sendMessage == true then
- --[[DEBUG]] if settings.debug == true then log('DEBUG: Attempting to send message.') end
- send_command('input /t '..settings.beforeWho..' '..settings.messageToSend)
- end
- end
- update_display()
- end
- function create_display()
- tb_create('stunner')
- tb_set_bg_color('stunner',200,30,30,30)
- tb_set_color('stunner',255,200,200,200)
- tb_set_location('stunner',settings.xPos,settings.yPos)
- tb_set_bg_visibility('stunner',1)
- tb_set_font('stunner','Consolas',12)
- tb_set_visibility('stunner',settings.display)
- update_display()
- end
- function update_display()
- if not settings.display then
- return
- end
- local text = 'Stunner version: '..tonumber(_addon.version)..' Author: r3g1stry\n\n'
- -- sets end of display title - on or off
- if settings.stun then
- text = text..'~~~~~~~~~ Stunner currently \\cs(0, 225, 0)active\\cr ~~~~~~~~~\n\n'
- else
- text = text..'~~~~~~~~ Stunner currently \\cs(225, 0, 0)inactive\\cr ~~~~~~~~\n\n'
- end
- if settings.order then
- text = text..'Stun order: \\cs(0, 225, 0)on\\cr'
- if can_stun then
- text = text..' Next: \\cs(0, 225, 0)yes\\cr\n'
- else
- text = text..' Next: \\cs(225, 0, 0)no\\cr\n'
- end
- if settings.beforeWho == settings.afterWho then
- text = text..'In order with: \\cs(0, 200 ,200)'..settings.beforeWho..'\\cr\n'
- else
- text = text..'After: \\cs(0, 200, 200)'..settings.afterWho..'\\cr '.. 'Before: \\cs(0, 200, 200)'..settings.beforeWho..'\\cr\n'
- end
- if settings.sendMessage then
- text = text..'Sending message: "\\cs(220, 20, 150)'..settings.messageToSend..'\\cr"\n\n'
- end
- else
- text = text..'Stun order: \\cs(225, 0, 0)off\\cr\n\n'
- end
- if settings.showTargets then
- if table.empty(settings.targetList) then
- text = text..'Targets: Last target: \\cs(0, 225, 0)'..last_target..'\n\t(none)\\cr\n\n'
- else
- text = text..'Targets: Last target: \\cs(0, 225, 0)'..last_target..'\\cr'
- for _,targ in ipairs(settings.targetList) do
- text = text..'\n \\cs(0, 225, 0)'..tostring(targ)..'\\cr'
- end
- text = text..'\n\n'
- end
- else
- text = text..'Last target: \\cs(0, 225, 0)'..last_target..'\\cr\n\n'
- end
- if settings.showAbilities then
- if table.empty(settings.abilityList) then
- text = text..'Abilities: Last used: \\cs(225, 0, 0)'..last_abil..'\n\t(none)\\cr\n\n'
- else
- text = text..'Abilities: Last used: \\cs(225, 0, 0)'..last_abil..'\\cr'
- for _,abil in ipairs(settings.abilityList) do
- text = text..'\n \\cs(225, 0, 0)'..tostring(abil)..'\\cr'
- end
- text = text..'\n\n'
- end
- else
- text = text..'Last ability used: \\cs(225, 0, 0)'..last_abil..'\\cr\n\n'
- end
- if settings.showSpells then
- if table.empty(settings.spellList) then
- text = text..'Spells: Last used: \\cs(0, 75, 225)'..last_spell..'\n\t(none)\\cr'
- else
- text = text..'Spells: Last used: \\cs(0, 75, 225)'..last_spell..'\\cr'
- for _,spell in ipairs(settings.spellList) do
- text = text..'\n \\cs(0, 75, 225)'..tostring(spell)..'\\cr'
- end
- end
- else
- text = text..'Last spell used: \\cs(0, 75, 225)'..last_spell..'\\cr'
- end
- tb_set_text('stunner', text)
- end
- function toggle_display()
- tb_set_visibility('stunner', settings.display)
- end
- -- Check if the actor is actually an npc rather than a player
- function is_mob(id)
- return get_mob_by_id(id)['is_npc']
- end
- -- Checks if a string is in a table, case does not matter.
- function string_in_table(str, tab)
- str = string.lower(str)
- for i, arg in ipairs(tab) do
- arg = tostring(arg)
- arg = string.lower(arg)
- if arg == str then
- return true
- end
- end
- return false
- end
- function parse_resources(lines_file) -- Code: Byrth (Battlemod)
- local completed_table = T{}
- local counter = 0
- for i in ipairs(lines_file) do
- local str = tostring(lines_file[i])
- local g,h,typ,key = string.find(str,'<(%w+) id="(%d+)" ')
- if typ == 's' then
- g,h,key = string.find(str,'index="(%d+)" ')
- end
- if key ~=nil then
- completed_table[tonumber(key)] = T{}
- local q = 1
- while q <= str:len() do
- local a,b,ind,val = string.find(str,'(%w+)="(.-)"',q)
- if ind~=nil then
- if ind~='id' and ind~='index' then
- completed_table[tonumber(key)][ind] = T{}
- completed_table[tonumber(key)][ind] = val:gsub('"','\42'):gsub(''','\39')
- end
- q = b+1
- else
- q = str:len()+1
- end
- end
- local k,v,english = string.find(str,'>([^<]+)</')
- if english~=nil then
- completed_table[tonumber(key)][ind] = T{}
- completed_table[tonumber(key)]['english']=english
- end
- end
- end
- return completed_table
- end
- function event_unload()
- send_command('unalias stunner')
- tb_delete('stunner')
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement