"How do I ZScript?"

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!
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!)
Locked
User avatar
Nash
 
 
Posts: 17512
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: "How do I ZScript?"

Post by Nash »

Ed the Bat wrote:What is the best way to check if a string variable is empty or not? if(variable!=null) throws an error.
Found within zscript/menu/optionitems.txt

Code: Select all

if (text.Length() == 0) text = "Unknown";
 
User avatar
Ed the Bat
Posts: 3060
Joined: Thu May 03, 2012 1:18 pm
Location: Maryland, US
Contact:

Re: "How do I ZScript?"

Post by Ed the Bat »

Indeed, the Length() function seems to be an excellent way to determine if a string is empty. Thanks, both of you!
User avatar
Nash
 
 
Posts: 17512
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: "How do I ZScript?"

Post by Nash »

Code: Select all

    override void Tick(void)
    {
        String s = "test";
        screen.DrawText (SmallFont, OptionMenuSettings.mFontColorValue,
            (screen.GetWidth() - SmallFont.StringWidth (s) * CleanXfac_1) / 2, screen.GetHeight() / 2, s,
            DTA_CleanNoMove_1, true);
        PlayerThink();
        Super.Tick();
    }
 
I'm trying to print this text from the PlayerPawn so I put it in his Tick, but the text on the screen flickers, like as if it's being drawn, then immediately erased, then drawn again.

How do I make the text stay up and look solid?
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: "How do I ZScript?"

Post by ZZYZX »

You cannot. And it's a bad idea to do it in Tick() and overall bind any drawing to actors.

Drawing should be performed every frame, at a very specific moment of it.
For that, wait for either event handlers or menus to be pulled/implemented.
Otherwise you can abuse subclassing Powerup class and using DrawPowerup method (see examples in gzdoom.pk3).

I blame Graf for ignoring my technical questions about structs and at the same time refusing to pull it without structs.
Graf, have fun observing people hack menus in order to draw things on player HUD :)
User avatar
Major Cooke
Posts: 8221
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town
Contact:

Re: "How do I ZScript?"

Post by Major Cooke »

You know, you're not exactly enticing him with that attitude to look into it.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: "How do I ZScript?"

Post by ZZYZX »

idk that was side and half-joke point in my post. Primary point was the response to Nash.
User avatar
Nash
 
 
Posts: 17512
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: "How do I ZScript?"

Post by Nash »

ZZYZX wrote:You cannot. And it's a bad idea to do it in Tick() and overall bind any drawing to actors.

Drawing should be performed every frame, at a very specific moment of it.
For that, wait for either event handlers or menus to be pulled/implemented.
Otherwise you can abuse subclassing Powerup class and using DrawPowerup method (see examples in gzdoom.pk3).

I blame Graf for ignoring my technical questions about structs and at the same time refusing to pull it without structs.
Graf, have fun observing people hack menus in order to draw things on player HUD :)
Okay understood about it currently not being available yet; I will wait for event handlers and menus.

As for the actual thing I'm doing though; that's bad eh? I wanted to make a text display that prints the name of the thing that the player is aiming at. So if I shouldn't put it inside the PlayerPawn tick, where should I put it? A custom ZScriptified HUD I imagine? Will I have access to whatever the player's aiming at from the HUD?
User avatar
hideousdestructor
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia
Contact:

Re: "How do I ZScript?"

Post by hideousdestructor »

I keep getting "VM execution aborted: tried to read from address zero." crashes from who knows where, randomly, whenever things get busy. I can go for very long stretches without running into the problem until it happens.

What's a good way to try to narrow this down? What does that message even mean, anyway?
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: "How do I ZScript?"

Post by ZZYZX »

It means you tried to do something to a variable that's actually null.
e.g.

Code: Select all

Actor a = null;
a.health = 1;
Would produce this error.

Is there no stack trace? Why is there no stack trace? (@Graf)
User avatar
Major Cooke
Posts: 8221
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town
Contact:

