Jump to content

Need Help on Particles


Allan
 Share

Recommended Posts

I did this to the UpdateColor function

UpdateColor()
	{

		// warn("UpdateColor");
		let cmpFoundationOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
		if (cmpFoundationOwnership)
			{
				cmpFoundationOwnership.SetOwner(cmpFoundationOwnership.GetOwner());
			}
   		 warn("Owner : " + cmpFoundationOwnership.GetOwner())
		let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
		if (!cmpVisual)
			return;

		const color = QueryOwnerInterface(this.entity, IID_Player).GetColor();
		cmpVisual.SetVariable("colorr", color.r);
		cmpVisual.SetVariable("colorg", color.g);
		cmpVisual.SetVariable("colorb", color.b);
		// warn("red : "+color.r);
		// warn("green : "+color.g);
		// warn("blue : "+color.b);
	}

I try to SetOwner at this moment but I think i'm doing it bad. I saw this function comes from a .cpp compoment and is quite simple. But how can I SetOwner the final building AND the foundation AND the preview ? :confused:

I'm testing many things but I don't understand why when I print the owner of my 2 civil_centre at the beginning of the game I have this

image.png.c2ce7233c8e21b7d21fe5608d0d8f4e8.png

It seems like the owner is changing 3 times before getting the right owner, maybe that is the problem :search:

Moreover, I'm not the best programmer in the team, that's why it's harder for me to understand these things, sorry for being a noob :sorry:

(Steph is not available)

 

Link to comment
Share on other sites

It's okay. Perserverance is all you need :)

Regarding your interrogation I think by default everything is INVALID_PLAYER = -1

You might also print this.entity so you know which is which. Ideally in one statement


warn("entity: " + this.entity + " Owner: " + cmpFoundationOwnership.GetOwner());

Or use string interpolation

warn(`entity: ${this.entity} Owner: ${cmpFoundationOwnership.GetOwner()}`);

 

Maybe we forgot the edge case of QueryOwnerInterface not having an actual player :)

 

 

Link to comment
Share on other sites

Posted (edited)

I think I found something but I don't know how to use the UpdateColor function in another file. I tried this : 

let cmpParticlePlayerColor = Engine.RegisterInterface("ParticlePlayerColor");
		if (cmpParticlePlayerColor)
			{
				cmpParticlePlayerColor.UpdateColor();
			}

And this

let cmpParticlePlayerColor = Engine.QueryInterface(this.entity, IID_ParticlePlayerColor);
		if (cmpParticlePlayerColor)
			{
				cmpParticlePlayerColor.UpdateColor();
			}

I think I understand why the second one doesn't work (wrong interface) but why the first one ? 

 

I'm trying this because i saw that the UpdateColor function is called before the owner is set, and I think that's the problem.

Edited by Allan
Link to comment
Share on other sites

Weird because the second one is correct :)

The first one registers a new interface for the engine. So it should never be called outside of the first initialisation of the component in the js file (Although you could create runtime components for nefarious purposes, I would advise against it)

If the first one doesn't work, it means that whatever is calling that code doesn't have that component attached, which could mean the template is invalid.

Link to comment
Share on other sites

2 hours ago, Allan said:

Ok, I've got these errors with the second one :

image.png.e5aed8571b7a5f665a89516f83c46604.png

So yes, itu says that is null, so how can I call my UpdateColor function if this is null ?

The error means it cannot find the owner, (probably cause it doesn't have one) It's this code that fails:

const color = QueryOwnerInterface(this.entity, IID_Player).GetColor();
cmpVisual.SetVariable("colorr", color.r);
cmpVisual.SetVariable("colorg", color.g);
cmpVisual.SetVariable("colorb", color.b);

You can replace it with

const cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
if (cmpPlayer) {
	const color = cmpPlayer.GetColor();
	cmpVisual.SetVariable("colorr", color.r);
	cmpVisual.SetVariable("colorg", color.g);
	cmpVisual.SetVariable("colorb", color.b);
}

but then since it cannot find the player it will not set the color

Link to comment
Share on other sites

After testing many things I think that it's true :down:

18 hours ago, Stan` said:

Maybe we forgot the edge case of QueryOwnerInterface not having an actual player :)

But how this works for the civili-centre (building placed at the beginning of the game) and not for other buildings being constructed during the game ?

 

And if I can't pick my player from here, how can I do ? :search:

Link to comment
Share on other sites

Posted (edited)

Ok I think I found something interesting. I found this message in Player.js :

Player.prototype.OnGlobalOwnershipChanged = function(msg)
{
	if (msg.from != this.playerID && msg.to != this.playerID)
		return;

	let cmpCost = Engine.QueryInterface(msg.entity, IID_Cost);

	if (msg.from == this.playerID)
	{
		if (cmpCost)
			this.popUsed -= cmpCost.GetPopCost();

		let panelIndex = this.panelEntities.indexOf(msg.entity);
		if (panelIndex >= 0)
			this.panelEntities.splice(panelIndex, 1);

		let barterIndex = this.barterEntities.indexOf(msg.entity);
		if (barterIndex >= 0)
			this.barterEntities.splice(barterIndex, 1);
	}
	if (msg.to == this.playerID)
	{
		if (cmpCost)
			this.popUsed += cmpCost.GetPopCost();

		let cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity);
		if (!cmpIdentity)
			return;

		if (MatchesClassList(cmpIdentity.GetClassesList(), panelEntityClasses))
			this.panelEntities.push(msg.entity);

		if (cmpIdentity.HasClass("Barter") && !Engine.QueryInterface(msg.entity, IID_Foundation))
			this.barterEntities.push(msg.entity);
	}
};

It's always called when you build something so I decided to test this in ParticlePlayer.js

OnGlobalOwnershipChanged(msg)
	{
		if (msg.to == INVALID_PLAYER)
			return;

		this.UpdateColor();
	}

And it works !

The building switch from gaia to player color during the building or when it's constructed

BUT the UpdateColor function is being called 3-4 times every 5 seconds, which can be a problem ? I don't know

+ I understood how it works : 

Everytime I build something, the previous building is being Color updated. It means that if un build a large wall (with two towers), only the first tower will be color updated. To update the second one, I have to build another building :wallbash:

Edited by Allan
Link to comment
Share on other sites

Posted (edited)
9 minutes ago, Stan` said:

You can filter the entity // msg data is {"entity": ent, "from": playerId, "to": playerId}

Ok but how to use it ? I tried this but it makes the code not working again (does nothing without error)

OnOwnershipChanged(msg)
	{
		warn("OwnershipChanged");
		if (msg.to == INVALID_PLAYER)
			return;

		
		if (msg.ent)
			this.UpdateColor();

		
		// warn("OwnershipChangedUpdateColor");
	}

And will it be really useful ? I mean is the problem comes from this or not ? 

+ I don't know if my last post was clear after reading it :/

Edited by Allan
Link to comment
Share on other sites

Here is the "final" version of my UpdateColor function

UpdateColor()
	{
		const cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
		let owner = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner();
		warn("Entity : " + this.entity + "Owner : " + owner);
		
		let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
		if (!cmpVisual)
			return;
			
		
		if (cmpPlayer) 
			{
				const color = cmpPlayer.GetColor();
				cmpVisual.SetVariable("colorr", color.r);
				cmpVisual.SetVariable("colorg", color.g);
				cmpVisual.SetVariable("colorb", color.b);
			}
	}

	OnOwnershipChanged(msg)
	{
		if (msg.to == INVALID_PLAYER)
			return;
		
		this.UpdateColor();
	}

	OnGlobalOwnershipChanged(msg)
	{
		if (msg.to == INVALID_PLAYER)
			return;

		this.UpdateColor();
	}

	OnEntityRenamed(msg)
	{
		if (msg.to == INVALID_PLAYER)
			return;

		this.UpdateColor();
	}

	OnHealthChanged(msg)
	{
		if (msg.to == INVALID_PLAYER)
			return;

		this.UpdateColor();
	}

	OnGlobalInitGame(msg)
	{
		if (msg.to == INVALID_PLAYER)
			return;

		this.UpdateColor();
	}	

When I build a large wall (Tower + Wall + Tower), the particles of the first tower is gaia colored. When the wall is constructed, the first tower particles turns player colored. The third tower stays gaia colored since I build something else. I don't understand how is this possible to be honest :search: :lookaround:

Link to comment
Share on other sites

if (msg.ent === this.entity)
	this.UpdateColor();

I meant doing this in OnGlobalOwnershipChanged the global functions are called for every unit anytime anything changes. It's a bit better than OnUpdate but it still isn't great for performance.

33 minutes ago, Allan said:

en the wall is constructed, the first tower particles turns player colored.

I suppose it triggers one of the global functions and causes the old buildings to reupdate. I didn't know you were using wals, there might be something different in Wall.js or Wallset.js

Link to comment
Share on other sites

1 hour ago, Stan` said:
if (msg.ent === this.entity)
	this.UpdateColor();

 

If I put this in OnGlobalOwnershipChanged it doesn't work anymore, the color is not updated.

1 hour ago, Stan` said:

I suppose it triggers one of the global functions and causes the old buildings to reupdate. I didn't know you were using wals, there might be something different in Wall.js or Wallset.js

The wallset.js in kind of empty to be honest, and I can't find another file attached to walls. Moreover, I don't understand why i've got a good preview (with the good color) with my wall tower but not with my other building (spacedock) :search:

 

I'll see this tomorrow I take a break :sleepy:

Link to comment
Share on other sites

4 minutes ago, Allan said:

If I put this in OnGlobalOwnershipChanged it doesn't work anymore, the color is not updated.

The wallset.js in kind of empty to be honest, and I can't find another file attached to walls. Moreover, I don't understand why i've got a good preview (with the good color) with my wall tower but not with my other building (spacedock) :search:

 

I'll see this tomorrow I take a break :sleepy:

Can you push it in the branch of the mod git so I can take a look tomorrow ?

  • Like 1
Link to comment
Share on other sites

Posted (edited)
UpdateColor()
	{

		// warn("UpdateColor");

		// let cmpFoundationOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
		// let owner = cmpFoundationOwnership.GetOwner();
		// if (cmpFoundationOwnership)
		// 	{
		// 		cmpFoundationOwnership.SetOwner(owner);
		// 	}
   		// warn("Entity : " + this.entity + "Owner : " + owner)

		// var owner = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner();
		
		const cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
		let owner = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner();
		warn("Entity : " + this.entity + "Owner : " + owner);
		
		let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
		if (!cmpVisual)
			return;
			
		
		if (cmpPlayer) 
			{
				const color = cmpPlayer.GetColor();
				cmpVisual.SetVariable("colorr", color.r);
				cmpVisual.SetVariable("colorg", color.g);
				cmpVisual.SetVariable("colorb", color.b);
			}
		// warn("red : "+color.r);
		// warn("green : "+color.g);
		// warn("blue : "+color.b);
	}

 

I think it doesn't get the good color untli the building is finally constructed, so that's why it applies the gaia color. But how to collect the owner of a building before its construction ?  :search:

 

Something that I don't understand is that I call all the messages during the construction, it should be good but it's not 

Edited by Allan
Link to comment
Share on other sites

20 hours ago, Stan` said:

Can you push it in the branch of the mod git so I can take a look tomorrow ?

Hey ! Did you find something ? 

 

My exams are tomorrow and Friday so I'll be back on this after my exams :)

Link to comment
Share on other sites

Hey, I have some good news and some bad news... The good news is that I found the potential culprit for that messy behavior

okay preview -> broken construction -> broken final.

The problem is that Foundation.js sets the scaffold animation on buildings. That breaks the construction (If you remove the lines in Foundation.js the color is correct until completion)

After that it switches animation again to Idle I suppose and that breaks the final state. It "works" for buildings that have been placed at the start of the map because I suppose they don't change anims.

Unfortunately there is no way to force colors to update after each animation change...

This might be a C++ "bug". Which means we can't fix it without hacks....

One could add 8 variants of the particle to every single actor and switch them in the component we made. Each particle variant would have a color that you need to guess from the rgb values (fun heh)

Another solution is to get the animation name using a timer periodically and if it changed to force the color to update again.

Link to comment
Share on other sites

Posted (edited)

Ok thank you ! 
 

On 06/06/2024 at 10:35 PM, Stan` said:

One could add 8 variants of the particle to every single actor and switch them in the component we made. Each particle variant would have a color that you need to guess from the rgb values (fun heh)

I only have one week left to do it, so I don't think I will follow this solution.

On 06/06/2024 at 10:35 PM, Stan` said:

Another solution is to get the animation name using a timer periodically and if it changed to force the color to update again.

I think I can do this, I just don't know where can I put this timer ? In what file ?

 

 

Maybe these particules are only a detail, I'm hesitating, it's already working to be honest, I don't know if I will take time for this, because I have a lot of things to do :/

 

Edited by Allan
Link to comment
Share on other sites

In init you can do something like

const refreshInterval = 1000; // 1s
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
cmpTimer.SetInterval(this.entity, IID_PlayerParticleColor, "TimerTick", refreshInterval, refreshInterval, undefined);

Then you need to add function like

TimerTick = function()
{
	this.UpdateColor();
};

You can be a bit smarter and check what is the current animation and if it differs from the previous one but that's a bit more elaborate :)

 

  • Like 1
Link to comment
Share on other sites

Posted (edited)

Nice it's working ! Are you sure that it will not be too expensive for the engine ?

 

I mean updating the color every 1 sec, maybe we have to put this on 3 or 4 sec ?

 

Edited by Allan
Link to comment
Share on other sites

22 minutes ago, Allan said:

I mean updating the color every 1 sec, maybe we have to put this on 3 or 4 sec ?

It's not perfect but it should be okay. You might also reduce the amount of entities with such particles :)

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...