Users browsing this thread: 1 Guest(s)
Possible solution to the sap death bug

#4
Posts: 200
Threads: 1
Thanks Received: 10
Thanks Given: 0
Joined: Oct 2015
Reputation: 18
Status
None
1)
Quote:Hey, didn't mean to step on your toes -- if it weren't for your C2 disassembly, there's pretty much no way I'd even have started learning asm in the first place, much less started trying to patch bugs! So you really have my gratitude.

no problem.  it's mainly a matter of me having such a large backlog of unreleased patches, which are almost always waiting on the Readmes.  those in turn are usually drawn out by tweaking and refining the main description or, especially in this patch's case, writing the FAQ section or sections dealing with detailed oddities of admittedly low consequence.  by waiting indefinitely to finish and release these things, i run the risk of somebody else tackling it in the meanwhile.  it's frustrating on any patch, but magnified umpteen times for this one, due to said bazillion hours of planning it.

i appreciate the kind words; glad C2 was inspiring.

2)
Quote:Could you walk me through some of the pitfalls of the simpler approach I posted above? I saw in your code that you ensured these "death override" counters use the limited script functionality (i.e. >= FC only), which is definitely something that I overlooked. But aside from that, can you help me figure out a scenario where my patch would fail?

you mentioned a key one regarding limited script functionality.

back in 2015-2017, when i was in my heyday of planning my patch, and all sorts of variants that would never see the light of day, i could come up with numerous weird scenarios that'd arise from a pondered change or added feature.  sure, lots of them would be hypotheticals or only happen really narrowly.  but i was locked in when it came to exploring interactions/side effects (as bugfixes go, this one is more fraught than most).

3.5 years is a long time!  i barely remember most of this stuff.  generally, i'll have to study this further.

regarding your patched C2/4BF4, one loophole coming to mind is that you don't seem to enforce any per-batch limitation as long as the entity has died since last executing Command 1Fh, counterattack variant.  the exploiting example doesn't involve an actual monster i'm aware of, but an edited, simple counterattack script.  however, i consider it fair game, because the game's assembly functions should be robust to valid scripts, in the concept of modularity.  (that is, it's a bit different from expecting Assembly Function A to be robust to alterations to Assembly Function B.  things such as stats and scripts are more like input data, while a fellow assembly function is more of a peer that's part of the same processing structure.)

hack a monster appearing in a like group to have a counterattack script of:
Code:
FC 12 00 00 (If the following monster(s) is/are dead (target last attacker): )
15          (Quake)
F1 36       (Set Target to Self)
30          (Life)
FF          (End If, End Script)

whittle away much of each monster's HP.  kill one of them.  its Quake will kill the others, it'll revive itself, another one will counter with Quake and revive itself, etc., etc.  an infinite loop until they run out of MP! Surprised  (Note: i manually typed your C2/4BF4 patch into a different computer for testing, so there's a 1% chance i flubbed something. Hmm )

i suspect that the "One Command 1Fh Per Batch" limitation was originally created by Square to avoid endless strings of counters (mainly finals).  so they were rightfully wary about things running away and getting all-consuming.

3)
Quote:
Quote:I also am wondering whether your patch at $4CA2 would have any effect at all. Under what circumstance would a "normal" attack be preparing its counterattacks while the counterattack queue had pending periodic damage? Wouldn't the counterattack queue have to be empty before the "normal" attack queue got checked?
OK, I thought through the above, and figured out a scenario that would break. If an attack triggers a counterattack from Enemy A, and Enemy B gets a sap queued while the attack executes, then if Enemy A's reaction targets Enemy B, then the pending Sap tick will prevent Enemy B from queuing its reactive script, even if it is killed by the counterattack.
thank you for that example!  i could swear that i'd come up with at least one breakage scenario, but it's been so long, and my notes are too long and detailed and tangential for me to readily find it.  i'd have to slow down and comb through them for awhile to be more sure.  that's if they even include it in the first place; some key investigations regarding the bug and patch actually preceded my note-taking, while occurring after my mnrogar forum posts.  it's like i thought i could remember certain things indefinitely, or that i'd have refined them into a patch Readme section before they were forgotten.

