"How do I ZScript?"

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!)
Locked
User avatar
Matt
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: ZScript-only "How do I..." thread

Post by Matt »

Everything's a mess so it might take longer for me to extract something workable than to figure out that what I'm trying is impossible.

EDIT: turns out the target was being reset with each A_Chase call. Putting the A_Chase before the target switch helps a bit. Is there a way to replicate all the movement/dropoff/etc. checks and move towards a specific actor/point without all the extras A_Chase does?


How do I return an actor's class name?
Last edited by Matt on Sun Jan 29, 2017 12:42 pm, edited 1 time in total.
User avatar
Ed the Bat
Posts: 3060
Joined: Thu May 03, 2012 1:18 pm
Graphics Processor: nVidia with Vulkan support
Location: Maryland, US
Contact:

Re: ZScript-only "How do I..." thread

Post by Ed the Bat »

GetClassName()
User avatar
Matt
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: ZScript-only "How do I..." thread

Post by Matt »

Thanks!

(Added it to the big list... on that note, is there any particular order in which these are listed?)
User avatar
Gutawer
Posts: 469
Joined: Sat Apr 16, 2016 6:01 am
Preferred Pronouns: She/Her

Re: ZScript-only "How do I..." thread

Post by Gutawer »

So in A Boy and His Barrel ( viewtopic.php?f=19&t=53399 ), I recently implemented a carrying mechanic which Jimmy noticed has the annoying side effect of Violet not triggering any "Actor Hits Floor" things when moved into a sector as it is done with a warp - is there a way to force an actor to trigger these actions regardless of how they moved into the sector (moved "naturally", teleported in, warped in, etc.) as long as their Z pos is equal to their Floor Z pos? If it comes to it I can probably do some hack with setting the Z pos slightly above the floor, but i'd rather avoid hacks when possible.
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm
Contact:

Re: ZScript-only "How do I..." thread

Post by ibm5155 »

Ok I have my RayTracer and that's an acs+decorate salad code and I wanted to convert it into 100% zscript.
The thing is, in acs CheckSight can work with a source and a destination tid, while in decorate (And I belie in zscript) I can only CheckSight with the object and the player.
Do I need to change the pointers every time before I call the a_CheckSight function?
Also, is there a way to make an extern like var in c where you can have access to a global var from acs?

Here's the acs script that I'm converting to zscript

Code: Select all

script 4 (int tid) //check if visible by the tid
{
	switch(tid)
	{
		case 45:
		case 5:
			if(checksight(0,102,0)==true)
			{
				SetResultValue(true);
			}
			else
			{
				SetResultValue(checksight(0,103,0));								
			}
		break;

		case 48:
		case 44:
		case 2:
			SetResultValue(checksight(0,101,0));				
		break;


		case 1:
			SetResultValue(checksight(0,100,0));				
		break;
		
		case 68:
			SetResultValue(checksight(0,67,0));						
		break;

	}
}
script 5 (int tid) // check if player is under a specific room 
{
	switch(tid)
	{
		case 5:
		case 45:
			SetResultValue(camera_sector == 2);			
		break;

		case 48:
		case 44:
		case 2:
			SetResultValue(camera_sector == 1);			
		break;

		case 1:
		SetResultValue(true);
		break;
		
		case 68:
			SetResultValue(camera_sector == 3);
		break;
		
	}
}

and the decorate

Code: Select all

