Players are sometimes unable to fire guns (vehicle + AT guns)

Issue #313 resolved
Colin Basnett created an issue

The exact cause of this is unknown and difficult to replicate.

We think it has something to do with being killed while re-loading the gun. When you return to the gun, sometimes you are completely unable to fire it. Oddly enough, in the same round I was able to return to the gun that was previously "jammed" and magically it was working again. This leads me to think it may have something to do with the replication of the gun's reload status, but it's admittedly sort of a shot in the dark.

Comments (16)

  1. Andrew Theel
    • changed status to open

    This seems to be affecting all vehicles! I was unable to fire the JagdPanther after finished reloading. Still have no clue how to replicate this bug! However it is a blocker now!

  2. Andrew Theel

    I think this bug might have something to do with the new reload code. I think somehow my reload fails it "progress" or something and visually thinks I'm done reloading, but the other code says I'm not able to. So I can't fire, but I also can't reload as it's checking either the wrong variable or no longer checking.

  3. Colin Basnett reporter

    This has happened to us multiple times during testing. We should consider this a blocker bug for a 6.0 release.

  4. Matt Hands

    Added temp debug in commit 2d16aa7. Marked DEBUG in comments.

    Will log any serverside or clientside interruption to firing. Note server will sometimes log "AttemptFire returning false" when everything is fine & a reload is strating, due to fire key being held down for a split second after firing.

    Most usefully, whenever it gets jammed, type LogCannon in console and it will log all relevant variables & whether in state ViewTransition. For server, log in as admin and type "admin LogCannon". The problem is very likely a variable or state stuck clientside and if I know which one, it will be easy to work out why/where. Report the log and I'm sure I'll be able to fix it quickly. Cheers.

    I can't recreate this my end and I've fired 1000+ cannon shells in a dedicated server environment. I guess that's demonstrating that split second network delays or failure to transmit are much more likely to show effect in a real internet environment, rather than a dedicated server on a local machine (even though that is running separate server/client state and having to replicate everything, with a ping of about 30 typically for me).

    Note there is no new reload code/system. Lots of the vehicle code has changed, as has most of the game code, but nothing significant with reloads.

  5. Matt Hands

    Improved debug exec LogCannon() in commit 17b7b63.

    If you ever find a cannon will not fire or reload when there is no apparent reason, then use this exec, copy down the log results & post them here. The bug only happens occasionally and is hard to recreate, so if we get this info it will probably point to the cause straight away.

    The function logs all relevant clientside variables, calls a server function, which then writes back to the client with the corresponding server values. Everything is logged on your client, including the server values, so it's very convenient and no need to access the server's log. Cheers.

  6. Matt Hands

    Just encountered this for the 1st time ! Running a dedicated server on main PC, with batch file-driven client connection from same PC. Here's what was logged by exec LogCannon:

    ScriptLog: CLIENT: DH_JacksonCannonPawn  CannonReloadState = CR_ReadyToFire  bClientCanFireCannon = False  ProjectileClass = DH_Vehicles.DH_JacksonCannonShell
    ScriptLog: CLIENT: PrimaryAmmoCount() = 32  ViewTransition = False  DriverPositionIndex = 0  Controller = DHPlayer
    ScriptLog: SERVER: DH_JacksonCannonPawn  CannonReloadState = CR_ReadyToFire  bClientCanFireCannon = True  ProjectileClass = DH_Vehicles.DH_JacksonCannonShell
    ScriptLog: SERVER: PrimaryAmmoCount() = 32  ViewTransition = False  DriverPositionIndex = 0  Controller = DHPlayer
    

    Not what I expected. I thought the more likely culprit was the clientside setting for CannonReloadState - although I have spent ages trying to work out how that could happen & concluded that it can't ! But no, this culprit is the clientside setting for bClientCanFireCannon. And that's a replicated bool, with a very basic replication statement:

        reliable if (bNetDirty && Role == ROLE_Authority)
            bClientCanFireCannon;
    

    How that isn't reaching my client, I do not know ! The server has the correct value of true and I am sitting in the turret of a Jackson - but I'm not getting that replicated bool. There is nowhere in any RO or DH code where that can get set on the client, i.e. unwittingly overriding the correct value replicated from the server. It simply seems to be a replication screw up - the server thinks it has replicated the correct value to me, although it hasn't been received, but that means the server won't replicate again as it thinks the job has been done.

    Getting out of the vehicle and re-entering does nothing, as expected. That won't make the bool replicate. It isn't qualified with bNetOwner, so whether I'm in the cannon or not makes no difference (NB - it perhaps should be bNetOwner, for efficiency, but it isn't declared that way).

    But I have just connected as a 2nd player with my laptop. And also as expected, my 2nd player did receive the correct bClientCanFireCannon value of true and could fire the cannon. Once that had happened the 1st player was able to use the cannon normally - because firing changed bClientCanFireCannon to false on the server, then after the reload it was set back to true and the server updated all relevant clients by replicating the new true value. I am 100% certain that if I had moved out of net relevancy and the cannon actor was culled from my client, when I moved back into relevancy I would have received the correct value and been able to fire.

    Hmmmm .... let me look over where that leaves us.

  7. Matt Hands

    Can reproduce this regularly in the Jackson, but strangely I can't in the Sherman 75. In the Jackson, I press 1 to move into the driver's seat at almost the same time I click fire. It seems like a phantom shot is fired, so if I'm aiming at a clear target, nothing hits that, but I hear the shot. And when I go back to the cannon, there's no reload process, it won't fire and the server and client have different values of bClientCanFireCannon.

    When trying to reproduce it in the Sherman, I can't achieve the same, but several times in both vehicles I've had another weird bug where's no visible reload, but a server reload must be happening, because every few seconds a real, damaging shot is fired - but without me pressing fire, it's like the fire button is jammed down (it isn't) ! That bug disappears when I exit and re-enter the cannon, with a visible reload showing.

  8. Matt Hands

    Believe fixed in commit 9d675b7

    Removed client's checks on bClientCanFireCannon, instead relying on solely checking that CannonReloadState is CR_ReadyToFire. Made that change in 3 relevant functions. Appears to reliably solve the problem. CannonReloadState should be sound for checking reload status anyway, as only gets set at end of client's own series of reloading timer calls. And even if something goes wrong on the client, or someone hacks the clientside values, the server is the authoritative decider of whether a projectile gets fired. So the worst that could ever happen is the player seeing phantom firing effects, but no real projectile would be fired unless the server has the correct firing values.

    Added a temp debug exec function that allows you to recreate the bug: type CannonFireBug in the console while in a cannon that is loaded. That just sets the clientside value of bClientCanFireCannon to false. Before your cannon would be jammed in this condition, but now it should fire ok. If you watch the client's log, you should see a few temp debug lines where it logs that it is bypassing the fact that bClientCanFireCannon is false, which would normally stop you from firing. I'll remove all the debug once this has been verified. But I'm confident.

  9. Matt Hands

    Properly fixed in 37b9ffd, so no need for hack fix of removing the original clientside checks on bClientCanFireCannon. Reinstated the original bClientCanFireCannon checks & temp debug stuff.

    Bug was caused if player exited position immediately after firing. Could easily be recreated by pressing 1 to switch to driver at virtually same time as clicking fire. Usually get it in 3 or 4 attempts.

    On a net client this resulted in phantom firing effects in OwnerEffects() - flash, bang, smoke - but no shot actually being fired. I presume by the time the fire call had reached the server, there was no player & so no shot fired - native stuff.

    And the cause was the owning client setting bClientCanFireCannon to false in OwnerEffects(), in anticipation of server doing that. That was understandable, because OwnerEffects() is where the owning client starts its own clientside reload process (just for sounds & HUD reload indicator). So owning client has to set CannonReloadState to empty to being the reload, & server is going to be doing exactly the same its end, so it made sense to set bClientCanFireCannon =false. But in the case of a 'phantom' shot like this, the client ended up going through its reload but the server never initiated the fire/reload process, so the server stayed with bClientCanFireCannon=true, was never aware that the client had changed its value to false, & so never saw the need to replicate bClientCanFireCannon to the client. And the client ends up thinking a shot has been fired, thinking a reload has happened & patiently waiting - for ever- for the server to send it the new bClientCanFireCannon=true value.

    So bClientCanFireCannon =false in OwnerEffects() is the single cause of this specific bug and, although it seemed reasonable to do, it's actually completely unnecessary. That's because the client has already set CannonReloadState to empty, & all clientside firing checks are against both reload state AND bClientCanFireCannon. So no chance of a client still being able to fire immediately after firing, while it's waiting for the server to replicate bClientCanFireCannon =false. Re-firing is prevented immediately on the client by the client.

    So the very simple fix is just to remove the bClientCanFireCannon=false line in OwnerEffects().

    Note that when the client 'phantom fires' like this, it does end up with reload state empty but still bClientCanFireCannon, which is an obvious contradiction. But it's not a problem because as soon as the player (or any player) re-enters the cannon, the server calls replicated function ClientSetReloadState() on that client and passes the correct reload state 'ready to fire'.

    Also note this is a completely separate issue to cannon fire bugs caused by the more general problems of missing actor references (generally replication timing issues) that is discussed and - fingers crossed - fixed in https://bitbucket.org/darklightgames/darkesthour/issues/450/players-are-sometimes-unable-to-fire-or reload AT guns.

  10. Log in to comment