Decal issue

Discussions about Coding and Scripting
Post Reply
gopostal

Decal issue

Post by gopostal »

OK I'm kinda stuck on this. I made a custom redeemer with a custom blast decal. It works fine offline but it makes multiple decal copies online. I don't see in the code where it would make multiple copies:

Code: Select all

simulated function HitWall (vector HitNormal, actor Wall)
{
    if ( Role == ROLE_Authority )
    {
        if ( (Mover(Wall) != None) && Mover(Wall).bDamageTriggered )
            Wall.TakeDamage( Damage, instigator, Location, MomentumTransfer * Normal(Velocity), '');

        MakeNoise(1.0);
    }
    Explode(Location + ExploWallOut * HitNormal, HitNormal);
    if ( (ExplosionDecal != None) && (Level.NetMode != NM_DedicatedServer) )
        Spawn(ExplosionDecal,self,,Location, rotator(HitNormal));
}
I wonder if it is the multiple shockwaves creating the issue?
User avatar
Saya-chan
Adept
Posts: 446
Joined: Mon Jun 02, 2008 10:46 am
Personal rank: Former UT99 modder
Location: Vigo, Galicia
Contact:

Re: Decal issue

Post by Saya-chan »

Hm. Could you also post the Explode function?
Image
  ~♥~ Bless the Cute Emperor ~♥~
User avatar
Feralidragon
Godlike
Posts: 5493
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Decal issue

Post by Feralidragon »

Having quite the same issue with 2 of my projectiles (although they only spawn 1 or 2 extra decals, but only in in certain angles and orientations).

I think the issue is simple: for some reason, the projectile on the client hits the wall way before the server side version of it, and since it doesn't destroy itself (since the destroy() part is done server side, then replicated to the clients), it keeps "hitting the wall", and therefore creating multiple decals, since everytime it hits the wall, a new decal is created (client-side). but this is my explanation about the issue, don't know if it's the right one (just a theory though).

I still don't know how exactly to solve this (replication is a bitch), but I have been thinking in a way to to avoid that with a simple "hack" of sort to speak: basically, the projectile in its entire life should be able to spawn only 1 decal, therefore perhaps if we create a simple boolean variable, with no replication statements at all, that turns true when the first decal is spawned, then that could solve the problem.

That way the decal would only spawn if that bool was false, and would turn it true once the first decal was spawned.
Basically this is the same "hack" used in HurtRadius, which has a bool variable that turns true at the beggining of the function to avoid reentrance on that function.

But I still didn't test this "fix" though, so I am not sure if it works, just an idea so far to solve this kind of replication issues (an ugly one, but I can't think on a direct aproach :\ ).
gopostal

Re: Decal issue

Post by gopostal »

I appreciate the fast replies!

OK, I tested adding a boolean and it did not stop it. For now I just added rand code:

Code: Select all

if ( (ExplosionDecal != None) && (Level.NetMode != NM_DedicatedServer) )
    
    	if ( FRand() < 0.80)
		Spawn(ExplosionDecal,self,,Location, rotator(HitNormal));
	else 
                Spawn(ExplosionDecalA,self,,Location, rotator(HitNormal));
It's not the best solution but it will help enough to make the problem a very odd instance. Still I'd like to sort this so if you guys think of something let me know.
User avatar
Feralidragon
Godlike
Posts: 5493
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Decal issue

Post by Feralidragon »

I see...

Well, I tried another thing that actually worked on my projectiles, and it's quite similar to the bool variable.

Code: Select all

if ( (ExplosionDecal != None) && (Level.NetMode != NM_DedicatedServer) )
{
	Spawn(ExplosionDecal,self,,Location, rotator(HitNormal));
		
	ExplosionDecal = None;
}
But it generates another problem: sometimes it won't even spawn the first one :omfg:
Still, I will also keep trying to discover how to fix this properlly.
User avatar
Feralidragon
Godlike
Posts: 5493
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Decal issue

Post by Feralidragon »

Discovered one thing: It seems that the problem is general, as Epic couldn't solve this bug either.
It happens when we have a normal projectile with ROLE_SimulatedProxy and bNetTemporary=False. In bNetTemporary=True projectiles, this doesn't happen, everything works perfectly fine.

I tested the standard shockrifle online, since it has a bNetTemporary=False projectile: ShockProj. In certain times it also leaves multiple decals instead of just one, so it's not your fault, nor my fault that our projectiles leave multiple decals, since you have most likelly bNetTemporary=False.

Either ways, this means we have to create a solution ourselves. For now I am using that one shown above, although it has a little problem, but it's a problem I can live with for now. I have another solution as well that might work flawlessly, but it includes spawning another projectile and I personally don't want that kind of "fix".

If I find a definitive solution, I will post it here, or if anyone knows or finds the solution for this problem, please post as well, as we all would like to know to solve this general issue.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Decal issue

