Game Development Community

ParticleEmitterNode not ghosting to newly joined client.

by Andrew Mac · in Torque 3D Professional · 11/25/2013 (8:49 pm) · 8 replies

I was messing around with ParticleEmitterNode's and I made one and mounted it to the player in the preparePlayer() function. It works fine on host for all players that join. However, the other clients can't see the particle emitters of anyone who joined before them. If a player dies and respawns it shows up fine, and it shows up on the player the client is controlling, but not the players that were already spawned in the world.

I've tried setScopeAlways() with no luck. Is there something simple I'm missing or do I need to hardcode all the emitters I want to use into the Player class (or a derived one) to have it persist across all the clients? Or alternatively script a function to manually scope the emitters to newly joined clients?

#1
11/27/2013 (7:10 am)
I can't answer you right away, but this reminds me of something I have experienced before..

Is this running over the internet or on a local connection?

And are you saying that it works on all players connected after and not the ones connected before the emitting player?
#2
11/27/2013 (7:23 am)
If you take a fresh copy of MIT 3.0 full template and go into the onClientEnterGame function of GameCore and add the following to the end of it:

datablock ParticleEmitterNodeData( SimpleEmitterNodeData )
{
   timeMultiple = 1.0;
};

%emitter = new ParticleEmitterNode()
{
   datablock = SimpleEmitterNodeData;
   active = true;
   emitter = SmokeEmitter;
   velocity = 3.5;
};

%client.player.mountObject(%emitter, 0);
%emitter.setActive(true); // not sure if this is required.

Host a new game, switch to third person and you'll see smoke coming out of the players hand. Now, fire up another copy, and join the existing game. In client #2 you will see smoke on yourself, but not on the player who was already spawned. Check net stats, you should see 1 more ghosted object on the original client than on the newly connected one (the emitter I assume). If the first client kills itself and respawns though, both clients will see it. So it's not ghosting the existing particle emitter, only new ones.

Now, if you try the same thing with MIT 3.5 it works fine. So, I took 3.5, added IPS, and migrated my engine changes over (manually - line by line). Unfortunately the problem has resurfaced. Since I've made no changes to any particle systems or the scoping code I don't suspect my changes caused it to resurface. IPS alters the files in the T3D/fx folder including particleEmitterNode.cpp so it would seem obvious that's where the problem is.. EXCEPT.. there's been no significant revisions to that file between 3.0 and 3.5 that seem like it would correct this issue. Or any of the other files that IPS alters. If it really was a bug in 3.0 that was fixed in 3.5 I can't find where the fix was made. Either my testing methods are tainted or I'm overlooking something.
#3
11/27/2013 (7:27 am)
I will examine this and get back to you!
#4
11/27/2013 (12:34 pm)
Okay I can't find any commit that may have fixed the issue either, so it's very confusing.
It may be a script change, it may be something completely unrelated. How did you merge the IPS with the source? Did you just copy-paste or did you merge the files that needed merging?
#5
11/27/2013 (12:40 pm)
I manually merged everything outside of the FX folder ( player.cpp, shapebase.cpp, etc ) because I had my own changes to merge as well, so those were handled carefully. Then I just pasted the contents of the IPS t3d/fx folder from split source and overwrote the contents of 3.5's T3D/FX folder. That's why I figured I'd find the fix in the revision history for one of the files that I overwrote. Instead I found barely any revisions over the last year, and the ones that are there are minor things that wouldn't impact scoping.

When I get time later tonight I plan on stepping through the scope function on a secondary client and figuring out what condition isn't being met for the emitter to not be scoped.
#6
11/27/2013 (3:01 pm)
I've determined the culprit to be ScopeAlways. Removing it from the ParticleEmitterNode netFlags:

ParticleEmitterNode::ParticleEmitterNode()
{
   mNetFlags.set(ScopeAlways | Ghostable);
   mTypeMask |= EnvironmentObjectType;
...

Changing it to: mNetFlags.set(Ghostable); fixes the problem. I noticed the cameraScopeQuery functions were all ignoring the emitter because it was scopeAlways. The real question now is why is the client not getting the list of scopeAlways objects? edit: or why is not getting the emitter as part of that list.
#7
11/27/2013 (3:12 pm)
Yes you are right, I wonder why I put that there. Probably part of a debugging session once, anyways I agree I'm clueless as to why the scopeAlways objects are not scoped to new clients.

I hope someone can shed some light on this!
#8
11/27/2013 (3:17 pm)
Oh, it was you! Haha, okay great. For a minute there I thought ScopeAlways was set in the emitter nodes on the main source but I just checked and it isn't. That's great, I can consider this a proper solution and not just a work around.