Classes:ThinkerIterator

From ZDoom Wiki
Jump to navigation Jump to search
Note: This feature is for ZScript only.


ThinkerIterator is an internal class in ZScript, inheriting from Object.

This class is used for searching through descendants of thinkers. A_GiveToChildren is one of the many functions which uses this.

Functions

Return Type Function Arguments (first to last) Use/Arguments
ThinkerIterator Create
  1. class<Object> type = "Actor",
  2. int statnum =
Thinker.MAX_STATNUM + 1

Initializes the iterator.

  • type - Serves as a filter. Specifying a classname here will only search for this type of class and descendants. Default is Actor.
  • statnum - Sets the specific statnum to be searched. The default is MAX_STATNUM+1, meaning the iterator will search through all of the statnums. If only actors or thinkers in the game simulation are desired, consider setting this to STAT_DEFAULT to save on time an efficiency where all actors are regularly stored, except for inventory and PlayerPawn. See Thinker for more information.

Note: this function is static and should be called off the class name, i.e. ThinkerIterator.Create(...).

Thinker Next
  1. bool exact = false

Cycles through the list of existing actors, filtered out by the Create() function.

  • exact - If true, disables ancestry checking. Note that ancestry checking is just like CheckClass.
void Reinit None Restarts the search.

Example

In this example, an iterator is used during a Tick override on a morphed actor to allow key gathering, despite -PICKUP being set on the player.

// Think of this as A_CheckProximity, but with less limitation.
// However, we have to invent all the checks in order to use it
// properly.

// So, create an iterator that searches for D4KeyBase-inheriting
// only.
ThinkerIterator KeyFinder = ThinkerIterator.Create("D4KeyBase");
Actor mo;
while (mo = D4KeyBase(KeyFinder.Next()))
{
	 // Make sure it can be touched.
	 double blockdist = radius + mo.radius;
	 if (abs(pos.x - mo.pos.x) > blockdist || abs(pos.y - mo.pos.y) > blockdist)
	 {	continue;	}
						
	 // So we're in range horizontally. What about vertically?
	 if (pos.z + height < mo.pos.z || mo.pos.z + mo.height < pos.z)
	 {	continue;   }
		
	 // Execute any specials this thing had.				
	 if (mo && mo.special)
	 {
		 A_CallSpecial(mo.special, mo.args[0], mo.args[1], mo.args[2], mo.args[3], mo.args[4]);
	 }

	 // Assemble the arrays only if we succeed. This first array
	 // contains the actor's hard names.
	 static const Class<Actor> KeyName[] =
	 {
		 "D4RedCard",
		 "D4YellowCard",
		 "D4BlueCard",
		 "D4RedSkull",
		 "D4YellowSkull",
		 "D4BlueSkull"
	 };
		
	 // Contains the nice names for logging.
	 static const String NiceKeyName[] =
	 {
		 "Red Card",
		 "Yellow Card",
		 "Blue Card",
		 "Red Skull",
		 "Yellow Skull",
		 "Blue Skull"
	 };

	 // In the event someone decides to screw with the keys, check the base class.
	 for (int index = 0; index < 6; index++)
	 {
		 if (mo.CheckClass(KeyName[index], DefPtr, true))
		 {
			 //Concatenate a string with .. (two periods)
			 A_Log(NiceKeyName[index].." Found");
			 break;
		 }
	 }
		
	 // Grabs the actual key and gives it to the player. This would
	 // be the same as if I had done A_GiveInventory(KeyName[Index])
	 // inside the for loop and if block. However, if done above, it
	 // wouldn't be safe as D4D mods could possibly modify them.
	 // This ensures nothing is missed so long as they inherit from
	 // D4KeyBase. The worst that will happen, they simply don't have
	 // a pickup message attached. No big deal.
		
	 Class<D4KeyBase> keypick = (Class<D4KeyBase>)(mo.GetClass());
	 A_GiveInventory(keypick,1);
	 mo.A_Remove(DefPtr,RMVF_EVERYTHING);
	 
}

See Also