"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
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 »

Gutawer wrote:What's the cleanest way to send out a hitscan from a position in 3d space? Spawning an actor to send out the hitscan seems to work nicely, but I can't figure out how to make it transfer the target to the actor that is "supposed" to have sent out the hitscan.
Is the target supposed to be the thing hit by the bullet? If so, you can do this one of two ways:

1. Use LineAttack in conjunction with passing an FTranslatedLineTarget struct.
Check to see if the struct's "linetarget" exists.

Code: Select all

// returned by AimLineAttack.
struct FTranslatedLineTarget
{
	Actor linetarget;
	double angleFromSource;
	double attackAngleFromSource;
	bool unlinked;	// found by a trace that went through an unlinked portal.
	
	native void TraceBleed(int damage, Actor missile);
}
--- Or ---

2. Give the puff +HITTRACER, or HITMASTER flag, in addition to +PUFFGETOWNER. The puff will then set the entity hit as its own tracer/master, which the puff can then transfer that to the target pointer, which is the one who shot the bullet.

Method 1 would be best -- you can offset this hitscan along the Z axis as well.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: "How do I ZScript?"

Post by Apeirogon »

Can someone take my hand and lead me through process of creating custom property?
I want armor which:
If damage lower than yield limit armor will deflect all damage
If damage higher than yield limit, but smaller than strength limit it will damaged only at 1 point of armor
If damage higher than strength limit it will damaged to x point of armor, where x=round down((incoming damage)/(strengh limit))

So i write

Code: Select all

class hard_armor : basicarmorpickup
{
	int yield_limit;
	property hard_armor_yield_limit: yield_limit;
	
	int strength_limit;
	property hard_armor_strength_limit: strength_limit;

	Default
	{
    Armor.SaveAmount 600;
    Armor.SavePercent 0;
    Armor.MaxFullAbsorb 0;
    hard_armor.hard_armor_yield_limit: 15;
    hard_armor.hard_armor_strength_limit: 40;
	}
States
	{
	Spawn:
		arm2 A 6;
		arm2 b 6 bright;
	loop;
	}
}
And....what next?
ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: "How do I ZScript?"

Post by ZippeyKeys12 »

Override the Use function in the armor

Code: Select all

   //===========================================================================
	//
	// ABasicArmorPickup :: Use
	//
	// Either gives you new armor or replaces the armor you already have (if
	// the SaveAmount is greater than the amount of armor you own). When the
	// item is auto-activated, it will only be activated if its max amount is 0
	// or if you have no armor active already.
	//
	//===========================================================================

	override bool Use (bool pickup)
	{
		let armor = BasicArmor(Owner.FindInventory("BasicArmor"));

		// This should really never happen but let's be prepared for a broken inventory.
		if (armor == null)
		{
			armor = BasicArmor(Spawn("BasicArmor"));
			armor.BecomeItem ();
			Owner.AddInventory (armor);
		}
		else
		{
			// If you already have more armor than this item gives you, you can't
			// use it.
			if (armor.Amount >= SaveAmount + armor.BonusCount)
			{
				return false;
			}
			// Don't use it if you're picking it up and already have some.
			if (pickup && armor.Amount > 0 && MaxAmount > 0)
			{
				return false;
			}
		}
		
		armor.SavePercent = clamp(SavePercent, 0, 100) / 100;
		armor.Amount = SaveAmount + armor.BonusCount;
		armor.MaxAmount = SaveAmount;
		armor.Icon = Icon;
		armor.MaxAbsorb = MaxAbsorb;
		armor.MaxFullAbsorb = MaxFullAbsorb;
		armor.ArmorType = GetClassName();
		armor.ActualSaveAmount = SaveAmount;
		return true;
	}
}
And PlayerPawn's Damage(I don't remember the name) function to follow what ever rules its supposed to based on the items you add to it. I'm not sure but you may be able to access it directly from the variable?
Last edited by ZippeyKeys12 on Sun Nov 05, 2017 10:39 am, edited 1 time in total.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: "How do I ZScript?"

Post by Apeirogon »

I try make monster with custom hitbox area.
The problem is that actor which embody parts of body much smaller than hitbox of desired monster, say imp. I must, and wish, insert all body part inside of hitbox that master-imp. But it make him completely unreachable for attacking, since all attack blocks by hitbox of that imp.

I already brute force all available combinations of flag and actor property in CanCollideWith without any satisfying result.
Or master-imp dont let pass punch, or hitscan, or it dont block anything included player and other walking actor.

Now I try make it with infinitesimal radius and height. Thats works, body part can be wounded without problem, but monster can seep through any gap in the wall, door and other holes. How make it stop a_chase through hole, if volume for a_warp-ing body part actor is not enough?
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: "How do I ZScript?"

Post by Apeirogon »

ZippeyKeys12 wrote:Override the Use function in the armor

Code: Select all

   //===========================================================================
	//
	// ABasicArmorPickup :: Use
	//
	// Either gives you new armor or replaces the armor you already have (if
	// the SaveAmount is greater than the amount of armor you own). When the
	// item is auto-activated, it will only be activated if its max amount is 0
	// or if you have no armor active already.
	//
	//===========================================================================

	override bool Use (bool pickup)
	{
		let armor = BasicArmor(Owner.FindInventory("BasicArmor"));

		// This should really never happen but let's be prepared for a broken inventory.
		if (armor == null)
		{
			armor = BasicArmor(Spawn("BasicArmor"));
			armor.BecomeItem ();
			Owner.AddInventory (armor);
		}
		else
		{
			// If you already have more armor than this item gives you, you can't
			// use it.
			if (armor.Amount >= SaveAmount + armor.BonusCount)
			{
				return false;
			}
			// Don't use it if you're picking it up and already have some.
			if (pickup && armor.Amount > 0 && MaxAmount > 0)
			{
				return false;
			}
		}
		
		armor.SavePercent = clamp(SavePercent, 0, 100) / 100;
		armor.Amount = SaveAmount + armor.BonusCount;
		armor.MaxAmount = SaveAmount;
		armor.Icon = Icon;
		armor.MaxAbsorb = MaxAbsorb;
		armor.MaxFullAbsorb = MaxFullAbsorb;
		armor.ArmorType = GetClassName();
		armor.ActualSaveAmount = SaveAmount;
		return true;
	}
}
Can you comment what going on in every line, like for baby?

Change damageobj to
Spoiler:
I`m not sure I use pointers right. And Is it necessary to change damagemobj at PlayerPawn? I cant attach it to armor directly?
ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: "How do I ZScript?"

Post by ZippeyKeys12 »

I'm a bit busy right now, I believe it is TakeSpecialDamage you want to override. I can try and give you a rough example in a couple of hours if no one more qualified helps you out first.
Also if you want code written/explained perhaps resource request would be better? :? I honestly have NO clue if that's correct, someone please correct me if it is not.

EDIT: To avoid double posting
Spoiler: Second Post
Also can one execute an arbitrary lump?
and once more:
ZippeyKeys12 wrote: Also is it possible to register an EventHandler while the game is running? I recall seeing ZZYZX mention this, but I can't seem to figure it out. :?
Also, is it not possible to put a constant array in a struct?
Can I access a variable in an EventHandler from my StatusBar?
Thanks for any help :wub:
Last edited by ZippeyKeys12 on Sun Nov 05, 2017 7:52 pm, edited 1 time in total.
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: "How do I ZScript?"

Post by gwHero »

Question:

how do I initialize a dynamic array of class items?

I know how to declare it but I can't figure out how to initialize it.
Array<classname> myArray = ..??
ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: "How do I ZScript?"

Post by ZippeyKeys12 »

https://zdoom.org/wiki/Dynamic_arrays
Please use the wiki for simple things.
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: "How do I ZScript?"

Post by gwHero »

ZippeyKeys12 wrote:https://zdoom.org/wiki/Dynamic_arrays
Please use the wiki for simple things.
I can assure you that when I am posting something here, I have searched the wiki and the forums extensively, and tried myself. The wiki does not say how to initialize it, nor could I find an example.
I have these parts in my code, and they are working properly; however, it's recommended to initiliaze it, and I simply don't know how.

Code: Select all

Array<MQueuedMessage> messQueue;
Array<MQueuedSpawn> spawnQueue;
int ticks;

	void QueueMessage(int ticsdelay, int line, int messnr)
	{
		let qm = new("MQueuedMessage");
		qm.delay = ticks + ticsdelay;
		qm.line = line;
		qm.messnr = messnr;
		messQueue.Push(qm);	// append item
	}
	
	void QueueSpawn(int ticsdelay, int tagms, string cname)
	{
		let qs = new("MQueuedSpawn");
		qs.delay = ticks + ticsdelay;
		qs.tagMapspot = tagms;
		qs.classname = cname;
		spawnQueue.Push(qs);	// append item
	}

ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: "How do I ZScript?"

Post by ZippeyKeys12 »

My bad :( , I was in a hurry and assumed you meant declaration because afaik there is no initializer for dynamic arrays.
Image
Sry :(
User avatar
gwHero
Posts: 360
Joined: Mon May 08, 2017 3:23 am
Graphics Processor: Intel with Vulkan/Metal Support
Location: The Netherlands

Re: "How do I ZScript?"

Post by gwHero »

ZippeyKeys12 wrote:My bad , I was in a hurry and assumed you meant declaration because afaik there is no initializer for dynamic arrays.
LOL okay :) But I think you're right, I guess there isn't.
ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: "How do I ZScript?"

Post by ZippeyKeys12 »

How does one add strings together? Can I register a EventHandler during runtime?
Blue Shadow
Posts: 5023
Joined: Sun Nov 14, 2010 12:59 am

Re: "How do I ZScript?"

Post by Blue Shadow »

ZippeyKeys12 wrote:How does one add strings together?
Check [wiki=String]here[/wiki]. You might find the answer.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: "How do I ZScript?"

Post by Apeirogon »

Spoiler:
But this still throw monter it pain state. What wrong?
ZippeyKeys12
Posts: 111
Joined: Wed Jun 15, 2016 2:49 pm

Re: "How do I ZScript?"

Post by ZippeyKeys12 »

Blue Shadow wrote:
ZippeyKeys12 wrote:How does one add strings together?
Check [wiki=String]here[/wiki]. You might find the answer.
I tried that, maybe I'm doing something else wrong.

Return to “Scripting”