Is There Any Macro Simplifying Lua Out There?

言語: JP EN DE FR
2010-06-21
New Items
users online
フォーラム » FFXI » Jobs » Black Mage » Is there any macro simplifying lua out there?
Is there any macro simplifying lua out there?
 Fenrir.Brimstonefox
Offline
サーバ: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-04-14 12:04:52  
I have, for a long time now, had my macros set up on BLM so all 6 spells are in one macro. ie:
Code
/ma "Fire VI" <t>
/ma "Fire V" <t>
/ma "Fire IV" <t>
/ma "Fire III" <t>
/ma "Fire II" <t>
/ma "Fire" <t>


And can just mash the macro and based off mp and/or recast timers my best tier nuke for the element goes off.

After setting show swaps to true last night it dawn on my this might not be a good idea as I was trying to debug something but instead of seeing ~3 sets show up (pre, mid, after) I got like ~18 (pre, mid, after for all 6 spells. I say about because its possible not all the afters fired (no pun intended) since only 1 spell went off. But it was pretty clear to me I was switching sets when I did not expect it (not sure how its affecting my magic everything switches so fast I may still get to the right sets at the right time, but its hard to know for sure)

Anyways my question is is there any lua or anything out there to streamline this something like the following (pseudo code only, I haven't tried it, nor expect it to work verbatim so its just an example in principle):
Code
    if spell.english == 'Fire VI') and (player.mp < spell.mp_cost or get_spell_recasts(spell.recast_id) > 0) then
        cancel_spell()
        send_command('input /ma Fire V'..spell.target.raw)
    end
    if spell.english == 'Fire V') and (player.mp < spell.mp_cost or get_spell_recasts(spell.recast_id) > 0) then
        cancel_spell()
        send_command('input /ma Fire IV'..spell.target.raw)
    end
etc...
Offline
Posts: 40
By Isilrhofal 2016-04-14 12:10:54  
Copying code within FFXIAH always messes the layout so I also addded the pastebin.

http://pastebin.com/JdCCgGAu

Not sure if that is what you are looking for, but maybe it gives you an idea.
[+]
 Odin.Vuq
Offline
サーバ: Odin
Game: FFXI
user: Delagyela
By Odin.Vuq 2016-04-14 12:22:58  
Oh this is interesting, that would save so many macro slots if you could get this to work. I cant contribute on how to solve the problem :(
 Fenrir.Brimstonefox
Offline
サーバ: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-04-14 14:24:43  
That looks to be pretty close to what I'm looking for Isilrhofal I'll test it out, at the very least it prevents me from writing it all from scratch.

Thanks much!
[+]
 Ragnarok.Flippant
Offline
サーバ: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-04-14 16:29:38  
This is something I wrote a few years ago when someone asked for a similar thing, but for cure/curaga.

It's a little more fluid, and includes the MP part. You can add more spells by adding a new table, listed from lowest to highest tier.
Code
degrade_tables = {}
degrade_tables.Fire = {"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI"}
degrade_tables.Stone = {"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI"}
degrade_tables.Cure = {"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"}

function pretarget(spell)
	local spell_recasts = windower.ffxi.get_spell_recasts()
	if (spell_recasts[spell.recast_id]>0 or player.mp<actual_cost(spell)) and find_degrade_table(spell) then		
		degrade_spell(spell,find_degrade_table(spell))
	end
end

function find_degrade_table(lookup_spell)
	for __,spells in pairs(degrade_tables) do
		for ___,spell in pairs(spells) do
			if spell == lookup_spell.english then
				return spells
			end
		end
	end
	return false
end

function degrade_spell(spell,degrade_array)
	local spell_index = table.find(degrade_array,spell.english)
	if spell_index>1 then		
		local new_spell = degrade_array[spell_index - 1]
		change_spell(new_spell,spell.target.id)
		add_to_chat(140,spell.english..' has been canceled. Using '..new_spell..' instead.')
	end
end

function change_spell(spellName,target)
	cancel_spell()
	send_command(spellName..' '..target)
end

function actual_cost(spell)
    local cost = spell.mp_cost
    if spell.type=="WhiteMagic" then
        if buffactive["Penury"] then
            return cost*.5
        elseif buffactive["Light Arts"] or buffactive["Addendum: White"] then
            return cost*.9
        elseif buffactive["Dark Arts"] or buffactive["Addendum: Black"] then
            return cost*1.1
        end
    elseif spell.type=="BlackMagic" then
        if buffactive["Parsimony"] then
            return cost*.5
        elseif buffactive["Dark Arts"] or buffactive["Addendum: Black"] then
            return cost*.9
        elseif buffactive["Light Arts"] or buffactive["Addendum: White"] then
            return cost*1.1
        end   
    end
    return cost
end
[+]
 Fenrir.Brimstonefox
Offline
サーバ: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-04-15 11:44:04  
Ragnarok.Flippant said: »
This is something I wrote a few years ago when someone asked for a similar thing, but for cure/curaga.

It's a little more fluid, and includes the MP part. You can add more spells by adding a new table, listed from lowest to highest tier.

Ah yes thank you tried it last night and appears to be working. I'm using a Mote derivative, so I added this to my User-Globals.lua file and renamed the pretarget function to "handle_spells" (or something like that, because there's a pretarget function elsewhere in the code) and just added handle_spells(spell) to my precast function.

