Page 1 of 1
Defend Script
Posted: Fri Dec 17, 2021 10:47 am
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.
Re: Defend Script
Posted: Sat Dec 25, 2021 5:37 am
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;
}
}