klei1984 / max

M.A.X. Port
https://klei1984.github.io/max/
MIT License
50 stars 4 forks source link

[Bug] Units fire too fast due to too fast game processing pace #31

Closed lockheed closed 5 months ago

lockheed commented 5 months ago

Operating System

Windows

Source of bug?

M.A.X. Port Version

v0.6.1

M.A.X. and DOS or DOSBox Versions

1.04

What is the issue you encountered?

The game works so fast that when a vehicle reacts to/attacks an enemy, it fires twice instead of once even if the first projectile destroys the enemy. This causes one-shot kills cost two shots (the second one wasted) and additional lost move.

Anything to add?

Apart from that - I have discovered your port just today. I have been playing this game on-off since 1997/98 and yours is the first thing that made any (and huge) improvement to MAX single player gameplay: works very fast in late turns, no more random crashing and wide screen!!! I am so blown away and thankful for it!!!

klei1984 commented 5 months ago

Hello, could you please attach your saved game file? E.g. auto save file is SAVE10.DTA.

lockheed commented 5 months ago

It happens with every game. You can start any custom game, get Assault Gun as a starting vehicle and when an enemy scout approaches in the first rounds, AG will shoot twice at it at once, even though the first hit will destroy it. The bug affects units that shoot fast projectiles (Assault Guns and Tanks (including Alien), Fighters, Artillery, etc) but not for units shooting missiles (Missile Launcher/Crawler, Rocket Launcher, Corvette, etc). Missile-firing units pause until the projectile reaches target which I think is the reason they are not affected.

klei1984 commented 5 months ago

Will look into it, but with stock assault gun and scout the two shots are actually needed.

Standard assault gun has 18 attack power. Standard scout has 16 hit points and 4 armor. 1 shot from assault gun means 18 attack power - 4 armor = 14 damage. 14 damage from 16 hit points = scout has 2 hit points remaining, hence second shot required.

Standard tanks have 16 attack power, cannot destroy standard scouts either in one shot. Standard artillery turrets have 18 attack power.

Alien units have 20+ attack power, they should be able to one shot standard scouts... will make a test game setup.

klei1984 commented 5 months ago

SAVE10.ZIP

Made a hot seat test setup. Tested alien tank and alien assault gun versus stock scouts.

Commanding alien unit to attack scout killed scout in one shot. Commanding scout to move into attack/scan range of alien unit resulted in reaction fire from alien unit killing scout in single shot.

Could you also try the given saved game just to be sure that hot seat and whatever else works the same way at your end?

lockheed commented 5 months ago

I will make a save game. I notice it primarily with Alien vehicles, but then I am pretty sure I saw it also affecting some regular ones. It is most obvious when an alien attack plane (upgraded to, say, 4 shots) is approached by multiple enemies. It has more than enough power to one-shot each of them, but will only kill 2 as a result. I will try to add a save game.

lockheed commented 5 months ago

Here's a savegame: https://file.io/KkVsW1hGnenx

Steps to replicate the issue: Take the 9-shooter Alien Plane and station it around 023-068. In a turn or two, a bunch of fighters will approach. AP can one-shot each of them, but because it fires so fast, it will waste 2 shots per kill.

klei1984 commented 5 months ago

Thanks! This will help me a great deal.

klei1984 commented 5 months ago

I have a good and a bad news. The good: with your help we identified an aspect of the fire order processing logic that is not determined based on events nor on time or frame rate. The game uses holy magic numbers to determine how many order processing cycles it should wait before it would progress the game logic state machine from bullet/missile is flying to the next order state which is enemy was hit so if not destroyed, lets fire again. The bad: this is not a bug, it is just bad design from the original authors and as such I need to come up with a better design for a feature that is already overly complicated to comprehend without documentation. And no, we have no documentation 😭

So the issue will be solved sooner or later, but it could take from one day to one month... we shall see.

lockheed commented 5 months ago

Ah, as an MAX fan for over quarter of a century I am well aware of the curse that has befallen MAX after release - the lost source code, no documentation, main dev killing his daughter and rotting in prison. I am impressed you have been able to do so much already, and curious how have you been achieving it. Is it by decompiling and reverse engineering, or running the original MAX code in some kind of "VM" and manipulating all the input? Also, how do you know what the game is actually doing under the hood? Is it not a blackbox to you?

Anyway, when I run MAX in dosbox, it doesn't have that problem - probably because it is so slow in comparison. Perhaps slowing things down during shooting could be a temporary solution?

klei1984 commented 5 months ago

I reengineered the game. Took 4 years effort. You can find a blog post about the workflow including a 1 hour video here: https://klei1984.github.io/max/2022/04/29/Work-work.html

The entire source code is here in this GitHub repository. Its 4 MiB of C/C++ code. I also restored many debug features that Interplay had in the game in demo and internal test builds while they removed them from the retail versions. The MS-DOS architecture of the game had to be adapted to run on modern systems so there is no way to build the game for MS-DOS anymore.

lockheed commented 5 months ago

Well, all I can say I'm beyond impressed. I did not think it was possible. BTW, what country are you based in?

klei1984 commented 5 months ago

Hungary.

klei1984 commented 5 months ago

Eventually while I was trying to determine the accurate FPS independent timings to be used for the various attack types, I realized in one of the videos I recorded to compare original dosmax and portmax behaviors that portmax started the next attack without waiting out the attacked unit's status to change from exploding to whatever else. This directed me to a different root cause analysis. Eventually after a couple of hours of code digging I found the real root cause behind the issue.

I incorrectly placed an AND statement instead of an OR statement into a single conditional branch operation... a single byte error really 😞

Any ways. Problem is solved now. Attacks immediately returned to good old dosmax speed at 24 FPS fastest tick rate. I will commit the reimplementation issue correction soon.

lockheed commented 5 months ago

Fantastic news! When do you predict the next version will be released?

klei1984 commented 5 months ago

Its not any time soon I am afraid :( I have to make a working and compliant deb installer, then still have to fix a dozen reported issues, and I need to finish the multi byte UTF8 encoding related remaining issues.

If we cannot make the GitHub Actions builds run on linux, you could try out building the game from source code. https://klei1984.github.io/max/build/

The fix is already up on the master git branch.