Invisible projectiles fix

  • Hey - turns out IRC is out and something a little more modern has taken it's place... A little thing called Discord!

    Join our community @ https://discord.gg/JuaSzXBZrk for a pick-up game, or just to rekindle with fellow community members.

Polle

New Member
Oct 8, 2001
280
0
I think most recognize the following scenario:

- You shoot 6 clustered rockets and see them explode on someone kneecaps yet he lives with no apparent damage.
- You run behind a teammate and he takes a rocket to the face but mysteriously he lives. 1 second later you are killed by a now invisible rocket.

UT has two kinds of projectiles:

The ones with bNetTemporary=False
- Bio
- Shock balls
- Flak balls

The above projectiles have the following properties:
- They are never invisible unless you have packet loss
- They will never become "ghost" projectiles unless you have packet loss
- When you see them explode you can be certain they exploded at that location on the server

The other group has bNetTemporary=True
- Plasma spheres
- Rippers
- Flak shrapnel
- Rockets and grenades

UT is more lazy with these projectiles. They use tearoff replication meaning that a harmless visual version is sent to the client while a deadly invisible version exists on the server. Even with 0% pl and 0 ms ping the server and client are rarely completely synchronous due to the servers limited tickrate. This means the following happen frequently even with a flawless connection:
- Invisible but lethal projectiles.
- Visible but harmless projectiles.
- You see projectiles detonate on a player but they dont draw blood and he takes no damage.

This is all by design. UT is optimized aggressively to use as little bandwidth as possible, and considering the number of players that used 56k at UTs release it does make some sense. Today tearoff replication is pointless however.

So I wrote a small mutator that changes all projectiles to bNetTemporary=false. The mutator is called RocketsFix.RocketsFixMut and has the following options:

- bDebug; (clientside option)
- bFixRockets; (serverside option)
- bFixFlak; (serverside option)
- bFixPulse; (serverside option)
- bFixRipper; (serverside option)

Which should be self explanatory except bDebug. This variable displays a shockimpact whenever a client detects a collision even if the server does not. So if you shoot a projectile against an opponent and you see a shockwave but the projectile continues then this is an example of where the original tearoff projectile would have turned invisible while still being deadly. The bDebug var only applies to secondary ripper, rockets and grenades.

Note: If bFixFlak or bFixRockets are true the flak cannon and/or the rocket launcher will be replaced with a similar version (UT_eightball_fix and UT_FlakCannon_fix). This means that binds using getweapon will no longer work but switchweapon will. TIW weapons cause the same problem.

Edit: Removed attachment. See updated version below
 
Last edited:
That explains why I can shoot 4 rocks at someone and they just walk through them then. It's a great idea and would make sense to test and use it, but I wonder if it will ever happen.

Match with Hak tonight so will see a lot of people walking through rocks hahaha.
 
Few minor bugs, but overall a good idea.

- Much better than the mutator that makes absolutely everything bRelevant=True ;)

Hop on to IRC at some point mate and give me a shout.
 
Few minor bugs, but overall a good idea.

I only tested vs Alarik & co on a local server with ping < 10 ms. I am certain the method is sound though, even if the implementation has bugs.

- Much better than the mutator that makes absolutely everything bRelevant=True

This wouldnt solve invis projectiles though because unlike pawns, projectiles dont become invis because of a failed relevancy check. Server simply makes no attempt to update client with info about the fate of "tearoff" projectlies.

The fix cant be made just by tweaking variables. The decision to spawn the explosion has to be moved from client to server and this is hardcoded in the projectile scripts.
 
Okay first update.

- Fixed: bdebug is now false by default.
- Thanks to Timo for letting me cut'n'paste code to ensure that pickups dont change rotation.

Edit: Removed attachment. Updated version below
 
Last edited:
On the clientside: Does it only work for your bullets, or for all the bullets you see in your screen... especially with the bDebug i think it can be annoying when 6v6 spamming on bridge final and you see 6 shockbeams in your screen ^^
but i guess this option can be unchecked by the client?
besides that... VERY GOOD JOB imho... It's nice to see people still working to make a '99 game going smoother and smoother :)
 
On the clientside: Does it only work for your bullets, or for all the bullets you see in your screen... especially with the bDebug i think it can be annoying when 6v6 spamming on bridge final and you see 6 shockbeams in your screen ^^
but i guess this option can be unchecked by the client?
besides that... VERY GOOD JOB imho... It's nice to see people still working to make a '99 game going smoother and smoother

If you have bDebug=false you will not see any shock effects from the fixed projectiles. The first package in this thread had bDebug=true by default which was a bug. I only left the bDebug in the package in case anyone was interested in seeing how easy it is to get the invisible rocket effect.

If you downloaded the first package you may have to change it manually by "set rocketsfix.rocketsfixmut bdebug false" or by modifying your ini file.
 