Post by Rakiayn »

is it a bad thing to just set bnettemporarely to true?
User avatar
Feralidragon
Godlike
Posts: 5493
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Decal issue

Post by Feralidragon »

Rakiayn wrote:is it a bad thing to just set bnettemporarely to true?
Well, in my case at least it is.
Basically, if you want a projectile to follow someone or something (update constantly it's velocity and rotation), or if you want it to explode when you shoot at it (combo), or do other stuff which need updates over the time, your projectile must be bNetTemporary=False.

In case you set bNetTemporary=True in one of those kind of projectiles, it won't follow client-side (1st case), it won't blow up when you shoot at it also client-side (2nd case) or do anything else client-side that requires updates on the projectile that must be replicated to the client.

Therefore, bNetTemporary=True is only used on projectiles that guide themselves by the Physics given to them (straight lines in case of PHYS_Projectile or affected by gravity in case of PHYS_Falling), and the engine events (ProcessTouch, HitWall, etc), in another words, most of the projectiles in UT use bNetTemporary=True (since most of them don't have any extra stuff occuring in them).

In resume, when you set a projectile bNetTemporary=True, it means that once spawned, only the initial settings get replicated, and on the rest of the lifespan of the projectile, only engine events will be called and replicated to the client, nothing more, and in case of bNetTemporary=False, anything "extra" that happens to the projectile sever-side, can be replicated to the client.
gopostal

Re: Decal issue

Post by gopostal »

Awesome explanation :thuup:
User avatar
TheDane
Masterful
Posts: 660
Joined: Tue Feb 12, 2008 2:47 pm
Personal rank: Happy fool :-)

Re: Decal issue

Post by TheDane »

my expirience tells me that projectiles are calculated in the world, both the client and server gets the point of origin and then the direction + velocity ... then it's easy to calculate the impact as both the server and client have the same map running and therefore the calculation should produce the same impact. I think it's a matter of replicating the custom vars to the client?

take the enforcer as example:

Code: Select all

replication
{
	reliable if ( bNetOwner && (Role == ROLE_Authority) )
		SlaveEnforcer, bIsSlave, bBringingUp;
}
if you remove that replication from the script it will work offline but not online.
Retired.
User avatar
Feralidragon
Godlike
Posts: 5493
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Decal issue

Post by Feralidragon »

Indeed, however that won't work entirelly if bNetTemporary is enabled, so it's not really that linear.

bNetTemporary basically defines that all the changes on variables and function calls occur successfully only at the moment the actor is spawned, and in the rest of its lifetime, only engine events are called both in the server and the client (otherwise it would hit a player in a server and could not hit in the client, and these events must be called on any actor on both ends).

Basically, even with those replication statements (and I did that experience myself), and and Timer() event being called on a projectile, it wouldn't "seek" as it should, but only client-side of course (everything works on the server if the actor let's so). It would go on a straight line like any other projectile in the clients end, because the server wasn't updating the new rotation/velocity of the projectile on the clients, simply because bNetTemporary was True which basically means: "spawn, change stuff only at the beggining if needed (event) and then fully simulate until further notice, however run any event (Tick, HitWall, ProcessTouch, PostBeginPlay, etc...)".
To make it work, bNetTemporary had to be False, which meant that any variable changes (with the proper replication statements) and any function calls will be replicated to the clients as necessary, and therefore the client version of the projectile can receive such updates.

Another example of this is the ShockProj: no matter how many replication statements you place there, if it's bNetTemporary=True, the combo won't happen client-side, although it happens on the server.

EDIT: Btw, do not forget that most of the variables implemented in the Actor class have replication statements as well: Location, Rotation, Texture, Mesh, MultiSkins, AmbientSound, etc... However, in these cases they might not reach the client as they should, due to that small setting.
User avatar
>@tack!<
Adept
Posts: 338
Joined: Sat Apr 17, 2010 4:51 pm
Personal rank: lol?

Re: Decal issue

Post by >@tack!< »

bah this is being a bitch to me too.. spawning multiple FX
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Decal issue

Post by JackGriffin »

Use Ferali's code:

Code: Select all

if ( (ExplosionDecal != None) && (Level.NetMode != NM_DedicatedServer) )
{
   Spawn(ExplosionDecal,self,,Location, rotator(HitNormal));
      
   ExplosionDecal = None;
}
I did it and it works well. You get sometimes where the decal won't spawn but at least it's not ever more than one.
So long, and thanks for all the fish
User avatar
>@tack!<
Adept
Posts: 338
Joined: Sat Apr 17, 2010 4:51 pm
Personal rank: lol?

Re: Decal issue

Post by >@tack!< »

isnt it possible to spawn something else which is bNetTemporary and that will spawn the decal? :p
Post Reply