ZScript global variables

From ZDoom Wiki
Jump to navigation Jump to search
Note: This feature is for ZScript only.


ZScript possesses several global structs accessible by classes.

Type Name Writable? Use/meaning
int validcount yes Internal variable used to avoid processing of the same data during one render frame.
bool multiplayer no Set to true if the game is networked.
LevelLocals level - Contains various level-related data, for example level's time, level and map name, settings and statistics.
DehInfo deh - Internal values used by DeHackEd-parsing code.
PlayerInfo[] players - List of all players in the level.
bool[] playeringame no An array that defines whether the specified PlayerInfo structure in players[] is set.
EGameAction gameaction yes Deeply internal variable used to get/set the current engine state.
WARNING: Do NOT use this unless you know GameAction works!
int consoleplayer no The player that owns the current client.
Weapon WP_NOCHANGE no An internal constant to describe the case when PlayerInfo.PendingWeapon doesn't have a value.

Creating Global Variables

There are two methods available for handling global variables: EventHandlers and Thinkers. Each has their advantages and disadvantages.

EventHandlers come in two flavors: EventHandler, which is only available within maps but are saved, and StaticEventHandler, which persist outside of maps but are never saved to savegames. See Events and handlers for more information on how to set up an event handler.

Individual EventHandler classes can be referenced using the Find() function, as below.

// The EventHandler itself.
Class MyEventHandler : EventHandler
{
	int MyGlobalInt;
}

// Example of accessing said EventHandler from an actor.
Class MyCustomClass : Actor
{
	MyEventHandler Event;
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		// Be sure to call the proper `Find()` method for the type of EventHandler you are using or problems may occur.
		// `EventHandler.Find()` for EventHandler and `StaticEventHandler.Find()` for StaticEventHandler
		Event = MyEventHandler(EventHandler.Find("MyEventHandler"));
		if (Event)
		{
			Event.MyGlobalInt = 1;
			Console.Printf("My global int is: %d", Event.MyGlobalInt);
		}
	}
}

All Thinkers, by contrast, are saved to savegames. Using a ThinkerIterator is slower than the StaticEventHandler's Find function, but a Thinker with the statnum STAT_STATIC is the only way to store information for the duration of a play session, saved and loaded or not. This performance hit can be mitigated by keeping a reference to the Thinker being used for global variables in either the actors needing to reference it or another, higher global variable keeper, such as an EventHandler.

// An example global variables thinker.
class MyGlobalVariables : Thinker
{
	int testVar;

	MyGlobalVariables Init()
	{
		ChangeStatNum(STAT_INFO); // Change this to STAT_STATIC if persisting between maps is desired.
		return self;
	}

	static MyGlobalVariables Get()
	{
		ThinkerIterator it = ThinkerIterator.Create("MyGlobalVariables",STAT_INFO); // Change this to STAT_STATIC if persisting between maps is desired.
		let p = MyGlobalVariables(it.Next());
		if (p == null)
		{
			p = new("MyGlobalVariables").Init();
		}
		return p;
	}
}

// Example of an actor accessing the above thinker's variables.
Class MyCustomClass : Actor
{
	override void PostBeginPlay()
	{
		Super.PostBeginPlay();
		let globalvars = MyGlobalVariables.Get();
		if (globalvars)
		{
			globalvars.testVar++;
			Console.Printf("My global int is: %d", globalvars.testVar);
		}
	}
}