Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
  • 0
Dexiaz

Spawn powerup once instead of random item?

Question

Hi there.

 

I'm working with a tweak mod for classic I/PWADs, and I want to make a feature to spawn "Allmap" on every map. I want it to spawn if it doesn't exist on map instead of any small item (armor bonus, health bonus, stimpack, medikit, shells, ammo box, clip, etc). And only once.

 

Engine: GZDoom. ACS, ZScript, Decorate.

Share this post


Link to post

5 answers to this question

Recommended Posts

  • 0

I tried doing this but the script refuses to run on the first frame of the actor for some reason, only works when I manually execute it, don't know why:

 

 

CheckAllMap.zip

Share this post


Link to post
  • 0

@tempdecal.wad two bugs here. first, second argument to `ACS_NamedExecuteAlways()` is map number, which should be 0 in your case (otherwise the script is simply scheduled, and never executed); and remove last "0". second, coordinates for `SpawnForce()`are in fixed-point, so you have to multiply them to 65536 in decorate code.

Share this post


Link to post
  • 1

ZScript solution:

 

version "4.2"

class AllmapSpawnHandler : EventHandler
{
	override void WorldLoaded(WorldEvent e)
	{
		static const string ClassNames[] =
		{
			"Stimpack",
			"Medikit",
			"Clip",
			"HealthBonus",
			"ArmorBonus"
			// more here
		};
		
		// Supposedly LevelCreateActorIterator is faster, but I don't think
		// it works with tag 0
		ThinkerIterator it = ThinkerIterator.Create();
		Array<Actor> actors;
		
		Actor mo;
		
		while(mo = Actor(it.Next()))
		{
			// Don't touch actors with a tag
			if(mo.tid != 0)
				continue;

			string cn = mo.GetClassName();
			
			// Stop if there's already an allmap in the map
			if(cn == "Allmap")
				return;
			
			// Check if it's an actor we're ok with to replace
			for(int i; i < ClassNames.Size(); i++)
			{
				if(ClassNames[i] == cn)
				{
					actors.push(mo); // Store all valid actors in an array
					break;
				}
			}
		}
		
		for(int i=0; i < actors.size(); i++)
			console.printf(string.format("%d: %s", i, actors[i].GetClassName()));
		
		// Chose a random actor. Hack: skip the first one, since it's apparently
		// the ammo the player gets at start. There must be a better way
		mo = actors[Random(1, actors.Size()-1)]; 
		Actor.Spawn("Allmap", mo.pos); // Spawn Allmap at the actor's position
		mo.Destroy(); // Destroy the original actor
	}
}

Example attached.

allmapspawner.zip

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×