ZScript Discussion

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
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm

Re: ZScript Discussion

Post by ibm5155 »

so can I request clientside scripts from zandronum into zdoom please? :D
User avatar
ZZYZX
 
 
Posts: 1381
Joined: Sun Oct 14, 2012 1:43 am
Discord: ZZYZX#1394
Github ID: jewalky
Location: Ukraine

Re: ZScript Discussion

Post by ZZYZX »

So in current version, code like this produces results like this.
That's also an usage example. Any feedback on usability of this?

(also, @Graf, why exactly do Fist and Pistol call OnDestroy, but next given weapons don't call PostBeginPlay?)
Last edited by ZZYZX on Mon Jan 30, 2017 6:43 pm, edited 1 time in total.
User avatar
Major Cooke
Posts: 8070
Joined: Sun Jan 28, 2007 3:55 pm

Re: ZScript Discussion

Post by Major Cooke »

Global vars?

As an aside, this could be EXTREMELY useful for my other mod I'm working on, and choosing random respawn locations. More info on that later when I have time.
User avatar
ZZYZX
 
 
Posts: 1381
Joined: Sun Oct 14, 2012 1:43 am
Discord: ZZYZX#1394
Github ID: jewalky
Location: Ukraine

Re: ZScript Discussion

Post by ZZYZX »

Using EventHandler as static storage is possible. Although I personally wouldn't... or would. Who knows. :)
It wasn't designed for that, but fits that role perfectly.
Last edited by ZZYZX on Mon Jan 30, 2017 6:22 pm, edited 1 time in total.
User avatar
Major Cooke
Posts: 8070
Joined: Sun Jan 28, 2007 3:55 pm

Re: ZScript Discussion

Post by Major Cooke »

I'd definitely use it for spawn points and keeping track of what team belongs to which since they can change teams based on whichever team is operating on them.
ZzZombo
Posts: 277
Joined: Mon Jul 16, 2012 2:02 am

Re: ZScript Discussion

Post by ZzZombo »

We have structs, and heck, could even use classes for messaging, and thus, your point about extensibility is invalid, since we could pass them into callbacks. But that's all beside the point that you missed in the first post I made regarding it: I don't see the proposed system easily interoperable with other parts of the game. For example, I want the Archvile to actively seek and resurrect fallen monsters. With your system I would have to keep track of all Archviles alive, "subscribe" to the "actor died" event, then from the handler pass the data to the Archviles and make them get over there and raise the fallen, rinse and repeat. In ideal world, I would make each Archvile subscribe to the same event, and cleanly get the relevant message data and deal with it.
User avatar
ZZYZX
 
 
Posts: 1381
Joined: Sun Oct 14, 2012 1:43 am
Discord: ZZYZX#1394
Github ID: jewalky
Location: Ukraine

Re: ZScript Discussion

Post by ZZYZX »

No. You will have to do a ThinkerIterator or BlockThingsIterator, check for dead actors and guide the archvile to the closest of them.

WorldThingDied is not for altering the playsim, it's for collecting stats, displaying various messages, and such.
For example you have a custom statusbar which checks boss monsters in the level and adds/removes them from the display.
Or if you want to observe damage events and do all kinds of processing about them (i.e. see if actor X was damaged by player Y, add Z score to the player based on the type or calculated power of damaged monster).

Otherwise, if you really want to use event handlers for this, you have to store all dead things in an array in an event handler, and in the archvile do something like this:

Code: Select all

DeadThingsLister lister = EventHandler.Find('DeadThingsLister');
// pick random dead thing from lister.DeadThings array
Currently you'd have to do a static array with a length counter, but I know in the future there are going to be dynamic arrays and maybe linked lists, which makes this approach rational.
And there's nothing wrong with this, having 1000 event handlers in separate Actors is not going to work properly anyway performance-wise, because the current architecture assumes there will be AT MOST some 10 event handlers registered.

Also, one major point that you are missing — handlers are implemented as classes because they should not be tied to the playsim (actors or thinkers), as event handlers are actually ENTRYPOINTS into the stuff that is not available for actors at all, like drawing on the screen, doing user input, perhaps in the future even loading your own lumps by something like GameLoadLumps. It's a plugin system more than everything else.
The playsim stuff is there mainly so that you don't anymore need to depend on ACS for catching these events (like map OPEN, etc).

Also, tested with Thing-related handlers in nuts.wad, don't seem to get any performance regressions if NOT handling any events, and almost unnoticeable performance regressions with non-empty defined handlers (like -3 fps or so, while I get 18 fps in nuts.wad after firing a pistol even on a regular GZDoom).
User avatar
Nash
 
 
Posts: 17296
Joined: Mon Oct 27, 2003 12:07 am
Twitch ID: nashmuhandes
Github ID: nashmuhandes
Location: Kuala Lumpur, Malaysia

Re: ZScript Discussion

Post by Nash »

Major Cooke wrote: I too would love to hear more about this.
First, you must establish a relationship between the spawner and the spawnee (eg the player and the particle, respectively). Either store the spawner in a pointer -or- make an actor variable have a valid reference to it -or- whatever else that works for you.

Then, in BeginPlay or Tick, check for the consoleplayer, like this:

Code: Select all

class Z_Precipitation : Actor
{
    // [snip]

    override void Tick()
    {
        Super.Tick();

        if (!tracer)
        {
            return;
        }

        // destroy precipitation from other players
        if (tracer != null && tracer != players[consoleplayer].mo)
        {
            //bINVISIBLE = true;
            Destroy();
        }
    }
}
Look inside zscript/inventory/powerups.txt APowerSpeed :: DoEffect for a similar concept (although it's functionality is reversed, is checking for the first person camera instead of just the actor, and it's just making the trail invisible instead of destroying it; see below)

So how is this safe in multiplayer?

Well, the particle I am spawning is COMPLETELY non-interactive - there's no collision, it doesn't affect anything else around it, and most importantly - the particle does not spawn anything else!!! That last bit is very important; as soon as you try to spawn something from that particle, the game will desync.

Also, another crucial step is that the particle MUST unconditionally spawn on all machines, for all players. That's the rule. So I made no effort to stop the particles from spawning for everyone.

So because my precipitation particle is completely isolated in terms of collision and spawning new actors, I can actually afford to destroy it, if it doesn't "belong" to my player actor. So this means that I can crank up the density of the particle spawn for MYSELF, and other players will not notice a thing on their screens ("my" particles don't even exist for too long on their machine; they've already been Destroy()'ed as early as possible!)

Lastly, if you're too afraid of this, you can also do what PowerSpeed is doing in gzdoom.pk3 and simply make it invisible, although that won't get rid of the Actor overhead because it still exists in the world, just made invisible.
ZZYZX wrote:modders that do care about demo and networking compatibility!
Of course I do. :mrgreen: Multiplayer still works the last time I played it a few weeks ago, and there were people who went through a lot of trouble to even make multiplayer a thing in Doom in the first place, so why not support it? :D

Also, awesome work on your event handler system. I can't say I fully understand yet the entire concept and how to use it; but if it will let me replicate OPEN ACS scripts, and to do things like store quest variables and quest progress that remain persistent between maps - I'm stoked for it. :D
User avatar
ZZYZX
 
 
Posts: 1381
Joined: Sun Oct 14, 2012 1:43 am
Discord: ZZYZX#1394
Github ID: jewalky
Location: Ukraine

Re: ZScript Discussion

Post by ZZYZX »

Nash wrote:Also, awesome work on your event handler system. I can't say I fully understand yet the entire concept and how to use it; but if it will let me replicate OPEN ACS scripts, and to do things like store quest variables and quest progress that remain persistent between maps - I'm stoked for it. :D
You can't make something persistent between maps in the savegame using event handlers.
That's going to be an entirely different concept (i.e. storing serialized global variables in ZScript) which is probably out of scope of the event system.

In the event system, event handler is either serialized or global.
That is, you can have GameInfo-defined Static event handler, but this will result in something that can't be stored in a savegame and will always be loaded from the current source code.
Then you can have GameInfo or Map-defined non-Static event handler, and it will be saved to savegames and between levels in a hub, but you won't be able to access these from another level.
User avatar
Xaser
 
 
Posts: 10771
Joined: Sun Jul 20, 2003 12:15 pm

Re: ZScript Discussion

Post by Xaser »

I'm a bit confused about the "not for altering the playsim" statement -- This makes sense for render events but not so much for the world types. Would I not be able to do something like spawn an actor in a WorldThingDamaged event or iterate through the global players[] array in WorldLoaded and initialize some stuff? Seems like I'm missing or misunderstanding something.

The one I'd be really interested in though is the future "PlayerJoined" event; that'd be the proper way to init player vars on map start and presumably we'll at be allowed to modify the player through that, at least. :P
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 48040
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript Discussion

Post by Graf Zahl »

If the event is fired from within the playsim it should be safe to do play-related things in it.

Of course we all know that with so much power at your disposal comes great responsibility. This event system is very powerful but that also means it's easily abusable in the end of less skilled modders.
User avatar
Major Cooke
Posts: 8070
Joined: Sun Jan 28, 2007 3:55 pm

Re: ZScript Discussion

Post by Major Cooke »

@Nash: To clarify this is spawning one for all eight of them? (eight in total) Or because this is non-interactive, the actor can safely call Destroy() without consequence and only one spawn is needed?
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm

Re: ZScript Discussion

Post by ibm5155 »

Does zscript support #defines ?
and where should I add the doomed number in my zscript code?
EDIT:
And can I make global vars or I'm forced to create an actor where everyone has access to his vars?
User avatar
ZZYZX
 
 
Posts: 1381
Joined: Sun Oct 14, 2012 1:43 am
Discord: ZZYZX#1394
Github ID: jewalky
Location: Ukraine

Re: ZScript Discussion

Post by ZZYZX »

ibm5155 wrote:Does zscript support #defines ?
IDTS, use const for that.
ibm5155 wrote:and where should I add the doomed number in my zscript code?
https://zdoom.org/wiki/MAPINFO/Editor_number_definition
ibm5155 wrote:EDIT:
And can I make global vars or I'm forced to create an actor where everyone has access to his vars?
Event system kinda allows you to have global vars in the handler, but that's a hack and otherwise you have to create an actor, yes.
(and Graf hasn't pulled nor commented the ES yet anyway)
User avatar
Major Cooke
Posts: 8070
Joined: Sun Jan 28, 2007 3:55 pm

Re: ZScript Discussion

Post by Major Cooke »

He's busy with a work project so it'll have to wait.

Return to “Scripting”