using variables in zscript without A_setuservar

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
bimshwel
Posts: 702
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced

using variables in zscript without A_setuservar

Post by bimshwel »

I am trying to make sense of the zscript basics so i can, among other things, stop using a_setuservar so that the game stops griping about that particular issue when I start it. But this sort of thing is very difficult for me, since I want to do one specific thing that I already know how to do in decorate and never seems to be strictly what the examples are covering. I try to adapt based on what IS covered and on this occasion am not succeeding. I have been told I can "access variables directly" in zscript but HOW to do that remains unclear, even when starting from other people's code.

In this example, I want the creature to use alternate attack, hop, and hopping-attack frames IF the creature is in the second half of its walk state, and that is all.
so far my attempts either go to the alternate frames regardless of the walk state or the game doesn't start at all. Presumably I only need one instance of the variable usage corrected and then I can fix the other two the same way, so I only included the first


See: ZIPw g 0 { let eempfeet = 1; //i only recently added the "let" but it didn't change anything } zipw gghhaabb 2 { A_Chase(); Return A_CheckNoGround("hopdown", "hopup", random(24, 48)); } goto midsee; midsee: zipw c 0 { let eempfeet = 2; } ZIPw CCddeeff 2 { A_Chase(); Return A_CheckNoGround("hopdown2", "hopup2", random(24, 48)); } goto see; Melee: ZIPw a 0 { if (eempfeet = 2); { return ResolveState("otherway"); } else { return 0; } } //this causes an error, only the latest of many things I have tried // //[and then the right-foot forward attack goes here; it is irrelevant for this question and eats up a lot of space] GoTo See; otherway: //[the same attack with left-foot graphics goes here] //as stated earlier, when my code attempts don't crash the game i only get the left foot version, but that at least means SOMETHING is happening GoTo midSee;
also I am using 1 and 2 right now for the variable because 0 and 1 weren't working and i remembered reading something about 0 sometimes meaning not quite what i think it does. i really only need this to be on or off, true or false, but i have other old decorate variables with more than two modes
thank you for any insight into this!
Proydoha
Posts: 36
Joined: Thu Jan 21, 2016 2:25 am

Re: using variables in zscript without A_setuservar

Post by Proydoha »

Look at example below:

Code: Select all

version "4.10"

class Test : Actor
{
	string columnColor;

	Default
	{
		Radius 16;
		Height 40;
		+SOLID;
	}
	
	States
	{
		Spawn:
			TNT1 A 0
			{
				columnColor = "green";
			}
			COL2 A 15;
			TNT1 A 0
			{
				columnColor = "red";
			}
			COL4 A 15;
			loop;
	}
	
	override void Tick()
	{
		Super.Tick();
		console.printf("This column is "..columnColor);
	}
}
I've declared a new field with name "columnColor" with the type "string" inside of a class "Test"
If you'll run this code you'll see that every tick of this actor's life the value of a "columnColor" field is printed into console and you can see how its value is changed inside of this actor's states.

When you write "let" you declare a new variable.
When you write "let" the type of the variable is inferred from its value.

Also in your expression here there are two mistakes at once:

Code: Select all

if 	  (eempfeet = 2); 
				{
					 return ResolveState("otherway");
				}
Mistake #1 - semicolon on the line with "if" statement.
Take a look at this example:

Code: Select all

bool condition = true;
if (condition)
{
	console.printf("Correct condition");
}

bool incorrectCondition = false;
if (incorrectCondition);
{
	console.printf("Incorrect condition");
}
Both lines "Correct condition" and "Incorrect condition" will be printed in this example.
It happens because when condition in if statement is true the statement located after it will be executed. And if you want more than one statement - you put them inside of a curly braces. However "the statement located after it" in second case ends with a semicolon and statements grouped by curly braces are no longer part of it. ZScript even puts yellow warning message into a console:"Empty if statement"

Mistake #2:
When you write "eempfeet = 2" you assign "2" to variable "eempfeet". And act of assigning (I think) always resolves to "true".
If you want to compare them instead you need to use == , like this: eempfeet == 2
User avatar
bimshwel
Posts: 702
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced

Re: using variables in zscript without A_setuservar

Post by bimshwel »

I was trying to assign 2 to it, but then assign 1 to it afterward, and alternate between them.
I HAVE been trying to cut back on things that the console complains about but doesn't abort the game over so that I might notice ones that are more important. I finally got rid of all the "truncation of floating point" whatever, apparently largely caused by me using numbers like "0.8," after you mentioned if statement warnings, and yes now I do see them! Hopefully I can make further progress from there.
User avatar
bimshwel
Posts: 702
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced

Re: using variables in zscript without A_setuservar

Post by bimshwel »

I removed the if's semicolon and added a second equals sign like so
Melee: if (eempfeet == 2) { return ResolveState("otherway"); }
but now I get a "unexpected '==''" error. The game does not like a single '=' either.

if (eempfeet == 2) { goto otherway; }
this makes it worse. There seems to be something very fundamental that I am missing.
if (eempfeet == 2) goto otherway;
this one the game REALLY hates
Jarewill
 
 
Posts: 1645
Joined: Sun Jul 21, 2019 8:54 am

Re: using variables in zscript without A_setuservar

Post by Jarewill »

You still need to specify a frame and put that code inside that frame for it to work, like so:

Code: Select all

     Melee:
				TNT1 A 0
				{
					if 	  (eempfeet == 2)
					{
					return ResolveState("otherway");
					}
					return ResolveState(null); //This is needed to prevent a return type mismatch
				}
Might be worth also noting that for this case you can also use A_JumpIf:
TNT1 A 0 A_JumpIf(eempfeet == 2, "otherway");
Proydoha wrote: Sat May 20, 2023 7:30 pm And act of assigning (I think) always resolves to "true".
Actually what is happening is that first it assigns and then it compares.
If you just write if(variable) then it will check if it's a non-zero value.
if(variable = 2) will pass, but if(variable = 0) will not.
User avatar
bimshwel
Posts: 702
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced

Re: using variables in zscript without A_setuservar

Post by bimshwel »

Thank you, you saved me again! ah ha that resolvestate null, I know I tried that somewhere, I just could not input it properly. It starts to become abstract to me at some point, along with the semi colon and bracketing shenanigans, I forget that they are all part of the same bit, probably why I wondered if attaching it to a frame was necessary.
I don't believe I knew about a_jumpif even though one of the parts I omitted, a silly jump-kicking attack, uses a_jumpifcloser.

although having come to this point, is it possible to have jumpifcloser treat vertical distance differently? I see a way to disable z checking entirely, which I do not think is what I want, unless I can run two jumpifclosers and the other ONLY checks z. Right now the beasts keep trying to jump kick even if i float where they can't hit. my cheap fix is to have a 1 in 4 chance of them switching to a conventional projectile attack if the kick misses and they still have a line-of-sight toward their targets. I also see a way to "get distance" but am not clear what to do with the distance once I get it.

like A_JumpIf(targetz <= 48)
i think
Jarewill
 
 
Posts: 1645
Joined: Sun Jul 21, 2019 8:54 am

Re: using variables in zscript without A_setuservar

Post by Jarewill »

You could use Distance3D to retrieve the distance to the target in 3D, but I'm not sure if it would be any different than A_JumpIfCloser.
If you just want to compare Z positions of both actors, you could use this function:

Code: Select all

	state A_JumpIfDiffZ(double difference, statelabel label){
		If(target){
			double dist = abs(abs(self.pos.z)-abs(target.pos.z));
			If(dist <= difference){
				Return ResolveState(label);
			}
		}
		Return ResolveState(null);
	}
Throw it into your monster base class and you will be able to use it on any monster.
The use case is A_JumpIfDiffZ(48, "State2"), which will jump to State2 if the Z difference between both the actor and its target is smaller or equal to 48.
It is late where I am and I am very tired, so this is the best I could come up with. I swear I will wake up in the morning and realise that I could have easily used some built-in function instead of this.
User avatar
bimshwel
Posts: 702
Joined: Tue Jul 15, 2003 5:15 pm
Location: misplaced

Re: using variables in zscript without A_setuservar

Post by bimshwel »

Ha, another good one! a bit funny since the game doesn't differentiate between above or below but that still leaves a lot to work with and sometimes funny is good. It almost feels like you are my underappreciated co-author, though I make sure to mark all the code with where or who I got it from. At least recently I have been doing that.

Return to “Scripting”