Actor RayCast 32766
{
	//$Category RayCast_Fixed
	-SOLID
	+NOGRAVITY
	+NOCLIP
	+INVISIBLE
	+NOINTERACTION 
	height 4.0
	Scale 0.5
	var int user_RayState;//true = is lighting, false is shadowing
	States
	{
	Spawn:	
		C000 A 1 
		C000 A 0 A_SetUserVar("user_RayState",1)
		C000 A 1 A_RearrangePointers(AAPTR_NULL, AAPTR_PLAYER1, AAPTR_DEFAULT)
		goto "FindRay"
		
	"NoShadow":
		C000 A 1 // LIGHT
	Goto "FindRay"

	"Shadow":
		C001 A 1  // SHADOW
	goto "FindRay"

	"StartShadow":
		C001 D 1
		C001 C 1 A_SetUserVar("user_RayState",0)
		C001 B 1
	Goto "Shadow"

	"EndShadow":
		C001 B 1
		C001 C 1  A_SetUserVar("user_RayState",1)
		C001 D 1
	Goto "NoShadow"
	
	"SleepRay":
		C000 A 50 // I better replace this one with some thing_deactivate
		goto "NoShadow"
	"FindRay":
//PART 1: OPTIMIZE THE CODE, GET A SOLUTION TO KNOW IF THE RAY SHOULD BE CHECKED OR NOT
//THE RAY COULD BE CHECKED IF THE RAY IS OVER THE PLAYER's VIEWPOINT OR OTHER TRICKS...
//solution 7:
		TNT1 A 0 A_Jumpif(Acs_executewithresult(5,tid)==false,"SleepRay")
//=============		
//PART2: MAIN RAY CODE, CHECK IF THE RAY WAS HIT BY A LIGHT SOURCE
//check if was hit
//METHOD 2:
//	TNT1 A 0 A_jumpiftargetinlos(3,360,JLOSF_TARGETLOS | JLOSF_CHECKMASTER  ,0,0)
//	TNT1 A 0 A_jump(256,"See")
	TNT1 A 0 A_Jumpif(Acs_executewithresult(4,tid)==true,3) //check all the light sources
	TNT1 A 0 A_jumpif(user_RayState == 1,"StartShadow") // make light shade effect
	TNT1 A 0 a_jump(256,"Shadow") //else, this ray is already shadow
	TNT1 A 0 A_jumpif(user_RayState == 0,"EndShadow") // make light shade effect

	Goto "NoShadow"
	}
}
and also my first try with zscript where I try to get those two codes and mix it together

Code: Select all

struct RayEnum
{
  enum RayEnum
  {
	NoLightSource,
	WithLightSource
  };
}


class Z_RayCast : Actor 22766
{
	//$Category RayCast_Fixed
	Default
	{
	-SOLID
	+NOGRAVITY
	+NOCLIP
	+INVISIBLE
	+NOINTERACTION 
	RayEnum user_RayState = NoLightSource;
	}
	States
	{
		Spawn:	
		C000 A 1 
		C000 A 1 A_RearrangePointers(AAPTR_NULL, AAPTR_PLAYER1, AAPTR_DEFAULT);
		goto "FindRay"
		
		"NoLightSource":
		{
			C000 A 1
			Goto "FindRay"
		}
		
		"WithLightSource":
		{
			C001 A 1
			Goto "FindRay";
		}
		
		"StartShadow":
		{
			C001 D 1
			C001 C 1
			{
				user_RayState = RayEnum.NoLightSource;
			}
			C001 B 1
			Goto "NoLightSource";
		}
		"EndShadow":
		{
			C001 B 1
			C001 C 1
			{ 
				user_RayState =RayEnum.WithRaySource;
			}
			C001 D 1
			Goto "WithLightSource";
		}
		"Sleep"
		{
			C000 A 50
			goto "FindRay";
		}

		"FindRay":
		{
			TNT1 A 0
			{
				if(IsPlayerNearMySector() == false)
				{
					goto "Sleep"
				}
				else if(CheckVisibility() == RayEnum.WithRaySource)
				{
					if(user_RayState == RayEnum.NoRaySource)
					{
						goto "EndShadow";
					}
					else
					{
						goto "WithLightSource";
					}
				}
				else // RayEnum.NoRaySource
				{
					if(user_RayState == RayEnum.WithRaySource)
					{
						goto "StartShadow";
					}
					else
					{
						goto "NoLightSource";
					}
				}
			}
			Goto "NoShadow"
		}
	}
	
