random placement for specific monster spawn at random level?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
User avatar
nakkemake
Posts: 237
Joined: Fri Apr 24, 2015 3:31 am
Location: ┌П┐(▀̿Ĺ̯▀̿ ̿)

random placement for specific monster spawn at random level?

Post by nakkemake »

I have no code to try to it yet, but is this possible?

I would have a specific bossmonster wandering about in a map, but at random map. How should this be implemented? The placement of the monster would not be an issue since it would be a ghost wandering, noclipping trough walls, it would turn solid when it would have line of sight to attack.

Obviously it is for Co-Op.
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: random placement for specific monster spawn at random le

Post by Player701 »

Depends on how exactly you want it to work, but the WorldLoaded event is a good entry point for this. For example, the following code randomly spawns a ghostly cyberdemon in the current level, and the chance to spawn it at all is 50%. The actual spawn point is randomly picked from the list of actors in the level, excluding players, monsters, and owned inventory items, as well as anything that is located outside of map bounds. You can use this code as a starting point and adjust the initial chance and spawn point conditions as you see fit.

Code: Select all

version "4.5"

class BossSpawnHandler : EventHandler
{
    override void WorldLoaded (WorldEvent e)
    {
        if (e.IsReopen)
        {
            // Do not spawn again on hub re-entry
            return;
        }

        // Step 1: Roll dice
        bool shouldSpawn = FRandom[BossSpawn](0, 1) < 0.5;

        if (!shouldSpawn)
        {
            return;
        }

        Actor mo;
        ThinkerIterator it = ThinkerIterator.Create('Actor');
        Array<Actor> spawnPoints;

        // Step 2: Count total number of spawn points
        while ((mo = Actor(it.Next())) != null)
        {
            if (!IsValidSpawnPoint(mo))
            {
                continue;
            }

            spawnPoints.Push(mo);
        }      

        // Step 3: Pick spawn point
        int spawnAt = Random[BossSpawn](0, spawnPoints.Size() - 1);

        // Step 4: Spawn boss monster
        Actor.Spawn('BossMonster', spawnPoints[spawnAt].Pos);
        players[consoleplayer].mo.A_Print("Boss Monster Spawned");
    }

    private static bool IsValidSpawnPoint(Actor mo)
    {
        // Do not consider as spawn points:
        // 1) other monsters
        // 2) players
        // 3) owned inventory items
        // 4) actors outside of the map
        return !mo.bIsMonster
            && mo.player == null
            && !(mo is 'Inventory' && Inventory(mo).Owner != null)
            && Level.IsPointInLevel(mo.Pos);
    }
}

class BossMonster : Cyberdemon
{
    Default
    {
        RenderStyle "Translucent";
        Alpha 0.5;
        -SOLID;
        +NOCLIP;
    }
}
And don't forget to register the event handler in MAPINFO:

Code: Select all

gameinfo
{
    AddEventHandlers = "BossSpawnHandler"
}
Post Reply

Return to “Scripting”