Player: Embric of Wulfhammer's Castle: "Row" battle command is missing

Created on 18 Dec 2015  路  25Comments  路  Source: EasyRPG/Player

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:

  • Download game ( http://aeresland.net/EmbricDELUXE_2.2.2.7z )
  • Download my savegame from http://www.heavylobster.com/files/Save03.lsd
  • Take one step north to enter combat
  • Select 'strategize'. The 'Row' command, which is present on RPG_RT, is missing from the list. Note that even on RPG_RT, you need to scroll down in the list to actually see it.
Battle Patch available

Most helpful comment

@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

All 25 comments

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:

  • Basically you have front and back row.
  • Not all actors can be in the front row, because it would be back row then ;-)
  • So back row is default
  • Front row "protects" back row, i.e. monsters target first row with higher chance (60/40 or 70/30 ?)
  • speculation: some things work better depending on the row

    • from back row: recovering HP?, preparing a special attack?

    • from front row: higher chance of critical hit?

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):

  • Battle Type is Normal or Initative and you are in the front row
  • Battle Type is Back Attack, row doesn't matter
  • Battle Type is Sourround attack and row is back (???, probably a bug because you can't change the row in Sourround and Pincer type battles)

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

  • [ ] Row adjustments only performed if target is an actor.
  • [ ] Row has no effect on skills
  • [ ] Row has no effect on self destruct
  • [ ] Row has no effect on how monsters choose targets

Physical Attack Evasion Adjustment

After the adjustment for HasPhysicalEvasionUp(), the to_hit rate is further adjusted like so:

  • [ ] The row of the attacker has no effect on evasion

If defender is an actor:

  • [ ] If encounter condition is Normal, or Initiative and defender is in the back row: to_hit -= 25
  • [ ] If encounter condition is Surround: to_hit -= 25 regardless of row
  • [ ] If encounter condition is Back and defender is in the front row: to_hit -= 25
  • [ ] If encounter condition is Pincer row has no effect

Damage Adjustment

This happens after dmg = max(0, atk / 2 - def / 4), before any other adjustments

If attacker is an actor:

  • [ ] If encounter condition is Normal, or Initiative and attacker is in the front row: dmg = 125 * dmg / 100
  • [ ] If encounter condition is Surround: dmg = 125 * dmg / 100 regardless of row
  • [ ] If encounter condition is Back and attacker is in the back row: dmg = 125 * dmg / 100
  • [ ] If encounter condition is Pincer row has no effect

Next, attribute adjustments are applied, then

If defender is an actor:

  • [ ] If encounter condition is Normal, or Initiative and defender is in the back row: dmg = 75 * dmg / 100
  • [ ] If encounter condition is Surround: dmg = 75 * dmg / 100 regardless of row
  • [ ] If encounter condition is Back and defender is in the front row: dmg = 75 * dmg / 100
  • [ ] If encounter condition is Pincer row has no effect

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:

  • Player in front row attacks Enemy: 200-300 Damage (+25%)
  • Player in back row attacks Enemy: 160-240 Damage (卤0%)
  • Enemy attacks Player in front row: 160-240 Damage (卤0%)
  • Enemy attacks Player in back row: 120-180 Damage (-25%)

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:

  • Player in front row attacks Enemy: 120-180 Damage (-25%)
  • Player in back row attacks Enemy: 150-225 Damage (-6.25%)
  • Enemy attacks Player in front row: 120-180 Damage (-25%)
  • Enemy attacks Player in back row: 160-240 Damage (卤0%)

Surround encounter condition:

  • Player in front row attacks Enemy: 150-225 Damage (-6.25%)
  • Player in back row attacks Enemy: 150-225 Damage (-6.25%)
  • Enemy attacks Player in front row: 120-180 Damage (-25%)
  • Enemy attacks Player in back row: 120-180 Damage (-25%)

Pincer encounter condition:

  • Player in front row attacks Enemy: 160-240 Damage (卤0%)
  • Player in back row attacks Enemy: 160-240 Damage (卤0%)
  • Enemy attacks Player in front row: 160-240 Damage (卤0%)
  • Enemy attacks Player in back row: 160-240 Damage (卤0%)

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.

Savegames

  • [x] row flag is what is saved to LSD, rowAlt is not

Row Command in Menu Scene

  • [x] Row command in menu toggles both flags and uses only row to decide the toggle. I.E if row == front then row = rowAlt = back
  • [x] Menu does not allow all party members in the back row

Battle Adjustments

  • [ ] Above adjustments to evasion and damage only use the row flag.

Row Command in Battle

  • [ ] Row command is hard coded to always be present, you can't disable row feature from 2k3 battle
  • [ ] RPG_Actor::UpdateBattle() is called to update animations and actor state.
  • [ ] Row command execution is processed: toggles rowAlt flag only.
  • [ ] Next frame: RPG_Actor::UpdateBattle() runs again and checks the 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;
}

Battle Start Adjustments

  • [x] When battle is started if no live actors are in the front, row, entire party is moved to front row.
  • [x] When actor sprite is "spawned" onto the battle scene rowAlt = row
  • [x] If 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:

  • Player in front row attacks Enemy: Normal hit rate
  • Player in back row attacks Enemy: Normal hit rate
  • Enemy attacks Player in front row: Normal hit rate
  • Enemy attacks Player in back row: Reduced hit rate

Back encounter condition:

  • Player in front row attacks Enemy: Reduced hit rate
  • Player in back row attacks Enemy: Reduced hit rate
  • Enemy attacks Player in front row: Reduced hit rate
  • Enemy attacks Player in back row: Normal hit rate

Surround encounter condition:

  • Player in front row attacks Enemy: Reduced hit rate
  • Player in back row attacks Enemy: Reduced hit rate
  • Enemy attacks Player in front row: Reduced hit rate
  • Enemy attacks Player in back row: Reduced hit rate

Pincer encounter condition:

  • Player in front row attacks Enemy: Normal hit rate
  • Player in back row attacks Enemy: Normal hit rate
  • Enemy attacks Player in front row: Normal hit rate
  • Enemy attacks Player in back row: Normal hit rate

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:

  • Are ally->ally (state inflicted) attacks considered normal attacks?
  • Is the row relevant in this case?

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..

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fmatthew5876 picture fmatthew5876  路  12Comments

carstene1ns picture carstene1ns  路  18Comments

LucasMW picture LucasMW  路  19Comments

Ghabry picture Ghabry  路  22Comments

BlisterB picture BlisterB  路  66Comments