EVENT scripts: Difference between revisions
(Added documentation for GAMEEVENT_JOINQUEUECHANGED.) Tag: Source edit |
(Renamed GAMEEVENT_ACTOR_ARMORDAMAGED to GAMEEVENT_ACTOR_DAMAGED_PREMOD.) Tag: Source edit |
||
Line 31: | Line 31: | ||
;GAMEEVENT_ACTOR_DAMAGED 11 | ;GAMEEVENT_ACTOR_DAMAGED 11 | ||
:When an actor is just about to take damage, after all damage modifications are applied. The activator is the actor taking damage, <tt>arg1</tt> is the amount of damage received, and <tt>arg2</tt> is a dynamic ACS string containing the damage type. | :When an actor is just about to take damage, after all damage modifications are applied. The activator is the actor taking damage, <tt>arg1</tt> is the amount of damage received, and <tt>arg2</tt> is a dynamic ACS string containing the damage type. | ||
; | ;GAMEEVENT_ACTOR_DAMAGED_PREMOD 12 | ||
:Behaves exactly like GAMEEVENT_ACTOR_DAMAGED but is triggered slightly earlier, just before an actor's | :Behaves exactly like GAMEEVENT_ACTOR_DAMAGED but is triggered slightly earlier, just before an actor's armour or inventory items can absorb any damage. This was previously known as GAMEEVENT_ACTOR_ARMORDAMAGED. | ||
;{{Devfeature|3.2|alpha}} GAMEEVENT_DOMINATION_CONTROL 13 | ;{{Devfeature|3.2|alpha}} GAMEEVENT_DOMINATION_CONTROL 13 | ||
: When a player takes control of a point sector in [[Game Modes#Domination|Domination]]. The activator is the player who took control of the point sector, <tt>arg1</tt> is the team index that previously owned the sector (this is always 255 if no team occupied it before), and <tt>arg2</tt> is a dynamic ACS string containing the name of the sector that was captured. | : When a player takes control of a point sector in [[Game Modes#Domination|Domination]]. The activator is the player who took control of the point sector, <tt>arg1</tt> is the team index that previously owned the sector (this is always 255 if no team occupied it before), and <tt>arg2</tt> is a dynamic ACS string containing the name of the sector that was captured. | ||
Line 47: | Line 47: | ||
You are allowed to modify the results of some events by changing the result value of the EVENT script itself via {{zdoomwiki|SetResultValue}}. The event types that current support this are: | You are allowed to modify the results of some events by changing the result value of the EVENT script itself via {{zdoomwiki|SetResultValue}}. The event types that current support this are: | ||
*'''GAMEEVENT_CHAT''': setting the result value to zero prevents the chat message from being printed onto the screen. If the result value is non-zero, the chat message will be printed like normal. | *'''GAMEEVENT_CHAT''': setting the result value to zero prevents the chat message from being printed onto the screen. If the result value is non-zero, the chat message will be printed like normal. | ||
*'''GAMEEVENT_ACTOR_DAMAGED''' and ''' | *'''GAMEEVENT_ACTOR_DAMAGED''' and '''GAMEEVENT_ACTOR_DAMAGED_PREMOD''': changing the result value affects how much damage the actor actually takes. | ||
*{{Devfeature|3.2|alpha}} '''GAMEEVENT_MEDALS''': setting the result value to zero prevents the player from receiving the medal that was earned. | *{{Devfeature|3.2|alpha}} '''GAMEEVENT_MEDALS''': setting the result value to zero prevents the player from receiving the medal that was earned. | ||
*{{Devfeature|3.2|alpha}} '''GAMEEVENT_DOMINATION_POINT''': the result value determines how many points a team gets from the point sector. Anything above and including zero is acceptable. | *{{Devfeature|3.2|alpha}} '''GAMEEVENT_DOMINATION_POINT''': the result value determines how many points a team gets from the point sector. Anything above and including zero is acceptable. | ||
Line 61: | Line 61: | ||
==Additional information== | ==Additional information== | ||
Due to risks of performance drops, '''GAMEEVENT_ACTOR_SPAWNED''', '''GAMEEVENT_ACTOR_DAMAGED''', and ''' | Due to risks of performance drops, '''GAMEEVENT_ACTOR_SPAWNED''', '''GAMEEVENT_ACTOR_DAMAGED''', and '''GAMEEVENT_ACTOR_DAMAGED_PREMOD''' are disabled by default. There are two methods for enabling these event types: | ||
*'''Method A''': Add the properties <tt>ForceSpawnEventScripts</tt> or <tt>ForceDamageEventScripts</tt> in the [[zdoom:GameInfo_definition|GameInfo Definition]]. This helps if you want all actors to execute these events. Note that using this method in the case of '''GAMEEVENT_ACTOR_SPAWNED''', actors with the <tt>NOBLOCKMAP</tt> (actors with <tt>ISMISSILE</tt> will still execute the event) or <tt>NOSECTOR</tt> flags still won't execute the event. This way, only the non-trivial actors are accounted for. | *'''Method A''': Add the properties <tt>ForceSpawnEventScripts</tt> or <tt>ForceDamageEventScripts</tt> in the [[zdoom:GameInfo_definition|GameInfo Definition]]. This helps if you want all actors to execute these events. Note that using this method in the case of '''GAMEEVENT_ACTOR_SPAWNED''', actors with the <tt>NOBLOCKMAP</tt> (actors with <tt>ISMISSILE</tt> will still execute the event) or <tt>NOSECTOR</tt> flags still won't execute the event. This way, only the non-trivial actors are accounted for. | ||
*'''Method B''': Add the <tt>USESPAWNEVENTSCRIPT</tt> or <tt>USEDAMAGEEVENTSCRIPT</tt> flags to the actor that you wish have execute the events. These are useful if you only want certain actors to trigger the events and not all of them, which can optimize your mod better. | *'''Method B''': Add the <tt>USESPAWNEVENTSCRIPT</tt> or <tt>USEDAMAGEEVENTSCRIPT</tt> flags to the actor that you wish have execute the events. These are useful if you only want certain actors to trigger the events and not all of them, which can optimize your mod better. | ||
Line 68: | Line 68: | ||
In addition, '''GAMEEVENT_ACTOR_DAMAGED''' and ''' | In addition, '''GAMEEVENT_ACTOR_DAMAGED''' and '''GAMEEVENT_ACTOR_DAMAGED_PREMOD''' enable special actor pointers that give you access to the actors involved in the <tt>P_DamageMobj</tt> call: | ||
*AAPTR_DAMAGE_SOURCE: Accesses the "shooter" responsible for making the attack. | *AAPTR_DAMAGE_SOURCE: Accesses the "shooter" responsible for making the attack. | ||
*AAPTR_DAMAGE_INFLICTOR: Accesses the actor directly responsible for causing damage (e.g. a barrel or projectile). | *AAPTR_DAMAGE_INFLICTOR: Accesses the actor directly responsible for causing damage (e.g. a barrel or projectile). |
Revision as of 03:22, 30 August 2024
EVENT scripts are scripts that are triggered by various in-game events:
script 123 (int type, int arg1, int arg2) EVENT
The event that caused the script to be fired is enumerated into the type argument. arg1 and arg2 may or may not be used (depending on the event type) to provide additional data.
Script types
- GAMEEVENT_PLAYERFRAGS 0
- Player frags another player. The activator is the killing player and arg1 is the number of the player who was fragged.
- GAMEEVENT_MEDALS 1
- Player receives a medal. The activator is the player who recieves the medal and arg1 is the string containing the name of the medal.
- GAMEEVENT_CAPTURES 2
- Player captures the flag/skull. The activator is the capturing player and arg1 is the player who assisted. If nobody assisted the capture, -1 is supplied instead. In Zandronum 3.1, arg2 returns the number of points earned.
- GAMEEVENT_TOUCHES 3
- Player touches the flag/skull. The activator is the player who touched the team item and arg1 is the team index of the team whose flag/skull was touched.
- GAMEEVENT_RETURNS 4
- The flag/skull is returned. The activator is the player who returned the team item (or the world if the item was automatically returned), arg1 is the index of the team whose item was returned. arg2 is set to 0 if the return was done automatically or 1 if it was done by a player.
- GAMEEVENT_ROUND_STARTS 5
- When the round starts.
- GAMEEVENT_ROUND_ENDS 6
- The current round ends and the win sequence starts, e.g. when the fraglimit is hit.
- GAMEEVENT_ROUND_ABORTED 7
- If the round is aborted (e.g. in duel where one of the combatants leaves the game).
- GAMEEVENT_CHAT 8
- When a chat message is sent. The activator is always the world, arg1 is the number of the player who sent the message (if the server sent the message, -1 is passed instead), and arg2 is set to 0 if it was a global chat message or 1 if it was a team chat message.
- GAMEEVENT_PLAYERCONNECT 9
- A client or bot connects to the server. The activator is the world, arg1 is the number of the player, and arg2 is set to 1 if the client had previously joined the server or 0 if not.
- GAMEEVENT_ACTOR_SPAWNED 10
- When an non-player actor is spawned. Strictly speaking, this occurs just before the actor's first tic. The activator is the actor that spawned.
- (development version 3.2-alpha and above only): arg1 is a boolean which is true if the actor was spawned by the level.
- GAMEEVENT_ACTOR_DAMAGED 11
- When an actor is just about to take damage, after all damage modifications are applied. The activator is the actor taking damage, arg1 is the amount of damage received, and arg2 is a dynamic ACS string containing the damage type.
- GAMEEVENT_ACTOR_DAMAGED_PREMOD 12
- Behaves exactly like GAMEEVENT_ACTOR_DAMAGED but is triggered slightly earlier, just before an actor's armour or inventory items can absorb any damage. This was previously known as GAMEEVENT_ACTOR_ARMORDAMAGED.
- (development version 3.2-alpha and above only) GAMEEVENT_DOMINATION_CONTROL 13
- When a player takes control of a point sector in Domination. The activator is the player who took control of the point sector, arg1 is the team index that previously owned the sector (this is always 255 if no team occupied it before), and arg2 is a dynamic ACS string containing the name of the sector that was captured.
- (development version 3.2-alpha and above only) GAMEEVENT_DOMINATION_POINT 14
- When a team gets a point for controlling point sector in Domination. The activator is always the world, arg1 is the team index that occupies the sector, and arg2 is a dynamic ACS string containing the name of the sector.
- (development version 3.2-alpha and above only) GAMEEVENT_PLAYERLEAVESSERVER 15
- When a player disconnects from the server (the opposite of GAMEEVENT_PLAYERCONNECT). This is not to be confused with DISCONNECT scripts which fire when a player leaves the game, including becoming a spectator. The activator is the world, arg1 is the number of the player who disconnected, and arg2 indicates the reason the player disconnected - see Leave reasons below.
- (development version 3.2-alpha and above only) GAMEEVENT_LEVEL_INIT 16
- This event is executed early in map initialization, before things are spawned, OPEN scripts executed, etc. This script is usable as a way to manipulate map features early where the regular OPEN script doesn't work. This is not to be confused with said OPEN scripts which fire when a level initialized, happening much later down the line. The activator is the world.
- (development version 3.2-alpha and above only) GAMEEVENT_JOINQUEUECHANGED 17
- When a player is added or removed from the join queue. The activator is the world, arg1 is the number of the player, and arg2 is their position in line (this is always -1 if they're removed from the join queue).
Event handling
You are allowed to modify the results of some events by changing the result value of the EVENT script itself via SetResultValue. The event types that current support this are:
- GAMEEVENT_CHAT: setting the result value to zero prevents the chat message from being printed onto the screen. If the result value is non-zero, the chat message will be printed like normal.
- GAMEEVENT_ACTOR_DAMAGED and GAMEEVENT_ACTOR_DAMAGED_PREMOD: changing the result value affects how much damage the actor actually takes.
- (development version 3.2-alpha and above only) GAMEEVENT_MEDALS: setting the result value to zero prevents the player from receiving the medal that was earned.
- (development version 3.2-alpha and above only) GAMEEVENT_DOMINATION_POINT: the result value determines how many points a team gets from the point sector. Anything above and including zero is acceptable.
A few things to note are:
- If there are multiple EVENT scripts, the result of the event will be transferred from one script to the next. If more than one script tries to change the result of the event, then whichever script is fired last decides the outcome of the event.
- Event handling does not work at all in CLIENTSIDE scripts.
It's recommended that you change the result value in only one script per event type, unless you know the order in which the scripts are fired (e.g. creating an addon of a mod that overrides the result of the event).
(development version 3.2-alpha and above only): It's possible to get the current result value with GetEventResult.
Additional information
Due to risks of performance drops, GAMEEVENT_ACTOR_SPAWNED, GAMEEVENT_ACTOR_DAMAGED, and GAMEEVENT_ACTOR_DAMAGED_PREMOD are disabled by default. There are two methods for enabling these event types:
- Method A: Add the properties ForceSpawnEventScripts or ForceDamageEventScripts in the GameInfo Definition. This helps if you want all actors to execute these events. Note that using this method in the case of GAMEEVENT_ACTOR_SPAWNED, actors with the NOBLOCKMAP (actors with ISMISSILE will still execute the event) or NOSECTOR flags still won't execute the event. This way, only the non-trivial actors are accounted for.
- Method B: Add the USESPAWNEVENTSCRIPT or USEDAMAGEEVENTSCRIPT flags to the actor that you wish have execute the events. These are useful if you only want certain actors to trigger the events and not all of them, which can optimize your mod better.
If you wish to forbid an actor from triggering these events, you can add the NOSPAWNEVENTSCRIPT or NODAMAGEEVENTSCRIPT flags to them.
In addition, GAMEEVENT_ACTOR_DAMAGED and GAMEEVENT_ACTOR_DAMAGED_PREMOD enable special actor pointers that give you access to the actors involved in the P_DamageMobj call:
- AAPTR_DAMAGE_SOURCE: Accesses the "shooter" responsible for making the attack.
- AAPTR_DAMAGE_INFLICTOR: Accesses the actor directly responsible for causing damage (e.g. a barrel or projectile).
- AAPTR_DAMAGE_TARGET: Accesses the "victim" taking the damage. By default, this actor is already the activator of the script.
You may use these in ACS functions that deal with actor pointers, such as IsPointerEqual, SetActivator, SetPointer, or Warp.
It's recommended not to use these three event types in conjunction with CLIENTSIDE scripts, since the server must tell clients to execute the scripts every time the events are fired. Due to their frequent occurrence, this can create lots of network traffic, resulting in a huge drop in performance. Furthermore, the extra actor pointers available in damage events, along with the damage type stored in arg2, do not work properly in CLIENTSIDE scripts.
Leave reasons
The second argument passed to GAMEEVENT_PLAYERLEAVESSERVER indicates the reason a player disconnected from the server:
- LEAVEREASON_LEFT 0
- The player disconnected from the server of their own accord.
- LEAVEREASON_KICKED 1
- The player was kicked from the server by an admin.
- LEAVEREASON_ERROR 2
- The client was disconnected due to an error.
- LEAVEREASON_TIMEOUT 3
- The player timed out.
- LEAVEREASON_RECONNECT 4
- The player is re-connecting; e.g. the map command was used.
Examples
Let's say we want to use GAMEEVENT_ACTOR_SPAWNED and GAMEEVENT_ACTOR_DAMAGED for our mod. For the sake of simplicity, we want the events to be triggered by all actors, so we'll create a MAPINFO lump in our WAD file and add the following:
GameInfo
{
ForceSpawnEventScripts = true
ForceDamageEventScripts = true
}
Next, we'll create an ACS EVENT script that prints a message whenever an actor is spawned or takes damage. GAMEEVENT_ACTOR_DAMAGED gives us access to a lot of information about how an actor takes damage, so let's also print that stuff.
script "ActorEvent" (int type, int arg1, int arg2) EVENT
{
if (type == GAMEEVENT_ACTOR_SPAWNED)
{
// This prints every time an actor is spawned.
PrintBold(s:GetActorClass(0), s:" has spawned!");
}
else if (type == GAMEEVENT_ACTOR_DAMAGED)
{
// This event is called just before the actor's health is reduced. We can get
// their new health by subtracting their current health by arg1.
int oldHealth = GetActorProperty(0, APROP_HEALTH);
int newHealth = oldHealth - arg1;
// Construct a string that displays everything.
str message = StrParam(s:GetActorClass(0), s: " got damaged by ", d:arg1, s:" points! The damage type is: ", s:arg2);
message = StrParam(s:message, s:"\nTheir health was ", d:oldHealth, s:", now it's ", d:newHealth);
// Print the names of the source and inflictor classes, if they exist.
if (SetActivator(0, AAPTR_DAMAGE_SOURCE));
message = StrParam(s:message, s:"\nThe source was ", s:GetActorClass(0));
if (SetActivator(0, AAPTR_DAMAGE_INFLICTOR));
message = StrParam(s:message, s:"\nThe inflictor was ", s:GetActorClass(0));
// Set the activator back to the target.
SetActivator(0, AAPTR_DAMAGE_TARGET);
// Print the message!
PrintBold(s:message);
}
}