I think I need to have it check for addendum: black for sch main, but I can figure that out.
 Bismarck.Squah
Offline
サーバ: Bismarck
Game: FFXI
user: Squah
Posts: 106
By Bismarck.Squah 2016-04-15 12:16:24  
After shortcuts addon, i stopped making macros for all spells except emergency ones (sleep, stun, etc)

I just created manual shortcuts that are easy to type.

First letter of tier and number = spell

/t4 casts thunder 4
/b5 casts blizzard 5 etc. Works really well
 Ragnarok.Flippant
Offline
サーバ: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-04-15 12:34:16  
Fenrir.Brimstonefox said: »
Ragnarok.Flippant said: »
This is something I wrote a few years ago when someone asked for a similar thing, but for cure/curaga.

It's a little more fluid, and includes the MP part. You can add more spells by adding a new table, listed from lowest to highest tier.

Ah yes thank you tried it last night and appears to be working. I'm using a Mote derivative, so I added this to my User-Globals.lua file and renamed the pretarget function to "handle_spells" (or something like that, because there's a pretarget function elsewhere in the code) and just added handle_spells(spell) to my precast function.

I think I need to have it check for addendum: black for sch main, but I can figure that out.

Spells you cannot cast are caught by the filtered_action(spell) function. You can just put degrade_spell(spell,find_degrade_table(spell)) right in there, so that if you cannot cast a spell, it will look for and try the next lower version of it.
 Fenrir.Brimstonefox
Offline
サーバ: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-04-15 19:40:59  
Ragnarok.Flippant said: »
Spells you cannot cast are caught by the filtered_actions(spell) function. You can just put degrade_spell(spell,find_degrade_table(spell)) right in there, so that if you cannot cast a spell, it will look for and try the next lower version of it.

Not sure how to get it to work, I can't even get an add to chat message to register in job_pretarget when I say try to cast thunder 5 as sch w/o dark arts/addendum: black up. What file/function do I need to add what to?
 Ragnarok.Flippant
Offline
サーバ: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-04-15 20:12:51  
If GS detects you don't have access to an action (don't know spell, level too low, etc.), you will never hit pretarget/precast/midcast/aftercast. Instead, those actions get caught specifically by the filtered_action function, which most GS files don't use.

Looking over Mote's libs, I don't see him using it, so you should be free to place it directly into any file or include.
Code
function filtered_action(spell)	
	if find_degrade_table(spell) then
		degrade_spell(spell,find_degrade_table(spell))
	end
end
[+]
 Fenrir.Brimstonefox
Offline
サーバ: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-04-15 22:50:09  
awesome sauce that worked thank you much!
 Valefor.Madranta
Offline
サーバ: Valefor
Game: FFXI
user: Madranta
Posts: 89
By Valefor.Madranta 2016-04-15 23:46:48  
As an alternate way of doing this I have mine setup so you toggle the element you want with Alt 1 through 8, then choose the tier or other spell types with Ctrl. I use Ctrl 1 through 6 for nuke tiers 1 through 6, Ctrl 7 and 8 for Ancient magic tiers (may change these for how infrequently they are used), Ctrl 9 for Enfeebles and Ctrl 0 for /SCH weather spells. -Ga's and -Ja are in a separate macro set.

