A_Blast

From ZDoom Wiki
Jump to navigation Jump to search

Actor

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

Usage

Blasts actors away as a disc of repulsion does.

Parameters

  • EBlastFlags flags
The following flags can be used alone, combined as needed by listing their keywords (separated by the '|' character):
  • BF_USEAMMO — If this flag is set and the codepointer is used by a player, ammunition is used. By default, it is not. Do not set this flag in an inventory item or player class!
  • BF_DONTWARN — If this flag is set, monsters will not be woken up by the sound of the blast. By default, they are.
  • BF_AFFECTBOSSES — If this flag is set, monsters with the BOSS flag are affected. By default, they are immune to this effect.
  • BF_NOIMPACTDAMAGE — If this flag is set, affected monsters will not cause melee damage on impact. By default, they do.
  • BF_ONLYVISIBLETHINGS — If this flag is set, only visible monsters will be blasted away.
  • double strength
Not actually used by default. ZScript-based actors can take it into account by overriding the SpecialBlastHandling virtual function. (Default: 255.)
  • double radius
The maximum distance at which actors are affected. (Default: 255)
  • double speed
The speed at which blasted actors are sent away. (Default: 20.0)
  • class<Actor> blasteffect
The actor spawned on each blasted actor to show the effect taking place. (Default: BlastEffect)
  • sound blastsound
The sound to play when blasting. (Default: "BlastRadius")

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.

The original definition of this function:

	//==========================================================================
	//
	// 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));
		}
	}

Examples

Nuvolachalk.png Note: This article lists no examples. If you make use of this feature in your own project(s) or know of any basic examples that could be shared, please add them. This will make it easier to understand for future authors seeking assistance. Your contributions are greatly appreciated.


See also