One more update:

Added fix for "switchtobestweapon". It still wont work if you already have 49 or 50 weapons in your weapon priority list.

The code to fix this was taken from LeagueAS (written by Psy)
 

Attachments

  • rocketsfix.zip
    33.4 KB · Views: 78
i put the rocketfix.u in my /system and dog custom says package mismatch
nm i guess dog has the older version... dodododood



so my switchtobestweapon for rockets doesnt work,,,,,,

[Engine.PlayerPawn]
WeaponPriority[0]=Translocator
WeaponPriority[1]=ChainSaw
WeaponPriority[2]=ImpactHammer
WeaponPriority[3]=enforcer
WeaponPriority[4]=doubleenforcer
WeaponPriority[5]=ShockRifle
WeaponPriority[6]=ut_biorifle
WeaponPriority[7]=SniperRifle
WeaponPriority[8]=ripper
WeaponPriority[9]=Minigun2TIW
WeaponPriority[10]=minigun2
WeaponPriority[11]=pulsegunTIW
WeaponPriority[12]=PulseGun
WeaponPriority[13]=UT_FlakCannon
WeaponPriority[14]=UT_Eightball
WeaponPriority[15]=WarheadLauncher
WeaponPriority[16]=None
WeaponPriority[17]=None
WeaponPriority[18]=None
WeaponPriority[19]=None

hoi sucks
 
Last edited:
You can replace it manually with this (which is what the updated version would do automatically):

[Engine.PlayerPawn]
WeaponPriority[0]=Translocator
WeaponPriority[1]=ChainSaw
WeaponPriority[2]=ImpactHammer
WeaponPriority[3]=enforcer
WeaponPriority[4]=doubleenforcer
WeaponPriority[5]=ShockRifle
WeaponPriority[6]=ut_biorifle
WeaponPriority[7]=SniperRifle
WeaponPriority[8]=ripper
WeaponPriority[9]=Minigun2TIW
WeaponPriority[10]=minigun2
WeaponPriority[11]=pulsegunTIW
WeaponPriority[12]=PulseGun
WeaponPriority[13]=UT_FlakCannon
WeaponPriority[14]=UT_FlakCannon_fix
WeaponPriority[15]=UT_Eightball
WeaponPriority[16]=UT_Eightball_fix
WeaponPriority[17]=WarheadLauncher
WeaponPriority[18]=None
WeaponPriority[19]=None
 
I'd swear I got killed by an invisible flakball today, I didnt check if I had packetloss though :s
 
I've only had the briefest look at the code but I'm wondering if it's possible to set bNetTemporary=False via a mutator without the need to subclass every projectile?

Just change the default properties so that every rocket that spawns will have it set?
 
I've only had the briefest look at the code but I'm wondering if it's possible to set bNetTemporary=False via a mutator without the need to subclass every projectile?

Just change the default properties so that every rocket that spawns will have it set?

The original RocketMk2:
Code:
local UT_SpriteBallExplosion s;

s = spawn(class'UT_SpriteBallExplosion',,,HitLocation + HitNormal*16);	
s.RemoteRole = ROLE_None;

BlowUp(HitLocation);

Destroy();

The code above is run asynchronously on server and client when they independently detect a hit. A visual explosion is spawned on both client and server, but the server explosion is just a waste of cpucycles since setting its remoterole to none means it isnt sent to any client.

The changed RocketMk2_fix
Code:
if (Role==ROLE_Authority) {
  s = spawn(class'UT_SpriteBallExplosion',,,HitLocation + HitNormal*16);
// s.RemoteRole = ROLE_None;

  BlowUp(HitLocation);
  Destroy();
}
Now the explosion is only spawned on server but the remoterole isnt set to none so it is transmitted to client. You see the rocket explosion based on info sent by the server and not by the client guessing.

If you only changed bNetTemporary the following would happen:
- Rocket misses on client, hits on server: The rocket would disappear and cause damage but there would be no visual explosion
- Rocket hits on client, misses on server: you would see an explosion, but the rocket would fly past the victim and do no damage. This could occur several times if it the rocket has additional near misses.
- Even when you shoot rockets at a hard surface you often would not see an explosion.
- It WOULD fix invisible rockets caused by near misses. The rocket exists only on client as long as it is kept alive on server. The client still calls Destroy() but this call fails on client when bNetTemporary=false.

Doesn't help that the updates aren't version controlled

Polle!

Sorry! :sofa:

I'd swear I got killed by an invisible flakball today, I didnt check if I had packetloss though :s

Maybe they flakstabbed you ;)

Anyway flakballs are unchanged by the mutator since they are bNetTemporary=false from the start. The only invisible projectile problem that gets fixed is the one caused by near misses.
 
Seemed to work pretty well this afternoon for me, granted I didn't play UT for over a month before that and didn't remember what it was like without it :lol: