Classes:ArtiBlastRadius

From ZDoom Wiki
Jump to navigation Jump to search
Note: Wait! Stop! Before you copy this actor's definition into your mod, remember the following things:
  1. You do not need to copy that actor, since it is already defined.
  2. In fact, it's not just useless, it's actually harmful as it can cause problems.
  3. If you want to modify it, or use a modified version, using inheritance is the way to go.
  4. The actor definitions here are put on the wiki for reference purpose only. Learn from them, don't copy them.
  5. There is only one exception: if what you want is changing Ammo capacity, you need to create a new type from Ammo.
Disc of Repulsion
Actor type Artifact Game MiniHexenLogoIcon.png (Hexen)
DoomEd Number 10110 Class Name ArtiBlastRadius
Spawn ID 74 Identifier T_ITEMREPULSION


Classes: InventoryCustomInventoryArtiBlastRadius

The disc of repulsion, when used, calls A_Blast, pushing away nearby movable actors, including players, monsters and even projectiles. It can be used to avoid being hit by missiles, push enemies out of the way, throw them in chasms or traps, or even provoke infighting by making them collide another monsters. An actor projected by the disc of repulsion will take damage when colliding with a wall or another actor.

Monsters with the BOSS or DONTBLAST flags are normally unaffected; as well as any actor that isn't a monster, player, or projectile, unless they have the CANBLAST flag. When an actor is affected, a blue ring with a white cross temporarily appears on it to show the disc of repulsion did take effect.

ZScript definition

Note: The ZScript definition below is for reference and may be different in the current version of GZDoom.The most up-to-date version of this code can be found on GZDoom GitHub.
class ArtiBlastRadius : CustomInventory
{
	Default
	{
		+FLOATBOB
		Inventory.DefMaxAmount;
		Inventory.PickupFlash "PickupFlash";
		+INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND
		Inventory.Icon "ARTIBLST";
		Inventory.PickupSound "misc/p_pkup";
		Inventory.PickupMessage "$TXT_ARTIBLASTRADIUS";
		Tag "$TAG_ARTIBLASTRADIUS";
	}
	States
	{
	Spawn:
		BLST ABCDEFGH 4 Bright;
		Loop;
	Use:
		TNT1 A 0 A_Blast;
	}
	
}
//==========================================================================
//
// A_Blast is public to Actor
//
//==========================================================================

extend class Actor
{
	/* For reference, the default values:
	#define BLAST_RADIUS_DIST	255.0
	#define BLAST_SPEED			20.0
	#define BLAST_FULLSTRENGTH	255
	*/

	//==========================================================================
	//
	// AArtiBlastRadius :: BlastActor
	//
	//==========================================================================

	private void BlastActor (Actor victim, double strength, double speed, Class<Actor> blasteffect, bool dontdamage)
	{
		if (!victim.SpecialBlastHandling (self, strength))
		{
			return;
		}

		double ang = AngleTo(victim);
		Vector2 move = AngleToVector(ang, speed);
		victim.Vel.XY = move;

		// Spawn blast puff
		ang -= 180.;
		Vector3 spawnpos = victim.Vec3Offset(
			(victim.radius + 1) * cos(ang),
			(victim.radius + 1) * sin(ang),
			(victim.Height / 2) - victim.Floorclip);
		Actor mo = blasteffect? Spawn (blasteffect, spawnpos, ALLOW_REPLACE) : null;
		if (mo)
		{
			mo.Vel.XY = victim.Vel.XY;
		}
		if (victim.bMissile)
		{
			// [RH] Floor and ceiling huggers should not be blasted vertically.
			if (!victim.bFloorHugger && !victim.bCeilingHugger)
			{
				victim.Vel.Z = 8;
				if (mo != null) mo.Vel.Z = 8;
			}
		}
		else
		{
			victim.Vel.Z = 1000. / victim.Mass;
		}
		if (victim.player)
		{
			// Players handled automatically
		}
		else if (!dontdamage)
		{
			victim.bBlasted = true;
		}
		if (victim.bTouchy)
		{ // Touchy objects die when blasted
			victim.bArmed = false; // Disarm
			victim.DamageMobj(self, self, victim.health, 'Melee', DMG_FORCED|DMG_EXPLOSION);
		}
	}
	
	//==========================================================================
	//
	// AArtiBlastRadius :: Activate
	//
	// Blast all actors away
	//
	//==========================================================================

	action void A_Blast(int blastflags = 0, double strength = 255, double radius = 255, double speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius")
	{

		if (player && (blastflags & BF_USEAMMO) && invoker == player.ReadyWeapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
		{
			Weapon weapon = player.ReadyWeapon;
			if (weapon != null && !weapon.DepleteAmmo(weapon.bAltFire))
			{
				return;
			}
		}

		A_StartSound (blastsound, CHAN_AUTO);

		if (!(blastflags & BF_DONTWARN))
		{
			SoundAlert (self);
		}
		ThinkerIterator it = ThinkerIterator.Create("Actor");
		Actor mo;
		while ( (mo = Actor(it.Next ())) )
		{
			if (mo == self || (mo.bBoss && !(blastflags & BF_AFFECTBOSSES)) || mo.bDormant || mo.bDontBlast)
			{ // Not a valid monster: originator, boss, dormant, or otherwise protected
				continue;
			}
			if (mo.bIceCorpse || mo.bCanBlast)
			{
				// Let these special cases go
			}
			else if (mo.bIsMonster && mo.health <= 0)
			{
				continue;
			}
			else if (!mo.player && !mo.bMissile && !mo.bIsMonster && !mo.bCanBlast && !mo.bTouchy && !mo.bVulnerable)
			{	// Must be monster, player, missile, touchy or vulnerable
				continue;
			}
			if (Distance2D(mo) > radius)
			{ // Out of range
				continue;
			}
			if (mo.CurSector.PortalGroup != CurSector.PortalGroup && !CheckSight(mo))
			{
				// in another region and cannot be seen.
				continue;
			}
			if ((blastflags & BF_ONLYVISIBLETHINGS) && !isVisible(mo, true)) 
			{
				//only blast if target can bee seen by calling actor
				continue;
			}
			BlastActor (mo, strength, speed, blasteffect, !!(blastflags & BF_NOIMPACTDAMAGE));
		}
	}
}

DECORATE definition

Note: This is legacy code, kept here for reference only. DECORATE is still supported but no longer used by GZDoom. GZDoom internally uses the ZScript definition above.
ACTOR ArtiBlastRadius : CustomInventory
{
  +FLOATBOB
  Inventory.DefMaxAmount
  Inventory.PickupFlash "PickupFlash"
  +INVBAR
  +FANCYPICKUPSOUND
  Inventory.Icon "ARTIBLST"
  Inventory.PickupSound "misc/p_pkup"
  Inventory.PickupMessage "$TXT_ARTIBLASTRADIUS"
  Tag "$TAG_ARTIBLASTRADIUS"
  States
  {
  Spawn:
    BLST ABCDEFGH 4 Bright
    Loop
  Use:
    TNT1 A 0 A_Blast
  }
}