Re: "How do I ZScript?"

Post by Major Cooke »

There is a stack trace.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine
Contact:

Re: "How do I ZScript?"

Post by ZZYZX »

Judging by "how do I narrow this down" there is no stack trace in this case.
User avatar
Major Cooke
Posts: 8221
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: GZBoomer Town
Contact:

Re: "How do I ZScript?"

Post by Major Cooke »

There actually is below the vm argument execution after it's peformed. It points to the specific line.
User avatar
hideousdestructor
Posts: 9696
Joined: Sun Jan 04, 2004 5:37 pm
Preferred Pronouns: They/Them
Operating System Version (Optional): Debian Bullseye
Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia
Contact:

Re: "How do I ZScript?"

Post by hideousdestructor »

It does have that, but in this situation it keeps pointing to the following section of code which doesn't seem to refer to anything outside of the actor itself (and not, say, a line saying "a.health" or whatnot as I might expect) so I can only assume that the real problem is somewhere else in something else that the stack trace is somehow not picking up:

Code: Select all

//because "extend class Actor" doesn't work
class HDActor:Actor{
	void nexttic(){
		if(!CheckNoDelay()) return;
		if(tics!=-1){
			if(tics>0)tics--;
			while(!tics){
				if(!SetState(CurState.NextState)){
					return;
				}
			}
		}
	}
}
I recently had something similar that gave the same error that I did manage to fix by just rewriting the entire affected actor in ZScript from scratch, and didn't touch the above code at all, but comparing the before and after code now I still can't see what was causing the crash. EDIT: could be fixed by making sure the death state lasted at least 1 tic, whether explicitly or by using A_SetTics within an anonymous function. (Getting rid of the A_SpawnItemEx call but keeping it zero tics still crashed.)
User avatar
Xaser
 
 
Posts: 10774
Joined: Sun Jul 20, 2003 12:15 pm
Contact:

Re: "How do I ZScript?"

Post by Xaser »

Your real error is likely a few steps back in the stack trace. At some point, a function is being called on a null pointer. Das bad.

Without getting too much into the nitty-gritty, the bit to remember is that functions (e.g. nexttic()) are defined on the class, not on a particular instance of it. If you have a null HDActor variable and try to call nexttic() on it, the engine dutifully pulls the definition of nexttic() from the HDActor class and passes in the null pointer as 'self'. The engine doesn't actually blow up until you try an access a member of that null pointer -- e.g. trying to get CurState -- but the actual error occurred some time in the past.

This type of thing is called a "null pointer dereference," and while some languages explicitly throw an error message when you try and do so, ZScript doesn't because it would've involved adding a null check VM instruction to every single function call (lowering performance and whatnot). C++ also lets you shoot yourself in the foot in the same way, for interest's sake.

In cases like this, you may need to follow the VM stack trace a few steps backward to figure out where the nefarious null is, as it's probably one of the highlighted lines. Just not the "most recent."


[Post-mortem: this explanation is a bit layperson-y so there may be some wording that falls into the "there is technically something similar but more complex going on here" zone. plz ignore :< ]
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49252
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: "How do I ZScript?"

Post by Graf Zahl »

Xaser wrote: This type of thing is called a "null pointer dereference," and while some languages explicitly throw an error message when you try and do so, ZScript doesn't because it would've involved adding a null check VM instruction to every single function call (lowering performance and whatnot). C++ also lets you shoot yourself in the foot in the same way, for interest's sake.
Actually, ZScript guards every single pointer dereference, but when you call a function things are a bit different: The pointer is never dereferenced unless you call a virtual function - it's just being passed as a hidden function parameter, which prevents checking in the call instruction because it isn't part of that - the exception only gets triggered when the pointer actually gets used inside the called function.

The call stack trace is there for a reason - as you said, it isn't necessarily the innermost function that caused the problem but futher outward - so without this data, there's no way to tell what is wrong here.
Locked

Return to “Scripting”