You should look into if the action packet sends spell_finish on interruptions or anything that doesn't let the spell cast to completion. This would be the best way to handle this.
You should look into if the action packet sends spell_finish on interruptions or anything that doesn't let the spell cast to completion. This would be the best way to handle this.
Figured it out. If you load this in an addon and go cast stuff, it will print to chat log what it detects. I only tested start / finish / interrupt, there may be other params you need to cover. Not sure if paralyze is different than an interrupt and stuff like that.
You could use this, it detects interrupts and spell casting finishing using the action packet, shouldn't be hard to incorporate into gearswap. Just change the send_commands into your variable swaps. You could even use the action packet to swap your variable to true instead of your precast.
Also, are you sure aftercast doesnt do what you want? It is documented as "Passes the resources line for the spell with a few modifications. Occurs when the “result” action packet is received from the server, or an interruption of some kind is detected."
Code:windower.register_event('action', function(act) if act.category == 4 and act.actor_id == windower.ffxi.get_player().id then windower.send_command('input /echo finished') elseif act.category == 8 and act.actor_id == windower.ffxi.get_player().id and act.param == 24931 then windower.send_command('input /echo start ' .. act.param ) elseif act.category == 8 and act.actor_id == windower.ffxi.get_player().id and act.param == 28787 then windower.send_command('input /echo interrupt ' .. act.param ) elseif act.category == 8 and act.actor_id == windower.ffxi.get_player().id then windower.send_command('input /echo unknown param ' .. act.param ) end end)
Uh, maybe Byrth can clarify, but pretty sure that aftercast should still happen, even with a spell interruption.
There is literally a "spell.interrupted" boolean variable that's only valid in aftercast functions...
Thanks Mafai for your research.
I don't remember exactely why I had to implement that coroutine, it's somewhere in this thread lol, long time ago.
But trust me, sometimes that Aftercast wasn't working for whatever reason. Maybe packet-loss? It wasn't happening *all* of the times, but it wasn't something you'd see once every few moons either, it was annoying and dangerous (imagine being unable to cast at crucial moments because the var got stuck on "true").
If the cause was indeed a packetloss, then I'm afraid the same would happen with your small addon?
Edit:
found the original post, here, 2014 lol
Basically we never found out WHY it was getting stuck on "true", but once that happens you're fucked unless you implement manual means to get unstuck (like a manual selfcommand or w/e else)
If Aftercast REALLY works as it should, then maybe the only possible cause is a packetloss?
Maybe Byrth can enlighten us on the possible causes of this behaviour.
You guys don't have this issue? Nobody has a check to avoid precast launching if you're currently casting? Guess I'm the only button-spammer in here lol
Btw the solution I've been using these years (the coroutine one) is very efficient, I like it. It's just that the way "X" is calculated is appearently not enough anymore and, if anything, I should make it smaller. Maybe that would "fix" things for me even in situations of packetlosses. Like using (spell.cast_time*0.20+.1) should be closer to my >80% FC rate that the (spell.cast_time/4+.5) I'm currently using.
It could be lost packets, so you would want to rely on aftercast AND that function. i think you missed an end when pasting midcast, but you get the point.
I would do this.
Code:function midcast(spell) if spell.prefix ~= '/jobability' and spell.prefix ~= '/weaponskill' then casting = true coroutine.schedule(function () if casting then casting = false end end, (spell.cast_time/4+.5)) ... ~real content of my midcast function~ ... endCode:function aftercast(spell,action) if casting then casting = false end ... ~real content of my aftercast function~ ... end
Thumb up, thanks Mafai![]()
In your aftercast, you might as well remove the if, it won't hurt anything to set it to always false there.
The midcast coroutine is just a backup to the lost packet. If you still have a delay issue, I would just bump the .5 up a bit. Like I said, it is just a backup.
Also, maybe you need more paranthesis, I'm not sure how lua is doing the math on this.
coroutine.schedule(function () if casting then casting = false end end, (spell.cast_time/4+.5))
to
coroutine.schedule(function () if casting then casting = false end end, ((spell.cast_time/4)+.5))
I'm pretty sure GearSwap already has this built in. https://github.com/Windower/Lua/blob...tions.lua#L743
It's kind of slow, though, since it doesn't account for fast cast, etc.
For spells:Thinking about it, I wonder if that causes trouble if you're addled.cast_time*1.1+2
Yeah it could be an issue, but #careface.
Anyway why *1.1? That would actually create a timer bigger than the default cast time of the spell. I want it to be shorter!
Atm I have "cast_time*0.2+.1" which is 80% FC plus 0.1 seconds. I actually have more than 80% on SCH but that should be a good generic compromise.
Anyway, change of topic.
There's something strange I can't understand why it's not working in my BRD lua, just noticed because I happened to be testing something else with showswaps on, it's been there probably for ages and I never noticed before.
It's not working, it still swaps to Precast with Nightingale up.Code:function precast(spell,action) ... elseif spell.type == "BardSong" and not buffactive['Nightingale'] then equip(sets.precast.songs) ... end
I've been trying all sort of possible small variations.
Using "buffactive['Nightingale'] == false" or putting those two conditions in a concatenated if, like "If bardsong then ==> if not buffactive" then" etc.
But nothing, still same result.
But wait! Here comes the fun!
It DOES WORK for debuff songs, it just doesn't work for buff songs.
Wtf, why?
I went to check in the resources to see if BardSong spell.type was split in two recently and I never knew but nope, it's still BardSong for both.
So... the fuck is going on here? O.O
You need to post your whole precast because its probably executing something up higher in the if.
This is what I have before:
The specific sets is called sets.precast.songs. "Songs" is not a type, so it shouldn't get used in that "spell.type" line above the one I'm talking about.Code:function precast(spell,action) spell_map = spell_maps[spell.english] if spell.english == 'Mordant Rime' and player.equipment.main == 'Carnwenhan' then custom_aftermath_timers_precast() equip(sets.precast.WS[spell.english][ddmode]) elseif sets.precast[spell.english] then equip(sets.precast[spell.english]) elseif spell.english:startswith('Cure') or spell.english:startswith('Cura') then equip(sets.precast.heal) elseif sets.precast[spell.type] then equip(sets.precast[spell.type]) elseif spell.type == "BardSong" and not buffactive['Nightingale'] then ...
Actually nevermind, found the issue, was very silly!
I am using Falkirk's bst.lua.
I updated to a newer version a month or so ago.
One of the only things I like to do differently is to use a script of aliases to directly assign Jugmode.
ex:
alias ken gs c set JugMode 'Blackwater Broth'
This was working fine until I upgraded.
I get these errors.
Gearswap: Lua runtime error: Gearswap/flow.lua:339:
Gearswap has detected an error in the user function self_command:
... Mote-SelfCommands.lua:56: Unknown mode value: 'Blackwater
I've poked at the functions in flow and Mote-SelfCommands, but I've never learned lua or the intricacies of these scripts.
Any ideas what can/should be changed to make it so that I can manually change JugMode?
try manually setting your alias outside of the script by typing it in game just like the script. if that works, you probably need your apostrophe escaped, but that shouldnt have changed between versions....
alias ken gs c set JugMode \'Blackwater Broth\'
you do know you can cycle through jugmodes using alt-f8 and ctrl-f8 right?
I have a question about indexed tables.
For instance take this
Then I have another thing in my self_command section that does something like this:Code:sets.table.index = {'value 1', 'value 2', 'value 3', 'value 4'}
I basically use it to have an aliased key on my keyboard that I can use to cycle through the values of that table.Code:if command == 'something' then varname = varname + 1 if varname > 4 then varname = 1 end
The "problem" is that the max value has to be changed manually each time I add a new value to the table.
Following the examples above, if I were to add 'value 5' and 'value 6' to the table, I would have to change that "4" below into a "6".
After this long premise, my question is:
Is there a way/function/command to get the number of items inside a table automatically? That way I could use this thing to set the number dynamically, instead of having to update it manually each time I add a new value to the table.
here is an example. its ganked from mot includes. you would just call handlecycle and handlecycleback from your command handler. i missed a lot of functions this uses, but everything you need is in Mote-SelfCommands.lua
Code:state.JugMode = M{['description']='Jug Mode', 'Meaty Broth', 'Bubbly Broth', 'Livid Broth', 'Tant. Broth', 'Blackwater Broth', 'Windy Greens', 'Bug-Ridden Broth'} send_command('bind !f8 gs c cycle JugMode') send_command('bind ^f8 gs c cycleback JugMode')if you want to do it your way...Code:-- Handle cycling through the options list of a state var. -- User command format: gs c cycle [field] function handle_cycle(cmdParams) if #cmdParams == 0 then add_to_chat(123,'Mote-Libs: Cycle parameter failure: field not specified.') return end local state_var = get_state(cmdParams[1]) if state_var then local oldVal = state_var.value if cmdParams[2] and S{'reverse', 'backwards', 'r'}:contains(cmdParams[2]:lower()) then state_var:cycleback() else state_var:cycle() end local newVal = state_var.value local descrip = state_var.description or cmdParams[1] if job_state_change then job_state_change(descrip, newVal, oldVal) end add_to_chat(122,descrip..' is now '..state_var.current..'.') handle_update({'auto'}) else add_to_chat(123,'Mote-Libs: Cycle: Unknown field ['..cmdParams[1]..']') end end -- Handle cycling backwards through the options list of a state var. -- User command format: gs c cycleback [field] function handle_cycleback(cmdParams) cmdParms[2] = 'reverse' handle_cycle(cmdParams) end
Code:function tablelength(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end
The modes class is prettier; I'm posting this for completion.
Your table is an array: the indices are consecutive integers starting at 1 (with no skips). The length operator will correctly return the length of an array.edit: goofedCode:varname = varname % #sets.table.index + 1
It works! Thanks guys! Love this <3 <3 <3
I just returned from a 5 year hiatus, to find that spellcast is no longer used, and everyone is using this newfangled gearswap thing. *Grabs cane and shakes it*
...I distinctly remember being able to edit my scripts on the fly with spellcast, but now I'm getting an error that states that it's being used by another program, even if I don't have gearswap loaded, or NP++ open? Few of my LS mates say they don't have this issue. Any windows 10 users here? I just up(coughdowncough)graded from win 7 to 10 and I'm wondering if it's because of this new OS.
...Also I'm having a few issues with the GS I've been making myself, but I can't post my pastebin for it till I've got 10 posts under my belt.Damn. Any way around it, or should I just not try to do that? I don't really want to enrage any mods.
you can always say go to pastebin at this address
y32JMRPg
for this example address http://pastebin.com/y32JMRPg