	bool CheckVisibility()
	{
		// is there a switch struct for zscript?
		if(tid == 5 || tid == 45)
		{
			if(A_checksight(102) == false)// where 102 is a light source tid
			{
				return A_checksight(103);
			}
			else
			{
				return true;
			}
		}
		else if(tid == 48 || tid == 44 || tid == 2)
		{
			return A_checksight(101);
		}
		else if(tid == 1)
		{
			return A_checksight(100);
		}
		else if(tid == 68)
		{ 
			return A_checksight(67);
		}		
	}
	
	extern int camera_sector; // acs global var
	
	bool IsPlayerNearMySector()
	{
		if(tid == 5 || tid == 45)
		{
			return camera_sector == 2;			
		}
		else if(tid == 48 || tid == 44 || tid == 2)
		{
			return camera_sector == 1;
		}
		else if( tid == 1)
		{
			return true;
		}
		else if( tid == 68)
		{
			return camera_sector == 3;
		}
	}
}
Why I'm not using a jump if target in los?because it's slow, think about 3000 objects calling it every tic, the checksight acs version was alot faster, but I do belive that by calling 2000x acs calls with a return will also drop the performance alot, so maybe a solution 100% made in zscript will work better.
User avatar
monkeybtm6
Posts: 115
Joined: Thu Dec 18, 2014 9:03 pm

Re: ZScript-only "How do I..." thread

Post by monkeybtm6 »

This may have already been asked somewhere but i cant find it. Can you set another actors properties in zscript? Like an ACS code with SetActorProperty. Trying to increase the players spawnhealth.
User avatar
Agentbromsnor
Posts: 265
Joined: Wed Mar 28, 2012 2:27 am

Re: ZScript-only "How do I..." thread

Post by Agentbromsnor »

Major Cooke wrote:Try pming zombiekiller about it directly. I don't have the file anymore myself.
I'm sorry for the delayed reply, but... What? Who is zombiekiller, and what do I need to contact him for? What file? h666_isolated.pk3? Reading someone else's code can be very difficult, especially when it's in C-style, so I need a lot more to go on than that I'm afraid.
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm
Contact:

Re: ZScript-only "How do I..." thread

Post by ibm5155 »

ok I'm evolving...
So, I found that in zscript has the CheckSight function just like the acs one, but instead of requesting a tid as input it request an actor.
Soooo, should I just pass the tid and it's oj or do I need to get some actor pointer from the given tid? if yes, how?

EDIT:


ALLLSO.
How do I use enums, and how to convert bool to enum?
like

Code: Select all