minute details and off-the-wall crap got *better* attention in my notes, in the fear they'd be more readily forgotten.

with some focused memory jogging, i was gradually arriving at counterattacks from multiple enemies.  but at the current pace, it would've taken me another half day, at least.

Quote:(Edit: On second thought, this would still function correctly, as Enemy B's next Sap tick will trigger its reactive script, due to $3A56).
will C2/5018 allow this?  i think the omni-counter might have to wait until *another* entity's periodic damage/healing occurs, or an entity takes a normal turn.

Quote:My next thought is -- why not remove the check at $4CA2 altogether? If a duplicate reaction script is queued, it will inevitably be aborted due to the $33FC flag. And the $3A56 flag will only override the $33FC flag once (per my changes above).
the queuing does create needless junk for C2/4B7B and C2/4BF4 to process.

there's another reason, from my October 2015 notes and semi-coherent to December 2020 me, which i'm in the process of deciphering.

i think my patch approaches C2/4BF4 properly.  it recognizes that vanilla C2/4BF4 is short-sighted in its indiscriminate treatment of queue siblings, and almost certainly not what was intended.  (that is, allowing a periodic damage and a counter to coexist in the queue does not risk whatever nightmare scenario -- perhaps an endless string of counters/finals -- the designers were trying to avoid with the queuing restriction.)  yet it also recognizes that a precaution was put there for a reason.

the two main issues with my patch's add-on function are size and speed.  i barely care about the former; free space can still be found decades after the game's release, and fitting things in-line is more a point of pride, which shouldn't trump maintaining functionality.  the latter could be obnoxious with the queue walking performed by my routine, but the shortness of the average counterattack + periodic damage/healing queue limits its harm.

both metrics could be improved by ditching the queue walking for setting and clearing a custom flag to track Command 1Fh's presence in the queue.  a tentative variant i'd written uses a free RAM bit (probably Bit 3 of $3AA1,X), clearing it at C2/4B97, and setting it at C2/4CAC.

4)
regarding your C2/4C5B changes: does your alternate code change any functionality from your first, shorter code?  i can't readily tell.

anyway, proceeding based on the simpler version: this tweak goes to something i'd thought about on MANY instances during my patch planning: Square's subtly different treatment of the "death override" in C2/4C5B versus C2/4BF4.

in the former, first-executed function, they have these criteria for queuing:
((entity hit by attack) AND (entity not targeting self) AND (conventional attack)) OR (entity died since last Command 1Fh [counterattack] execution)

then because $33FE gets a subset of the first multi-clause, (conventional attack) is dropped from the criteria for detecting "death override" in the later-executed C2/4BF4.

the asymmetry always struck me as curious, but i couldn't necessarily decide it to be unintentional or without merit.  i can see why Square might want to put a "fully-fledged" counterattack, launched by a discrete other entity, in a different category from something like periodic damage/healing, which *conceptually* isn't really a full-on attack and has no extrinsic source.  and i can see why, in the absence of an FC 12 command in the script, they might want to broaden what the dying monster can retaliate against as it shuffles off this mortal coil.  iow, they wouldn't want to take away from the bite of lesser beings that have more simplistic brains (read: scripts). Tongue  the base quest for vengeance knows no IQ!

so it's something i'd probably keep deferring to (and my patch practically always does).  though i also get why it's tempting to iron out an inconsistency, and to achieve a unified representation of the "death override" from the "transmitting" (1Fh triggering) function to the "receiving" (1Fh executing) function.
Quote  
[-] The following 1 user says Thank You to assassin for this post:
  • Bropedio (12-12-2020)



Messages In This Thread
RE: Possible solution to the sap death bug - by assassin - 12-12-2020, 12:34 AM

Forum Jump:

Users browsing this thread: 1 Guest(s)


Theme by Madsiur2017Custom Graphics by JamesWhite