Could level init be hooked with zscript events?
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!)
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!)
Could level init be hooked with zscript events?
This is a long shot, but haven't seen any discussion of it, so I'm gonna throw it out there.
Would it be remotely possible in some future zscript to hook into level init with some virtual method of StaticEventHandler? In other words, might it be possible at some point to create a zscript that has access to some of the action specials marked as "no script" -- for example, using "SetLineSpecial" to set "Line_Horizon" on a line?
Would it be remotely possible in some future zscript to hook into level init with some virtual method of StaticEventHandler? In other words, might it be possible at some point to create a zscript that has access to some of the action specials marked as "no script" -- for example, using "SetLineSpecial" to set "Line_Horizon" on a line?
Re: Could level init be hooked with zscript events?
It’s possible. There was a discussion about making internal map compatibility handler available to modders in some way or another.
Nothing was done yet in this direction. This feature is still waiting for an implementer
Nothing was done yet in this direction. This feature is still waiting for an implementer

- Graf Zahl
- Lead GZDoom+Raze Developer
- Posts: 49230
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: Could level init be hooked with zscript events?
Actually, it was silently added by processing all subclasses of LevelCompatibility in sequence. But keep in mind that this code is run before any actors are spawned so you cannot use it to initate any gameplay related actions. It's solely meant to alter the level itself._mental_ wrote:It’s possible. There was a discussion about making internal map compatibility handler available to modders in some way or another.
Nothing was done yet in this direction.
Re: Could level init be hooked with zscript events?
Well, this sounds like the best news I've heard all year.
So how does this work exactly? It looks like LevelCompatibility does everything in Apply, which isn't virtual... how do subclasses of LevelCompatibility do their thing?
So how does this work exactly? It looks like LevelCompatibility does everything in Apply, which isn't virtual... how do subclasses of LevelCompatibility do their thing?
Re: Could level init be hooked with zscript events?
gramps wrote:Well, this sounds like the best news I've heard all year.
The Date wrote:Tue Jan 01, 2019

- Graf Zahl
- Lead GZDoom+Raze Developer
- Posts: 49230
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: Could level init be hooked with zscript events?
gramps wrote:Well, this sounds like the best news I've heard all year.
So how does this work exactly? It looks like LevelCompatibility does everything in Apply, which isn't virtual... how do subclasses of LevelCompatibility do their thing?
It just goes through all classes, fetches their 'Apply' method and calls it. What exactly would you do with it? Like I said, right now it is pretty much limited to stuff that can be done in an editor.
Re: Could level init be hooked with zscript events?
Ahh, thanks, I'll try it!
Basically my overall goal is to be able to put portals all over the place without things getting too screwy. I was going to mess with Static_Init[1] and see if I could use it to get sky angle to render properly across portals.
But it looks like individual vertices can be moved around with this class, and I might even try "physically" rotating some geometry and putting in static portals.
[1] - It looks like this thing would be running at a point when it would be alright to use Static_Init and other "no-script" specials, but will that actually work?
Basically my overall goal is to be able to put portals all over the place without things getting too screwy. I was going to mess with Static_Init[1] and see if I could use it to get sky angle to render properly across portals.
But it looks like individual vertices can be moved around with this class, and I might even try "physically" rotating some geometry and putting in static portals.
[1] - It looks like this thing would be running at a point when it would be alright to use Static_Init and other "no-script" specials, but will that actually work?
- Graf Zahl
- Lead GZDoom+Raze Developer
- Posts: 49230
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: Could level init be hooked with zscript events?
Yes, it runs before static line specials get evaluated.
Re: Could level init be hooked with zscript events?
I'm having some trouble getting this to work.
Here's what I have right now:
I know that it's at least being parsed, because it will throw errors on type mismatches and so on.
I'm not sure it's ever being evaluated, though. Console.printf doesn't seem to work; should it work here?
This code should change the ceiling of the sector where the player spawns, but nothing happens. Maybe something's wrong with the code? What's the simplest thing I can do in my LevelCompatibility subclass to test if it's actually being evaluated?
Here's what I have right now:
Code: Select all
class RLP_LevelInit : LevelCompatibility
{
private static void Apply(Name checksum)
{
level.sectors[50].SetTexture(Sector.Ceiling,
TexMan.CheckForTexture("FLAT3", TexMan.Type_Flat));
}
}
I'm not sure it's ever being evaluated, though. Console.printf doesn't seem to work; should it work here?
This code should change the ceiling of the sector where the player spawns, but nothing happens. Maybe something's wrong with the code? What's the simplest thing I can do in my LevelCompatibility subclass to test if it's actually being evaluated?
Re: Could level init be hooked with zscript events?
The problem is the missing test for map checksum. Please note that you need to add comparison with it as a name, not as a string. The internal handler does this in switch statement.
Re: Could level init be hooked with zscript events?
@_mental_, thanks, do you happen to know where the C++ code is that does the special handling for LevelCompatibility subclasses? I feel like there's either something I'm not understanding, or some serious black magic going on here... is it really checking whether I checked a checksum or not inside that function, instead of just running it?
I tried this:
Unfortunately, it still never seems to fire.
That's the checksum for the map wad, as reported by md5sum. The script, the map wad and other lumps are in a pk3-style unzipped directory. I hope that's not what I need a checksum for; that would be impossible because the checksum itself would need to be included in the thing being checksummed.
Tested on 3.7.1 and latest nightly.
I tried this:
Code: Select all
class RLP_LevelInit : LevelCompatibility
{
protected void Apply(Name checksum)
{
switch (checksum)
{
case 'deb751282d80fd59f56ae0240aa2e22b':
{
console.printf("it worked");
level.sectors[50].SetTexture(Sector.Ceiling,
TexMan.CheckForTexture("FLAT3", TexMan.Type_Flat));
}
}
}
}
That's the checksum for the map wad, as reported by md5sum. The script, the map wad and other lumps are in a pk3-style unzipped directory. I hope that's not what I need a checksum for; that would be impossible because the checksum itself would need to be included in the thing being checksummed.
Tested on 3.7.1 and latest nightly.
Re: Could level init be hooked with zscript events?
User defined compatibility handler is present in devbuilds only.
You should use checksum calculated by mapchecksum CCMD.
You should use checksum calculated by mapchecksum CCMD.
Re: Could level init be hooked with zscript events?
Awesome, let me try that, thanks for your help 
...Alright, mapchecksum did the trick.
I have no idea how this works internally, though.
With the right checksum, both messages are printed to the console, but with the wrong checksum, neither one prints.
What's going on here? I'd like to avoid using checksums for my own maps if possible; I'd rather identify them by map name or level number or whatever.
---
Played with it a bit more. Apparently what's necessary for the function to fire is just that the checksum appears somewhere in the function. A statement containing only a string literal with the checksum in it will trigger it. It can be placed anywhere in the function, even at the end, after a return, where it would never execute.
Weird, right? Haven't found any way around having that string literal there. Anyway, I'll play around with it and maybe put in a feature suggestion for hooking it up to event handlers or similar later.

...Alright, mapchecksum did the trick.
I have no idea how this works internally, though.
Code: Select all
class Blah : LevelCompatibility
{
protected void Apply(Name checksum)
{
console.printf("its working....");
switch (checksum)
{
case 'goodchecksum':
console.printf("it worked");
}
}
}
What's going on here? I'd like to avoid using checksums for my own maps if possible; I'd rather identify them by map name or level number or whatever.
---
Played with it a bit more. Apparently what's necessary for the function to fire is just that the checksum appears somewhere in the function. A statement containing only a string literal with the checksum in it will trigger it. It can be placed anywhere in the function, even at the end, after a return, where it would never execute.
Code: Select all
class Blah: LevelCompatibility
{
protected void Apply(Name checksum)
{
console.printf("it works");
return;
'goodchecksum';
}
}