class Z_RayCast : Actor
{
	//$Category RayCast_Fixed
	
enum RayEnum
  {
	NoLightSource,
	WithLightSource
  };
...
	RayEnum user_RayState;
...
	States
	{
		Spawn:	
		C000 A 1; 		
		C000 A 1
		{
			camera_sector = 0;
			user_RayState = /*RayEnum.*/NoLightSource;
               }
            user_RayState = CheckSight(ptr_LightSrc,0);
...

[code][/s]
got it, well, I prefer the C# style of enums but ansi c is ok
User avatar
Matt
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: ZScript-only "How do I..." thread

Post by Matt »

The function says "bool CheckSight(Actor target, int flags = 0);"

which means that you can do something like (assuming it's the player calling all these)

//who knows what this does
CheckSight(target);

//OR - see master and grovel
if(CheckSight(master)) A_PlaySound("sub/grovel");

//OR - if a point is not visible 1 second away, start braking
actor loscheck=Spawn("Blood",pos+vel*35);
if(!CheckSight(loscheck)) vel*=0.9;
loscheck.destroy();

I don't know how to search for an actor using a TID in ZScript, but basically you can use any function that outputs an "actor" and checksight using that.
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm
Contact:

Re: ZScript-only "How do I..." thread

Post by ibm5155 »

those CheckSight are going to be called by a specific actor that simulates a raytracing engine.
so lets say each dot object over a map needs to check if any kind of light source is visible or not.
I have all the light source tids, but I really don't know what could I do with that :|
User avatar
Matt
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: ZScript-only "How do I..." thread

Post by Matt »

I think I see what you mean. Basically we need a way to check LOS between two actors.

So far I've been using one or more of A_JumpIfTargetInLOS, A_JumpIfInTargetLOS and A_CheckLOF, but all of those have some limitations and screwiness and I'd really like to see some way to check if there's anything blocking a line between two arbitrary points and if so what it is.

Yes, I would like an answer for this too.


(Also, since I'm posting questions anyway: what's the best way (i.e., least processing required) to get all monsters in an area to
1. store its target in an internal variable;
2. target the activator; and
3. change a flag?
The area can be a sphere or a cube, I don't really care.)
User avatar
Xaser
 
 
Posts: 10772
Joined: Sun Jul 20, 2003 12:15 pm
Contact:

Re: ZScript-only "How do I..." thread

Post by Xaser »

Vaecrius wrote:I think I see what you mean. Basically we need a way to check LOS between two actors.
From the way this is phrased, it seems like you've already answered your own question a post ago: CheckSight is the function you want. The following function will indeed cause the actor to grovel if its target is within line-of-sight:

Code: Select all

if(self.CheckSight(self.target)) {
    self.A_PlaySound("sub/grovel");
}
(I've added the self. pointers to be explicit; technically they're not needed but it's a good habit to get into).

Dunno if you're meaning to ask a different/more-specific question; if so, that's a different story.

Regarding TIDs, unless you're messing with map stuff, it's best to try and stop thinking in terms of TIDs; you can now pass pointers to actors around, and it's likely your specific problem can be solved more elegantly that way instead. For helpfulness' sake though, if you can't avoid a TID (e.g. stepping stone while porting old ACS-based logic or doing map things, as mentioned), you'll need to use an ActorIterator to loop through everything with a given TID (it's a looping action since you can have more than one thing with the same TID, so you gotta be explicit about it).
Vaecrius wrote:(Also, since I'm posting questions anyway: what's the best way (i.e., least processing required) to get all monsters in an area to
1. store its target in an internal variable;
2. target the activator; and
3. change a flag?
The area can be a sphere or a cube, I don't really care.)
You'll want a BlockThingsIterator -- this loops through all actors within a given radius (excluding any actors with +NOBLOCKMAP). You'll need to do additional checks to see if it's a monster (and if it's alive, etc.), but fortunately, I happened to write almost exactly this code a couple of days ago, so here's a handy example. Replace the ArgNeuralStunner spawn bit with the logic described and you'll be good to go.

Hope this puts you on the right track. ;)
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm
Contact:

Re: ZScript-only "How do I..." thread

Post by ibm5155 »

I belive you gave me a light xase :D
...

Now, I have a question about this:

Code: Select all

		"Sleep":
			C000 A 50 a_log("B");
			goto FindRay;

		"FindRay":
			TNT1 A 0
			{
				if(IsPlayerNearMySector() == false)
				{
					A_Log("A");
					a_jump(256,"Sleep");
					A_Log("C");
				}
                         }
...

I see "A" and after "C" but not "A" "B", what's going on? a_Jump is not supported in zscript? (before there was a goto there but it looks like zscript doesnt like goto inside ifs.
So what should I use to replace the a_jump/goto inside the code?
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49067
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: ZScript-only "How do I..." thread

Post by Graf Zahl »

Why are your labels quoted? That doesn't work and will make the quotes part of the label.
User avatar
ibm5155
Posts: 1268
Joined: Wed Jul 20, 2011 4:24 pm
Contact:

Re: ZScript-only "How do I..." thread

Post by ibm5155 »

Oh I don't need to do like the decoate label style...
I also found this, but with the return before the a_jump, I get this error message:
"
Script error, "Ray.pk3:actors/z_ray/raycaststatic.txt" line 69:
Return type mismatch

Execution could not continue.

1 errors while parsing DECORATE scripts
"
since I'm noob at this language, I'm kinda lost :shrug:


EDIT: return from what I saw, the return should be in the last line inside the anonymous function (It's "sad" because I waited for some c style (or even acs) where you can return on the mid of the code)
Locked

Return to “Scripting”