When you toggle an element it will stay that element until you choose a different one. E.G. after toggling Dark, T3 will always try to cast Aspir III until a new element is chosen. If you then toggle Aero, the same T3 macro will now try to cast Aero III.
necroskull Necro Bump Detected! [45 days between previous and next post]
Offline
Posts: 148
By RolandJ 2016-05-31 10:58:20  
Edit: The following only happens when my main job is SCH and I try to cycle down to the lower-tiers of a spell by repeatedly attempting a T6 cast. I guess when it hops off the filtered_action train it gets hung on the recasts. If I main BLM instead it successfully cycles all the way down to t1 from repeated T6 attempts forcing the higher tiers into recast - in this case it never gets handled by the filtered_action function.

When using all of the code that the user Flippant's posted I cannot get it to cycle to another spell if during the degradation cycle it stumbles upon a spell that is waiting on recast. It will, however, successfully continue the cycle as long as the spell that it's currently trying to degrade to isn't available to your current job, though.

If I make the fire table..
fire>fire2>fire3>fire4>fire5>firaja>fire6
And then if I try to cast fire6 on SCH without addendum black it will attempt the following
fire6>firaja - gets caught by filtered_action & cycles to
firaja>fire5 - gets caught by filtered_action & cycles to
fire5>fire4 - gets caught by filtered_action & cycles to
fire4>fire3 fire 3 casts since sch has access to it.

If I try to cast fire6 again the cycle continues until it reaches f3 and if f3 is still on recast it simply stops there and does not try to cast f2.
 Ragnarok.Flippant
Offline
サーバ: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-05-31 15:35:39  
The issue is that the pretarget function is not hit for spells that are executed using ID. Makes sense I guess, but not something I expected. There's two solutions.

1. Change spell.target.id to spell.target.raw in the degrade_spell function.
Code
function degrade_spell(spell,degrade_array)
    local spell_index = table.find(degrade_array,spell.english)
    if spell_index>1 then        
        local new_spell = degrade_array[spell_index - 1]
        change_spell(new_spell,spell.target.raw)
        add_to_chat(140,spell.english..' has been canceled. Using '..new_spell..' instead.')
    end
end


2. If the above isn't ideal because you specifically handle certain situations using ID (as I do), then you'd need to move the pretarget section to precast. The 'return' will make sure you don't unintentionally do anything like equip precast gear when the spell does not go through.
Code
function precast(spell,action)
    local spell_recasts = windower.ffxi.get_spell_recasts()
    if (spell_recasts[spell.recast_id]>0 or player.mp<actual_cost(spell)) and find_degrade_table(spell) then      
        degrade_spell(spell,find_degrade_table(spell))
	return
    end
	
	--rest of your precast function
end
[+]
Offline
Posts: 148
By RolandJ 2016-05-31 15:45:15  
Thank you! I'm not sure if I should use target.raw or target.id because I'm not familiar with where and what mote's library and my job.luas use this feature (target.id) for and so I just went with changing it to the precast function instead to be on the safe side and --- it works :D Very nice Flippant, thank you.
necroskull Necro Bump Detected! [67 days between previous and next post]
 Fenrir.Brimstonefox
Offline
サーバ: Fenrir
Game: FFXI
user: Brimstone
Posts: 183
By Fenrir.Brimstonefox 2016-08-06 16:16:23  
Question for Flippant, any idea why this doesn't work for Ninjutsu?

It gets the send_command() int he change_spell() function but then nothing. spellName looks correct my theory its something with the id but I don't know...
 Ragnarok.Flippant
Offline
サーバ: Ragnarok
Game: FFXI
user: Enceladus
Posts: 658
By Ragnarok.Flippant 2016-08-07 00:09:33  
There are a number of spells and abilities that shortcuts will not pick up if there is a space in them; it happens primarily when the first word is shared with another ability, but not always. It's something I've been meaning to look into, but haven't bothered because it's easier to just strip everything of spaces.

Change the change_spell() function to
Code
function change_spell(spellName,target)
    cancel_spell()
    send_command(spellName:gsub('%s','')..' '..target)
end
Log in to post.