"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!)
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49130
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: "How do I ZScript?"

Post by Graf Zahl »

The a part will be set to 255, so if you just need RGB you still need the mask. Without setting a to non-0, black blood would not be possible.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine

Re: "How do I ZScript?"

Post by ZZYZX »

Major Cooke wrote:Note to self, do NOT put a "Cvar" type variable on a player that's in the actor scope space!
Or mark it transient :)
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49130
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: "How do I ZScript?"

Post by Graf Zahl »

That would prevent a crash but it's not persistent. For caching the value it's ok but the code needs to be prepared to restore it if it gets lost.
User avatar
Major Cooke
Posts: 8193
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: "How do I ZScript?"

Post by Major Cooke »

Graf Zahl wrote:The a part will be set to 255, so if you just need RGB you still need the mask. Without setting a to non-0, black blood would not be possible.
Let me get this straight...

Code: Select all

Color bl = (bloodcolor & 0xffffff);
This translates to:

Code: Select all

// Where rr, gg, and bb are replaced with the appropriate mask clearance (I don't know what they are)
Color bl = (rr, gg, bb, 255);
Or is there some other kind of voodoo going on?

Bigger question: does the 'a' part determine how light or dark it gets? In particular I'm thinking for particles.
User avatar
krokots
Posts: 269
Joined: Tue Jan 19, 2010 5:07 pm

Re: "How do I ZScript?"

Post by krokots »

There is function ChangeTid(int newtid). Is it possible to make ChangeTidToHate(int newtid) ? I could use some other method other than Thing_Hate.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine

Re: "How do I ZScript?"

Post by ZZYZX »

Thing_Hate simply sets "target" and few actor flags.
Refer to this source file for details on what gets set: https://github.com/coelckers/gzdoom/blo ... .cpp#L1633

You can receive an actor from TID by using ActorIterator (woo, documented part of ZScript!)
User avatar
Nash
 
 
Posts: 17454
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: "How do I ZScript?"

Post by Nash »

krokots wrote:I could use some other method other than Thing_Hate.
Indeed. You can set the Target field directly in ZScript.

Here are all the fields you can play with:

Code: Select all

    native Actor Target;
    native Actor Master;
    native Actor Tracer;
    native Actor LastHeard;
    native Actor LastEnemy;
    native Actor LastLookActor;
from zscript/actor.txt

Using TIDs for enemy behavior and AI scripting is an obsolete concept and shouldn't be brought over into ZScript. Here, you have direct access to a lot of the juicy internal variables, so manipulate those directly instead.
User avatar
Ed the Bat
Posts: 3060
Joined: Thu May 03, 2012 1:18 pm
Graphics Processor: nVidia with Vulkan support
Location: Maryland, US

Re: "How do I ZScript?"

Post by Ed the Bat »

Ed the Bat wrote:Am I able to change type-specific DamageFactors for an actor, so as to modify only how much damage certain types, or "elements", will do to the actor?
I notice there's a function called ApplyDamageFactors, which is used by PowerProtection. Would this be useful to me? As far as I know, PowerProtection can't overwrite an actor's DamageFactors; it just applies multiplication or division to them.
User avatar
ZZYZX
 
 
Posts: 1384
Joined: Sun Oct 14, 2012 1:43 am
Location: Ukraine

Re: "How do I ZScript?"

Post by ZZYZX »

Nash wrote:Using TIDs for enemy behavior and AI scripting is an obsolete concept and shouldn't be brought over into ZScript. Here, you have direct access to a lot of the juicy internal variables, so manipulate those directly instead.
Not when you need to setup it in a map, which is what I assume he's trying to do. Otherwise yes, using TIDs for general-purpose stuff is bad here.
Ed the Bat wrote:
Ed the Bat wrote:Am I able to change type-specific DamageFactors for an actor, so as to modify only how much damage certain types, or "elements", will do to the actor?
I notice there's a function called ApplyDamageFactors, which is used by PowerProtection. Would this be useful to me? As far as I know, PowerProtection can't overwrite an actor's DamageFactors; it just applies multiplication or division to them.
ApplyDamageFactors takes damage amount and type and processes them by main and damagetype-specific factors, as well as potential armour factors and such. It's informational and doesn't change anything.
User avatar
Nash
 
 
Posts: 17454
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia

Re: "How do I ZScript?"

Post by Nash »

Of course... for map scripting, TIDs are still the best way. :D

Just no more cringey DECORATE spaghetti and A_Jumps and GiveInventory-in-place-as-variables for generic enemy AI pls
User avatar
Ed the Bat
Posts: 3060
Joined: Thu May 03, 2012 1:18 pm
Graphics Processor: nVidia with Vulkan support
Location: Maryland, US

Re: "How do I ZScript?"

Post by Ed the Bat »

I see. So ApplyDamageFactors is not the answer, then. Thanks.
User avatar
krokots
Posts: 269
Joined: Tue Jan 19, 2010 5:07 pm

Re: "How do I ZScript?"

Post by krokots »

ZZYZX wrote:
Nash wrote:Using TIDs for enemy behavior and AI scripting is an obsolete concept and shouldn't be brought over into ZScript. Here, you have direct access to a lot of the juicy internal variables, so manipulate those directly instead.
Not when you need to setup it in a map, which is what I assume he's trying to do. Otherwise yes, using TIDs for general-purpose stuff is bad here.
I am making a mod in which two groups of monsters fight (kind of like hate arena...but waaaay more complex...spells and everything). So I think they must have TID's to hate each other. That's why I wondered about tidtohate.
User avatar
Major Cooke
Posts: 8193
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: "How do I ZScript?"

Post by Major Cooke »

ZZYZX wrote:
Nash wrote:Using TIDs for enemy behavior and AI scripting is an obsolete concept and shouldn't be brought over into ZScript. Here, you have direct access to a lot of the juicy internal variables, so manipulate those directly instead.
Not when you need to setup it in a map, which is what I assume he's trying to do. Otherwise yes, using TIDs for general-purpose stuff is bad here.
Obsolete my ass! Team-based combat situations like this EXCEL with them. (Turn your sound down. I'm warning you!)



These guys search by TID and DesignatedTeam. (I changed my DesignatedTeam and then they started treating me hostile.)

In situations like this, TID searching can gratuitously speed up the game since it helps limit the search, via using ActorIterators. And if I introduce islands, I can make entities above said island that eclipse the whole regions and the lil' dudes can then search just that entity for more lil' dudes of the same kind that are on different teams.

EDIT: The grenades and rockets also have TIDs which allows them to run away from threats like that.
User avatar
krokots
Posts: 269
Joined: Tue Jan 19, 2010 5:07 pm

Re: "How do I ZScript?"

Post by krokots »

I think using Thing_Hate every time changes haters targets and messes the fight. That is why I want to avoid using this middle battle. If there would be a simple function changing tidtohate, that would be perfect.
BTW, is it possible to make a custom A_Look which only target specified tid's?
Last edited by krokots on Fri Mar 03, 2017 2:54 pm, edited 1 time in total.
User avatar
Major Cooke
Posts: 8193
Joined: Sun Jan 28, 2007 3:55 pm
Preferred Pronouns: He/Him
Location: QZDoom Maintenance Team

Re: "How do I ZScript?"

Post by Major Cooke »

That's why you check to see if you have no target or the target is dead first.

Code: Select all

if (!target || target.health > 0)
{
    Thing_Hate(...);
}
And because of your ninja edit, yes, it's fully possible to make your own kind of look function. Bear in mind, mine doesn't do natural monster searching -- it only goes by TIDs.

Code: Select all

	//==========================================================================
	// Actor Search
	//==========================================================================
	
	void SearchForActors(Class<Actor> Specific = null, bool getClosest = false)
	{
		if (health < 1)	return;
		// Search for high priority threats first.
		
		static const int ActorID[] =
		{
			TID_SoulDestroyer,
			TID_Grenade,
			TID_Rocket,
			TID_Darwinian,
			TID_Darwinian
		};
		static const Class<Actor> ActorList[] =
		{
			"SoulDestroyer",
			"DarwinianGrenade",
			"DarwinianRocket",
			"DarwinianPlayer",
			"Darwinian"
		};
		
		static const int ActorDistance[] =
		{
			512,
			256,
			256,
			384,
			384
		};
		
		int size = ActorList.Size();
		for (int g = 0; g < size; g++)
		{
			// Do not waste effort searching for things we don't care about. This
			// is especially useful for constantly checking for grenades and/or
			// rockets, since without this, lots of slowdowns can occur.
			if (Specific && ActorList[g] != Specific)
				continue;
				
			// See ZMisc.txt
			int id = 					ActorID[g];
			double dist = 				ActorDistance[g];
			Class<Actor> cname = 		ActorList[g];
			
			
			let it = ActorIterator.Create(id, cname);
			Actor mo;
			while (mo = it.Next())
			{	
				if (!mo.TID || mo == self || mo.DesignatedTeam == DesignatedTeam || mo.bINVISIBLE)
					continue;
					
			//	if (mo.GetClass() != "DarwinianGrenade" && isTeammate(mo))
			//		continue;
				
				double distCheck = Distance2D(mo);
				
				if (distCheck > dist)
					continue;
			
				if (mo.tid == TID_Darwinian && !(mo is "PlayerPawn") && !(mo is "Darwinian"))
					continue;
			
				//if (!CheckSight(mo, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY))
				//	continue;
				
				if (closestDist < 0.0 || !closest)
				{
					closest = mo;
					closestDist = dist;
				}
				
				if (distCheck < closestDist)
				{
					closest = mo;
					closestDist = dist;
				}
				if (!getClosest)
					return;
				
			}
		}

Return to “Scripting”