Closed Siltala closed 4 years ago
Row is a special command that everybody has. Is not implemented yet because i never found it useful.
Asked cherry about the "Row" command but he hasn't figured this out yet. So feel free to suggest what the "Row" command shall do :D
Just leaving these two links here: https://rpgmaker.net/articles/371/ https://forums.rpgmakerweb.com/index.php?threads/do-you-remember-the-row-thing.20014/
What I remember/think of it:
I remember one non RPG Maker game that used a row system (Pier solar, don't play it, didn't age well) and in this game the front-row completely protected the back row from normal attacks.
The 60/40 makes sense, maybe 70/30 would be better, otherwise your healer is still hitted to often :D.
If I understood this correctly the row does the following: Physical attacks get a 25% bonus (or you receive 25% extra damage when):
Pincer is always 0% bonus. And at the end I see another 75% modifier with the same conditions, so I'm confused.
Looks like the hit-chance is modified in the same way (though not by 25% but by "25 out of 100" + hitchance %)
Enemy is always in the "Front row".
So this is boring.
I can confirm that the damage from physical attacks is increased by 25% if the source and the target are in the front row. From my tests with RPG_RT it looks like that being in the back row doesn't reduce the probability being targeted by an enemy.
To implement Row
properly we'll need to use reverse engineering tools to inspect the RPG_RT binary. The last time I did a quick glance, row has a lot of subtle interactions with damage, dodge rate, and other things. It will be very hard to get row correct by black box testing.
If you're interested in implementing this feature, I can dig into RPG_RT and write out the behaviors I find.
I'm definitely keen on learning more about the technical details of the row behaviors. But I'm not sure if my skills are sufficient to implement the whole row feature.
Ok so good news is as far as I can tell, row only affects normal physical attacks. The adjustments are rather simple
After the adjustment for HasPhysicalEvasionUp()
, the to_hit rate is further adjusted like so:
If defender is an actor:
to_hit -= 25
to_hit -= 25
regardless of rowto_hit -= 25
This happens after dmg = max(0, atk / 2 - def / 4)
, before any other adjustments
If attacker is an actor:
dmg = 125 * dmg / 100
dmg = 125 * dmg / 100
regardless of rowdmg = 125 * dmg / 100
Next, attribute adjustments are applied, then
If defender is an actor:
dmg = 75 * dmg / 100
dmg = 75 * dmg / 100
regardless of rowdmg = 75 * dmg / 100
After this charging, critical hit, strong defense, etc..
All of these numbers should be confirmed with testing
Thank you for providing the data! I did some tests the last days and I noticed that in Normal and Initiative encounter conditions the player party has a damage advantage against the enemy party. I tested this with 800 Attack and Defense for both the players and the enemies (to make calculations easier) which means in normal cases the damage ranges between 160 and 240. I encountered the following:
If encounter condition is Surround: to_hit -= 25 regardless of row
This explains the insane dodge rates I had in my tests with the Surround encounter condition...
Still have to do more tests with the Back, Surround and Pincer encounter conditions to get (halfway) accurate damage values.
Oops, your example is right. I messed up, the 125 is damage bonus based on source row, the 75 is damage reduction based on target row. I will update the post.
More damage values:
Back encounter condition:
Surround encounter condition:
Pincer encounter condition:
Noticeable is the lower average damage in the Back and Surround encounter conditions and the odd player damage values in the Surround encounter condition (this -6.25% is coming from calculating 1.25 times 0.75 which equals 0.9375). In the Surround and Pincer encounter conditions the row doesn't matter on the damage dealt.
Regarding the mechanics of the row state and row adjustment itself. This one is a little strange. RPG_RT has 2 flags, a row
flag and a rowAlt
flag. I haven't yet figured out why there are 2.
Some of these mechanics below are already implemented.
row
flag is what is saved to LSD, rowAlt
is notrow
to decide the toggle. I.E if row == front then row = rowAlt = back
row
flag.rowAlt
flag only.rowAlt
flag. If they differ, actor X position is adjusted and row
set to rowAlt
.if (rowAlt != row) {
adj = (rowAlt == BACK_ROW) ? 24 : -24;
if (encounterCondition == pincer || !mirrored) {
x += adj
} else {
if (encounterCondition == back) {
x += adj
} else {
x -= adj
}
}
}
row = rowAlt;
}
rowAlt = row
row == BACK_ROW
adjust actor position x += 24
btw are row changes in battle temporary or do they carry over? Would've expected a flag for "temporary row" but this rowAlt
is synced with row
in update so doesnt look temporary.
I don't believe they are temporary, row
is the main flag and battle modifies it.
It looks like this rowAlt
only exists because for some reason I haven't determined, they want to update the actors row position one frame after processing the row command.
At least until we understand 2k3 battle system better and refactor it, we could probably get away with not emulating rowAlt and the 1 frame difference as a first pass.
I did the hit rate tests now. Because it is impossible to get the exact accuracy values with black box testing I used the terms "Normal hit rate" (which translates to about 90% hit rate) and "Reduced hit rate" (which translates to about 65% hit rate) if I encountered frequent dodges. The hit rate percentage values are taken from your comment which contains the technical details.
Normal and Initiative encounter condition:
Back encounter condition:
Surround encounter condition:
Pincer encounter condition:
The Surround encounter condition makes the battle literally a dodge-fest and interestingly the Pincer encounter condition doesn't change the damage and hit rate values at all.
I have added a PR (#2321) now which implements the damage and accuracy modifiers depending on the row. But I have an other question: What is from your point of view the correct way to implement the in-battle row command? For me it looks like changes in liblcf are required (new BattleCommand type) and the biggest problem is probably the static database entry needed for the row battle command (this battle command is always available independent of the battle commands set in the LCF database).
There is no lcf enum for row. RPG_RT hard codes the Row command to always be present at the last battle command in the command window.
So it should be rather easy, you just need to add it directly, and then flip the row when the command is used.
@rueter37 Really good catch with pincer attack. It looks like pincer uses an entirely different code path which is why I missed (WTF RPG_RT??). I confirmed by setting a break point and the normal attack code never executes during pincer..
I'm still looking for this
Ok, so while there is an alternate code path for actor weapon attacks, which has to do with dual wield etc.. This was staring me in the face, I just read the code wrong.
You are right that pincer makes row meaningless, which makes sense. I've updated the earlier posts.
Thank you for the pointer how to implement the in-battle row command. I have added a PR (#2322) which implements the in-battle row command. Merging #2321 and #2322 into master closes this issue.
There is also this row command discussion by bugmenot which matches quite close to what matthew figured out: (even the "Back attack is broken" case and "*It's in the damage calculation, but never gets applied since Enemies are not of type 'Actor'. Either copy pasta or dummied out features.")
https://rpgmaker.net/forums/topics/17752/?post=640190#post640190
From IRC:
Ally -> Ally should consider the row of the attacking ally and the defending ally, according to RE code. Should be confirmed with a test.
So I think I understand now why rowAlt
exists.
The row command tries to behave like any other battle command, in that when you select it it doesn't happen right away. First the actor gets added to the battleProgress
list, and acts on their turn. Before they act (like any other action), the interpreter gets called.
So I guess they used this rowAlt
thing to enable that. Still seems very convoluted way to do this though..
With bug #601 having been fixed, most of the commands are now correctly shown and usable in git. However, one of the commands, 'Row' is still missing.
Steps to reproduce: