Defend Script

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!)
Post Reply
Drake Raider
Posts: 474
Joined: Fri Jul 18, 2008 12:27 pm

Defend Script

Post by Drake Raider »

This possibly one of my more oddly-specific requests, and I'd try to do it myself if I really had any idea how zScript worked, but I need (Particularly in zScript) a specific weapon function:

As long as you hold down the mouse button, it lowers your camera, reduces your collision box, and reduces all incoming damage by 60% or so.

You can keep it running as long as you want, but you can't attack/use items while it's active, and once you release it has a cooldown equal to half the time it was active (regardless of duration.)

I plan on using it as an altfire for a couple different weapons, so whatever I would need to do to impliment it flexibly as possible is also a plus. No idea where to start.
User avatar
Jekyll Grim Payne
Global Moderator
Posts: 1117
Joined: Mon Jul 21, 2008 4:08 am
Preferred Pronouns: He/Him
Graphics Processor: nVidia (Modern GZDoom)
Contact:

Re: Defend Script

Post by Jekyll Grim Payne »

I had a bit of time so I went ahead and coded the thing below.
I'm also attaching it as a text file to the post. It's rather heavily commented, so it should be fairly clear what does what.

Code: Select all

version "4.7.0"

// To make this work in other weapons, the easiest approach would be
// to put all of this into your custom base weapon class that other
// weapons in the mod inherit from. Then, in those weapons where
// you don't want this altfire to be useable, either replace it
// with a different altfire, or use A_WeaponReady(WRF_NOSECONDARY)
// to disable altfire in a specific weapon completely.

class DefendWeapon : Weapon
{	
	bool defenseactive;
	
	double prevheight; // cache player's original height
	double prevradius; // cache player's original radius
	double prevViewheight; // cache player's original viewheight
	double prevAttackZOffset; // cache player's original AttackZOffset
	
	// Using constants isn't necessary here but it makes it
	// easier to tweak these values in the future, since 
	// you can tweak them in one place instead of editing them
	// throughout the code.
	const SIZEREDUCTION = 0.75; //by how much to reduce player's hitbox
	const VIEWLOWER = 8; //by how much to lower player's view
	
	// The following could be done in anonymous functions,
	// but wrapping it into simple custom functions just
	// lets us keep the code a bit cleaner:
	
	action void ActivateDefense()
	{
		if (invoker.defenseactive)
			return;
		invoker.defenseactive = true;
		// record current values:
		invoker.prevheight = height;
		invoker.prevradius = radius;
		invoker.prevViewheight = player.ViewHeight;
		invoker.prevAttackZOffset = player.mo.AttackZOffset;
		// set size and view:
		A_SetSize(height * SIZEREDUCTION, radius * SIZEREDUCTION);
		// Note that viewheight has to be changed on the player,
		// whereas AttackZOffset has to be changed on the player pawn.
		// It's possible to access AttackZOffset on the player,
		// but it's not properly controllable.
		player.ViewHeight -= VIEWLOWER;
		player.mo.AttackZOffset -= VIEWLOWER;
		GiveInventory("DefendWeaponEffect", 1);
		//console.printf("ACTIVATED: size: %.1f, %.1f | attackZOffset: %.1f | viewheight: %.1f", radius, height, player.mo.AttackZOffset, player.ViewHeight);
	}
	
	action void DeactivateDefense()
	{
		if (!invoker.defenseactive)
			return;
		invoker.defenseactive = false;
		// reset size and view to previous values:
		A_SetSize(invoker.prevheight,invoker.prevradius);
		player.ViewHeight = invoker.prevViewheight;
		player.mo.AttackZOffset = invoker.prevAttackZOffset;
		TakeInventory("DefendWeaponEffect", 1);
		//console.printf("DEACTIVATED: size: %.1f, %.1f | attackZOffset: %.1f | viewheight: %.1f", radius, height, player.mo.AttackZOffset, player.mo.ViewHeight);
	}
	
	States
	{
	Ready:
		TNT1 A 1 A_Weaponready(WRF_NOPRIMARY); //disabling primary fire because we don't need it in this example
		loop;
	//Fire sequence can't be omitted, so we include one that does nothing:
	Fire:
		TNT1 A 1;
		goto ready;
	//Select and deselect sequences 
	Select:
		TNT1 A 1 A_Raise;
		loop;
	Deselect:
		TNT1 A 1 A_Lower;
		loop;
	Altfire:
		TNT1 A 1
		{
			// Check if the player is pressing and holding altfire button:
			if (player.cmd.buttons & BT_ALTATTACK && player.oldbuttons & BT_ALTATTACK)
			{
				// If defense isn't active yet, activate it:
				if (!invoker.defenseactive)
					ActivateDefense();
				// And do nothing else, jump to 'wait':
				return ResolveState(null);
			}
			// OTHERWISE deactivate defense and goto Ready:
			DeactivateDefense();
			return ResolveState("Ready");
		}
		wait;
	}
}

// A powerup-like item that reduces incoming damage:
class DefendWeaponEffect : Inventory
{
	Default
	{
		inventory.maxamount 1;
		+INVENTORY.UNDROPPABLE
		+INVENTORY.UNTOSSABLE
	}
	
	override void ModifyDamage (int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags)
	{
		if (!passive && damage > 0)
			newdamage = damage * 0.6;
	}
}
Attachments
defendWeapon.txt
(3.81 KiB) Downloaded 23 times
Post Reply

Return to “Scripting”