How to change actors from ZScript menus (ui scope) ?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
User avatar
krokots
Posts: 257
Joined: Tue Jan 19, 2010 5:07 pm

How to change actors from ZScript menus (ui scope) ?

Post by krokots »

Let's say I want to make a menu which increases player health on open :

Code: Select all

class TMenu : ListMenu
{
	Actor plr;
	override void Init(Menu parent, ListMenuDescriptor desc)
	{
		plr = players[consoleplayer].mo;
		if(plr)
			plr.health++;
		Super.Init(parent, desc);
	}
}
Unfortunately it can't be done in this way cause the UI scope of Menu class. So how can I do this?
ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: How to change actors from ZScript menus (ui scope) ?

Post by ZippeyKeys12 »

Look at events [wiki=Events_and_handlers]here[/wiki]. If you don't understand it, I can try and write an example.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48666
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: How to change actors from ZScript menus (ui scope) ?

Post by Graf Zahl »

The only way to do this is through a network event. The reason is that changing play data directly from the menu not only can cause network/demo desyncs but in case of perfectly implemented C/S wouldn't necessarily even exist on the same machine, except for a mirrored read-only copy of the play data.

BTW, in games like Quake or Quake 2, everything had to be explicitly routed through the C/S protocol.
User avatar
Nash
 
 
Posts: 17368
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: How to change actors from ZScript menus (ui scope) ?

Post by Nash »

Graf Zahl wrote:BTW, in games like Quake or Quake 2, everything had to be explicitly routed through the C/S protocol.
I take comfort in knowing that all this zealous blocking is also how other games do it. :mrgreen:

(Not a sarcastic remark; I really mean that in a positive way)
dpJudas
 
 
Posts: 2941
Joined: Sat May 28, 2016 1:01 pm

Re: How to change actors from ZScript menus (ui scope) ?

Post by dpJudas »

The blocking is actually very intentional. Without it, you'd accidentally do stuff that doesn't work and be essentially screwed the day you decide to add multiplayer support to your mod. For what its worth, some game engines are even more annoying where you can't even read directly from the play state in ui code.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48666
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: How to change actors from ZScript menus (ui scope) ?

Post by Graf Zahl »

... not to mention if we actually do C/S with real decoupling of play and UI state. This could even have some real benefits on single player because both systems could run on different threads. In that case all the UI would have is a read-only snapshot of the last calculated play frame and any modification of it would write into the void.
User avatar
krokots
Posts: 257
Joined: Tue Jan 19, 2010 5:07 pm

Re: How to change actors from ZScript menus (ui scope) ?

Post by krokots »

OK Just to be sure if I'm making this correctly (the easiest example possible) :

This is the custom event handler :

Code: Select all

Class GEventHandlers : EventHandler
{
	
	override void NetworkProcess(ConsoleEvent e)
	{
		int playerNumber = e.Player;
		let plr = players[playerNumber].mo;
		
		if(plr)
		{
			if (e.Name == "TestNetEvent")
			{
				Console.Printf(e.Name.." called by player : "..playerNumber);
				Console.Printf(plr.GetClassName());
				Console.Printf("Before : "..plr.Health);
				//plr.health++;	//health is not updating properly
				plr.A_SetInventory("Shotgun", 1);
				Console.Printf("After : "..plr.Health);
			}
			else
			{
				Console.Printf("Invalid event");			
			}		
		}
	}
}
And this is menu :

Code: Select all

Class TMenu : ListMenu
{
	Actor plr;
	override void Init(Menu parent, ListMenuDescriptor desc)
	{
		//plr = players[consoleplayer].mo;
		GEventHandlers.SendNetworkEvent("TestNetEvent",1,0,0);
		Super.Init(parent, desc);
	}
}
It works for player getting an item, but not for health. When I change health, console output from event shows it has changed, but in the HUD it is not changing (eg. I have 100 health and open the menu, the Console.printf("After : "..plr.health) prints 101 but HUD says 100).
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48666
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: How to change actors from ZScript menus (ui scope) ?

Post by Graf Zahl »

You also need to adjust the PlayerPawn's health to make it have an effect.
User avatar
krokots
Posts: 257
Joined: Tue Jan 19, 2010 5:07 pm

Re: How to change actors from ZScript menus (ui scope) ?

Post by krokots »

Graf Zahl wrote:You also need to adjust the PlayerPawn's health to make it have an effect.
Cool, I made it work, but I'm still not sure what the hell is going on.

Code: Select all

Class GEventHandlers : EventHandler
{
	
	override void NetworkProcess(ConsoleEvent e)
	{
		int playerNumber = e.Player;
		let plr = players[playerNumber].mo;
		
		if(plr)
		{
			if (e.Name == "TestNetEvent")
			{
				Console.Printf(e.Name.." called by player : "..playerNumber);
				plr.Health++;
				players[playerNumber].Health++;
			}
			else
			{
				Console.Printf("Invalid event");			
			}		
		}
	}
}
So there is "PlayerInfo" and "PlayerInfo.mo" which is "PlayerPawn". "PlayerPawn" is just an Actor, so if I want to change health obviously I need to change Actor's health variable. But I see that player's health calculations are based on "PlayerInfo's" health, not Actor's health ? Doomguy dies if his PlayerInfo health drops below 0, not his PlayerPawn's health. I'm probably making this more coplicated than it is.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48666
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: How to change actors from ZScript menus (ui scope) ?

Post by Graf Zahl »

In short: Both must be the same. This all is just historic bad design on id's part and cannot be changed for various technical reasons.
Blue Shadow
Posts: 4935
Joined: Sun Nov 14, 2010 12:59 am
Graphics Processor: ATI/AMD (Modern GZDoom)

Re: How to change actors from ZScript menus (ui scope) ?

Post by Blue Shadow »

Use [wiki]A_SetHealth[/wiki]. It handles everything for you.

Return to “Scripting”