|
Niche FFXI Tips, Tricks and other oddities...
By RadialArcana 2025-02-15 06:26:14
How does Gearswap break the 1 second server rule? It obviously swaps gear around faster than the actual game is supposed to allow.
By Kaffy 2025-02-15 06:33:24
Carbuncle.Maletaru
Server: Carbuncle
Game: FFXI
Posts: 3,224
By Carbuncle.Maletaru 2025-02-15 06:36:19
How does Gearswap break the 1 second server rule? It obviously swaps gear around faster than the actual game is supposed to allow.
I haven't actually looked at the code for GS, but AFAIK it just sends a (series of?) packet saying "equip these 16 items". It doesn't send /equipset 102 to the server.
It can send these packets as often as it wants. Sometimes it sends commands saying "equip these 16 items, then cast this spell, then equip these 16 items" all in a single command.
It works entirely differently from in-game macros, which is why I keep insisting on how GD different it is, despite ignorant trolls saying "GS is just in-game macros in a .lua file" over and over for years. They're absolutely nothing alike.
[+]
By Shichishito 2025-02-15 06:37:15
I don't think it's a "server rule". The server takes information in chunks called packets afaik, in FFXI case that hapens in a set interval of 2 or 3 times each second, either way extremely few for todays standards.
The up rounding to a full second is a macro specific thing that happens on your PC within FFXI, independant from server packets.
[+]
By RadialArcana 2025-02-15 06:43:11
So in theory an addon could be made that removed this 1 second limitation for everyone, not just people using GS.
Shiva.Thorny
Server: Shiva
Game: FFXI
Posts: 3,214
By Shiva.Thorny 2025-02-15 07:04:52
When the client is told to create a packet, it goes through a series of checks before adding it to the internal packet queue. For equipset, it checks if another equipset has been sent in the last 1 second. For single slot equip, it checks if another single slot equip of the same slot has been sent in the last second. If either is true, the packet won't be queued. It's not macro specific, typed commands or multiple macros or even equip screen swaps will still face the same limits. If you've ever tried to move a bunch of items quickly with the ingame interface, you've probably noticed that they don't go through if you move faster than 1 item/sec (same issue here).
When windower inserts packets, none of these checks are followed. The server doesn't enforce any of it.
It would be possible to hook the function that evaluates whether another packet can be sent and alter the result for specific packets. I am not sure if it'd allow you to guarantee the same order (equipset->action->equipset) in the actual outgoing block like GS. Probably can't do it in an addon either, you'd need at least a sidecar DLL file since windower's plugin API isn't public. Definitely an interesting idea for people who wanted to split the difference and have better precasts without committing to a full GS file.
Phoenix.Iocus
Server: Phoenix
Game: FFXI
Posts: 1,869
By Phoenix.Iocus 2025-02-15 07:44:49
Not looking to divert. Just asking tinfoil questions.
Is there any reason that equipsets would execute in game actions faster than macros using gearswap in the background that mimics just the basic functionality of equipsets?
Shiva.Thorny
Server: Shiva
Game: FFXI
Posts: 3,214
By Shiva.Thorny 2025-02-15 07:51:49
Is there any reason that equipsets would execute in game actions faster than macros using gearswap in the background that mimics just the basic functionality of equipsets?
Not really. If you mean measurable performance, they will both be the first frame after the next packet interval so the difference will be less than 1/30 second and depend on which aligns closer to the frame timing-wise than anything based on performance. (If the technically slower option resulted in a frame occurring sooner after the packet interval, it might be effectively faster.)
In terms of cpu time, it'd be difficult to gauge but I assume gearswap is slower than client. In this case, you're talking about nanoseconds, it doesn't matter at all.
[+]
Server: Asura
Game: FFXI
Posts: 1,464
By Asura.Pergatory 2025-02-15 15:45:23
Maquette Ring works in Ambuscade
[+]
Fenrir.Svens
Server: Fenrir
Game: FFXI
Posts: 137
By Fenrir.Svens 2025-02-15 21:18:49
Buffs that persist upon zoning appear to the left/before the food icon, buffs that wear upon zoning appear to the right/after the food icon. Just in case you want to load up on the absolute maximum amount of buffs for whatever reason.
[+]
Cerberus.Dekar
Server: Cerberus
Game: FFXI
Posts: 256
By Cerberus.Dekar 2025-02-15 21:24:46
Sigil works in Odyssey for the Regen, Refresh, and extended food duration.
By Kaffy 2025-02-27 18:06:59
Real minor one here, but I like it. When you set your home point, the game saves your position and camera angle relative to the home point so you can take off running in the right direction and see what you want to. Warping to another homepoint sets your position and camera to a default.
Server: Fenrir
Game: FFXI
Posts: 3,425
By Fenrir.Skarwind 2025-02-27 18:25:07
Maquette Ring works in Ambuscade
IIRC all of the legion items do. I used to use that STR/DA ring at one point.
[+]
Carbuncle.Nynja
Server: Carbuncle
Game: FFXI
Posts: 5,027
By Carbuncle.Nynja 2025-02-27 18:55:29
Warping to another homepoint sets your position and camera to a default. I think this was one of the things that set off red flags on the iteration of superwarp.
Bahamut.Senaki
Server: Bahamut
Game: FFXI
Posts: 207
By Bahamut.Senaki 2025-02-27 22:18:31
You can learn the Blu Spell "Mighty Guard" from the RoV fight Mission 3-17 ( No Time like the Future). This bypasses the need to farm access to Shinryu.
Server: Asura
Game: FFXI
Posts: 27
By Asura.Anybody 2025-02-28 00:59:35
You don't lose invisible if you get onto a mount.
By Hovann 2025-02-28 13:56:07
Hold [Tab] and [Shift] while on your non-chocobo/non-vehicle/non-floating mount and you can moonwalk with it by going backwards.
And if you turn your mount as you press those two and hold the opposite direction, you can moonwalk sideways while blaring the first few notes of Billie Jean.
[+]
By LightningHelix 2025-02-28 14:05:24
You can learn the Blu Spell "Mighty Guard" from the RoV fight Mission 3-17 (No Time like the Future). This bypasses the need to farm access to Shinryu. You can also learn it from someone else's mission 3-17, because you can't repeat that mission yourself once you're past it.
And if the person who doesn't have the clear yet disconnects on purpose, you can kill it and then have them reconnect without the clear, in case you don't learn it the first time!
By Felgarr 2025-02-28 16:12:23
Hold [Tab] and [Shift] while on your non-chocobo/non-vehicle/non-floating mount and you can moonwalk with it by going backwards.
And if you turn your mount as you press those two and hold the opposite direction, you can moonwalk sideways while blaring the first few notes of Billie Jean.
I like to do this with crawler mounts and pretend I'm in Tokyo Drift.
Server: Asura
Game: FFXI
Posts: 112
By Asura.Buffyslyph 2025-02-28 19:22:51
You don't have to pay for ffxi if you turn your subscription off.
Leviathan.Wiccaan
Server: Leviathan
Game: FFXI
Posts: 29
By Leviathan.Wiccaan 2025-03-05 18:32:32
Regarding the equipment set discussions above; I have released a new addon for Ashita v4, called quicksets, that accomplishes the desired effect. This allows you to stack multiple equipsets into a single command/macro, and allows them to be properly queued and sent to the server. The order in which things are done in the macro are preserved properly as well (ie. equipset -> action -> equipset) as long as the player is not using another addon or plugin that is rewriting the manner in which equip/equipset packets are being sent.
With my addon, you can now do things such as: Code /equipset 1
/ma "Cure" <t>
/equipset 2
Normally the client would give a command error on the second equipset attempt.
For those interested, you can find my new quickset addon on the Ashita Discord server, in the 'v4-beta-plugins' channel.
~~~
For any of the fellow nerds that are interested in how this works, there are three different patches that need to be done to the client in order for this to work.
1. /equipset Command Delay
The equipset command has a built-in delay it uses to prevent the command from being used too fast. This delay is 900ms and is checked after some other validation takes place first. The delay check looks like this:
Code ret = FUNC_Equipset_CheckReuseDelay(); // This function is just: return FUNC_ntTimeNowGet() - PTR_LastEquipsetTime > 900;
if (ret)
{
PTR_LastEquipsetTime = FUNC_ntTimeNowGet();
// process and perform the equipset here..
}
If the 'FUNC_Equipset_CheckReuseDelay' function returns false, then the timing check failed and the equipset attempt is blocked. Otherwise, the equipset attempt is allowed and the 'PTR_LastEquipsetTime' is updated with the current timestamp, then the equipset attempt is processed. The patch here is to ignore the time check and just always process the equipset attempt.
2. Command System Delay
When the game client processes a command handler, it uses the handlers return value to determine if additional command attempts should be allowed to happen without a delay. This is used as a means to prevent spamming certain commands and causing extra traffic to the server that does not need to happen. The last part of the equipset command handler determines if the equipset attempt was successful or not and if continued use of the command should be prevented/delayed or not. That looks like this:
Code if (FUNC_Equipset_Equip(equip_set_id, echo))
return cmd_num;
else
return -cmd_num;
To prevent the client from blocking multiple equipset commands in a row, a patch is needed here to alter the return value.
3. Equipset Packet Queueing
The game client is designed to queue packets into chunks and send them at a calculated interval. (This system was designed with 56k modems in mind, allowing the game to function on dial-up internet.) This queue system has several arguments that are used when the client is attempting to queue a packet to be sent which determines how the packet will be processed and queued. These arguments include things such as checking for a delay between the same kind of packet attempt, overwriting an existing packet of the same kind that is already queued, or allowing for multiple of the same packet to be present in the same chunk. The call to queue an equipset packet looks like this:
Code pkt = FUNC_gcZoneSendQueSearch(0x51, 0, 0);
if (!pkt)
return 0;
// snipped the packet building code here..
FUNC_gcZoneSendQueSet(pkt, 0x48, 0);
The normal behavior of this packet is to not allow additional equipset packets to be queued if one is already present. The first valid equipset attempt is honored and queued, while additional ones are ignored until the queue is processed, send to the server and cleared. The patch here is to change the argument that prevents multiple of the same opcode to be queued.
By Tarage 2025-03-05 18:59:48
Have another Summoner one: Cait Sith can give Reraise III with infinite duration. Cait Sith's 1hr gives everyone on your party RR3 and casts Arise on any dead party member. The resulting RR3 has no timer and will last until you either tick it off manually or change jobs. I try to always keep it on in case of emergency. Sadly it still gets eaten by trove...
[+]
Leviathan.Wiccaan
Server: Leviathan
Game: FFXI
Posts: 29
By Leviathan.Wiccaan 2025-03-05 19:54:46
From the earlier discussions in this topic; to help dispel the misinformation regarding the way the client treats and handles waits, here is how that works in the client.
The client has a single function that is used to parse and determine the delay times that will be used from a /wait command or an inline <wait..> tag. That function is called FsMacroContainer::_checkWaitCommand and looks like this:
Code int __stdcall FUNC_FsMacroContainer__checkWaitCommand(char *str, uint32_t *start_time, uint32_t *wait_time)
{
char *ptr1; // eax
const char *ptr1_; // esi
char *ptr2; // eax
int cnt1; // eax
int cnt2; // eax
int wait; // [esp+8h] [ebp-244h] BYREF
char v10[64]; // [esp+Ch] [ebp-240h] BYREF
char buffer[512]; // [esp+4Ch] [ebp-200h] BYREF
ptr1 = strstr(str, "<wait");
ptr1_ = ptr1;
if ( ptr1 )
{
ptr2 = strstr(ptr1, ">");
if ( ptr2 )
{
ptr2[1] = 0;
cnt1 = sscanf(ptr1_, "<wait%d>", &wait);
*ptr1_ = 0;
if ( cnt1 != 1 )
{
wait = 1;
LABEL_6:
*start_time = FUNC_ntTimeNowGet();
*wait_time = 1000 * wait;
return 0;
}
if ( (unsigned int)wait <= 60 )
goto LABEL_6;
}
return 0;
}
FUNC_FsTextInput_convertToString2(PTR_g_fsTextInput, str, strlen(str), (int)buffer, 512, 0, 0);
cnt2 = sscanf(buffer, "%s %d", v10, &wait);
if ( strcmp(v10, "/wait") || wait <= 0 || wait > 60 )
return 0;
if ( cnt2 == 1 )
wait = 1;
*start_time = FUNC_ntTimeNowGet();
*wait_time = 1000 * wait;
return 1;
}
The most common bit of misinformation regarding wait times is that they allow for fractions of a second. This is not true. The client specifically parses (scans) the delay amount from the command/tag as an integer via the '%d' formatter. This means that it will not accept decimal numbers, at all.
The next bit of misinformation is how the client handles the value and if it performs rounding. (ie. people claiming it rounds to the nearest 1) This is not true and there is no rounding performed, at all. Again, the client is reading a signed integer value from the string using the 'sscanf' call. When the '%d' formatter is used, it ignores the decimal place entirely and only uses the whole number given, if one was found.
The manner in which the client treats /wait commands vs. the inline <wait..> tags is also different. This is likely where the misunderstanding is coming from as the command form does not have a default fallback value, while the inline tag does.
When using the /wait command, there is no fallback value if an invalid wait time is given. Instead, the client will simply ignore the wait altogether. The function will fail and return false and the wait_time argument will not be set.
To give some examples of this, here is how this function would treat the following command attempts:
Code /wait - Returns false; no wait happens.
/wait 0 - Returns false; no wait happens.
/wait 0.1 - Returns false; no wait happens.
/wait 0.9 - Returns false; no wait happens.
/wait 1 - Returns true; wait is 1000ms.
/wait 1.1 - Returns true; wait is 1000ms.
/wait 1.9 - Returns true; wait is 1000ms.
/wait 60 - Returns true; wait is 60000ms.
/wait 61 - Returns false; no wait happens.
Here you can see how fractions of a second are not handled and are ignored. The '%d' formatter used with 'sscanf' will only accept a valid integer value and ignore the decimal place entirely. (Note: While not that interesting, it is also valid to prefix numbers in this formatting method with a -/+ to denote a negative or positive number. FFXI will allow for positive prefixes, but considers negative ones invalid as the number falls below its clamped value of 0. This means that it is valid to use /wait 2 and /wait +2 to mean the same thing.)
The function will then check if the value falls within a clamped range to be considered invalid.
This range is: <= 0 || > 60
This means that only values 1 to 60 (inclusive) are valid for the /wait command.
When using the inline <wait..> tags, there is a fallback value of 1. However, the fallback value is only used under certain conditions. There are still times where the wait will be invalid/rejected. The following table shows some examples of how the inline tag is treated:
Code // The following uses the 1000ms fallback time..
/wave <wait> - Returns false; wait is 1000ms.
// The following are all treated as a wait of 0..
/wave <wait0> - Returns false; no wait happens.
/wave <wait 0> - Returns false; no wait happens.
/wave <wait0.1> - Returns false; no wait happens.
/wave <wait 0.1> - Returns false; no wait happens.
// The following all only see the wait value of 1..
/wait <wait1> - Returns false; wait is 1000ms.
/wait <wait 1> - Returns false; wait is 1000ms.
/wait <wait1.5> - Returns false; wait is 1000ms.
/wait <wait 1.5> - Returns false; wait is 1000ms.
/wait <wait1.9> - Returns false; wait is 1000ms.
/wait <wait 1.9> - Returns false; wait is 1000ms.
// The following demonstrate the range limit and negative prefix..
/wave <wait 60> - Returns false; wait is 60000.
/wave <wait 61> - Returns false; no wait happens. (Outside the valid range.)
/wave <wait +60> - Returns false; wait is 60000. (Valid positive prefix.)
/wave <wait -60> - Returns false; no wait happens. (Invalid negative prefix.)
Here you can see the fractions are again, ignored entirely and no rounding happens. The value(s) after the decimal are just simply ignored, only making use of the integer value prior to it. (You could consider this a means of flooring, but it's technically not.) The inline wait tag also allows for the delay value to be directly after the word wait, or can contain a space between the word and the number value. It also supports the positive/negative prefixes while negative ones will be considered invalid due to the value range clamping. (1 to 60 inclusive.)
While not important to this discussion, some may notice that this function always returns false when processing an inline tag, even if a valid wait time is returned. This is because the command handler uses the functions return (true/false) to determine if the current processed command is delayed or not. When using a /wait command, the command itself needs to be delayed, and will cause this function to return true when a valid wait is detected. Otherwise, when processing an inline wait tag, the function will return false, allowing the command being processed currently to fire immediately, while then applying the delay to the next command.
~~~
tldr; The client does not support decimals in wait times.
Ragnarok.Martel
Server: Ragnarok
Game: FFXI
Posts: 3,011
By Ragnarok.Martel 2025-03-06 10:47:38
I've tested and posted a much less technical and detailed version of this sort of thing multiple times, but the idea always seems to pop up again. <,<;
Perhaps such an in-depth case by case explanation will sink in better if we can point enough ppl at it. Great post. Thank you.
By Kaffy 2025-03-06 11:33:57
So I guess then the aby vnm trick is only possible because of ja0wait?
Shiva.Thorny
Server: Shiva
Game: FFXI
Posts: 3,214
By Shiva.Thorny 2025-03-06 11:43:35
So I guess then the aby vnm trick is only possible because of ja0wait?
VNM trick happens because the server cancels the old attempt to pop when it sees a new one. JA0Wait isn't necessary, nor is any mod, if you rest fast enough it could still occur. You wouldn't be able to move as easily though, so you might have to just mash heal while standing in a place near it until it wanders onto you.
It is *much* easier to accomplish consistently if you use an alternative method to get around the delay between rests. Even easier if you also modify the S>C packet to show you standing the whole time, though you'll be sliding around to everyone else.
Edit: I still wouldn't take 'can be done vanilla' to mean it is 110% safe. I highly doubt SE will do anything about it, but it would still be clear intent if you popped it that way numerous times. Exploiting systems using vanilla is still against TOS.
[+]
By Lili 2025-03-06 12:46:43
Leviathan.Wiccaan said: »tldr; The client does not support decimals in wait times.
There was, for a while, a JP blog that claimed that <wait 0> tags would force the client to wait for the command to resolve before moving onto parsing the successive. Such "info" certainly did not help reduce the confusion.
By Moonlightagb 2025-03-06 18:08:17
If you turn on the jobemote filter in the chat filters so you can't see them anymore, you can still use the emote even though you can't see it but everyone else will. Doing this allows you to "jobemote nin" and move around instead of being posed in place on top of the frog, and everyone will see a giant frog moving around
Carbuncle.Nynja
Server: Carbuncle
Game: FFXI
Posts: 5,027
By Carbuncle.Nynja 2025-03-06 18:21:05
I wouldnt do that because someone who doesnt know better is gonna assume you're cheating and mash those GM reports.
I'm sure it looks hilarious to others, but I wouldnt want to risk that on my accts.
Ragnarok.Jukiro
Server: Ragnarok
Game: FFXI
Posts: 206
By Ragnarok.Jukiro 2025-03-06 23:02:45
iirc you can /jobemote nin and then /jump and be able to move around with only the frog mostly visible
OK, another one of my threads where I ask the audience for your input on FFXI-randomness. All I ask is that you stay on topic.
Let's hear some of your really niche use-cases for anything within FFXI that has been beneficial to you. (It doesn't have to be beneficial to anyone else either. It just has to be something you decided to do because it was helpful to you, or a friend, or to get out of some tricky situation). These can be items used in a way that you hadn't considered before, or maybe you have a mule in a strange location ...or maybe you have a cooking mule that stores nothing but walnuts*?
I'll go first. I have a $1 mule that I use for troves, vouchers, login points, extra armor storage that I may need at a later date, so I activate/reactivate it as needed. For convenience sake, I also parked this level 10 character behind the Altepa Gate in Western Altepa Desert:
*Many years ago, before crafting shields, someone told me that walnuts were a really important ingredient to get Cooking from 100 to 110, so ....I also have a mule that stores Walnuts...that I just forgot about:
...OK folks, your turn.
|
|