A_SpawnFly

From ZDoom Wiki
Jump to navigation Jump to search
DoomWiki.org
For more information on this article, visit the A_SpawnFly page on the Doom Wiki.


Actor

void A_SpawnFly(class<Actor> spawntype = null)

Usage

Checks whether a boss cube has reached its target and if so spawns a monster there. Monsters are defined through the DropItem property of the SpawnShot.

It also telefrags anything in the way of spawning.

If spawntype is provided, the specified actor will be spawned as a visual effect on top of the monster. If not provided, uses SpawnFire instead. Also, the sound that plays at spawn will be the SeeSound of the spawned spawntype actor.

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 behavior of this function is wholly handled in ZScript and consists of two parts: a public A_SpawnFly function and a private SpawnFly method. Despite being private, the latter can be copy-pasted and modified to create custom behavior.

The behavior of picking the class to spawn is very similar to what RandomSpawner uses.

	private void SpawnFly(class<Actor> spawntype, sound snd)
	{
		Actor newmobj;
		Actor fog;
		Actor eye = master; // The eye is the spawnshot's master, not the target!
		Actor targ = target; // Unlike other projectiles, the target is the intended destination.
		int r;

		if (targ == null)
		{
			Destroy();
			return;
		}
			
		// [GZ] Should be more viable than a countdown...
		if (special2 != 0)
		{
			if (special2 > level.maptime)
				return;		// still flying
		}
		else
		{
			if (reactiontime == 0 || --reactiontime != 0)
				return;		// still flying
		}
		
		if (spawntype)
		{
			fog = Spawn (spawntype, targ.pos, ALLOW_REPLACE);
			if (fog) A_StartSound(snd, CHAN_BODY);
		}

		class<Actor> SpawnName = null;

		DropItem di;   // di will be our drop item list iterator
		DropItem drop; // while drop stays as the reference point.
		int n = 0;

		// First see if this cube has its own actor list
		drop = GetDropItems();

		// If not, then default back to its master's list
		if (drop == null && eye != null)
			drop = eye.GetDropItems();

		if (drop != null)
		{
			for (di = drop; di != null; di = di.Next)
			{
				if (di.Name != 'None')
				{
					int amt = di.Amount;
					if (amt < 0)
					{
						amt = 1; // default value is -1, we need a positive value.
					}
					n += amt; // this is how we can weight the list.
				}
			}
			di = drop;
			n = random[pr_spawnfly](0, n);
			while (n >= 0)
			{
				if (di.Name != 'none')
				{
					int amt = di.Amount;
					if (amt < 0)
					{
						amt = 1;
					}
					n -= amt;
				}
				if ((di.Next != null) && (n >= 0))
				{
					di = di.Next;
				}
				else
				{
					n = -1;
				}
			}
			SpawnName = di.Name;
		}
		if (SpawnName == null)
		{
			// Randomly select monster to spawn.
			r = random[pr_spawnfly](0, 255);

			// Probability distribution (kind of :),
			// decreasing likelihood.
				 if (r < 50)  SpawnName = "DoomImp";
			else if (r < 90)  SpawnName = "Demon";
			else if (r < 120) SpawnName = "Spectre";
			else if (r < 130) SpawnName = "PainElemental";
			else if (r < 160) SpawnName = "Cacodemon";
			else if (r < 162) SpawnName = "Archvile";
			else if (r < 172) SpawnName = "Revenant";
			else if (r < 192) SpawnName = "Arachnotron";
			else if (r < 222) SpawnName = "Fatso";
			else if (r < 246) SpawnName = "HellKnight";
			else			  SpawnName = "BaronOfHell";
		}
		if (spawnname != null)
		{
			newmobj = Spawn (spawnname, targ.pos, ALLOW_REPLACE);
			if (newmobj != null)
			{
				// Make the new monster hate what the boss eye hates
				if (eye != null)
				{
					newmobj.CopyFriendliness (eye, false);
				}
				// Make it act as if it was around when the player first made noise
				// (if the player has made noise).
				newmobj.LastHeard = newmobj.CurSector.SoundTarget;

				if (newmobj.SeeState != null && newmobj.LookForPlayers (true))
				{
					newmobj.SetState (newmobj.SeeState);
				}
				if (!newmobj.bDestroyed)
				{
					// telefrag anything in this spot
					newmobj.TeleportMove (newmobj.pos, true);
				}
				newmobj.bBossSpawned = true;
			}
		}

		// remove self (i.e., cube).
		Destroy ();
	}

	void A_SpawnFly(class<Actor> spawntype = null)
	{
		sound snd; 
		if (spawntype != null) 
		{
			snd = GetDefaultByType(spawntype).SeeSound;
		}
		else
		{
			spawntype = "SpawnFire";
			snd = "brain/spawn";
		}
		SpawnFly(spawntype, snd);
	}

Examples

This example is taken from Doom's spawn cube.

 Spawn:
   BOSF A 3 BRIGHT A_SpawnSound;
   BOSF BCD 3 BRIGHT A_SpawnFly; // See SpawnFire
   Loop;

See also