[Script] - Smart Spawner

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

[Script] - Smart Spawner

Post by Xanathar »

Hi all, following is a script for a "smart" spawner.

Code:
SpoilerShow

Code: Select all

function countEntitiesOfTypesInLevel(spawnedEntityNames, level)
	local count = 0

	for e in allEntities(level) do
		for _, t in ipairs(spawnedEntityNames) do
			if (e.name == t) then
				count = count + 1
			end
		end
	end
	
	return count
end

function partyDist(x, y)
	return math.abs(party.x - x) + math.abs(party.y - y)
end


function spawnChecked(level, spawners, spawnedEntityNames, maxEntities, minDistance)
	if countEntitiesOfTypesInLevel(spawnedEntityNames, level) >= maxEntities then
		return
	end
	
	local spawner = spawners[math.random(1, #spawners)]
	
	local dist = partyDist(spawner.x, spawner.y)
	
	if dist < minDistance then
		return
	end
	
	spawner:activate()
	
end	
	
Usage:
  • Put it into a script entity in one (and only one) level in the dungeon, doesn't matter which, called "smartSpawning"
  • Call it with smartSpawning.spawnChecked(<level>, <table-of-spawners>, <table-of-monsters>, <max-monsters>, <min-distance>) from a timer, pressure-plate or other activating device
Example:

Code: Select all

function spawnGo()
	local spawners =
	{
		lvl5spawner1,
		lvl5spawner2,
		lvl5spawner3,
		lvl5spawner4,
		lvl5spawner5,
		lvl5spawner6
	}
	
	smartSpawning.spawnChecked(5, spawners, { "spider" }, 16, 7)	
end	
Features:
  • Spawns choosing a random spawner from the list
  • Doesn't spawn if there are already <max-monsters> spawned entities in the level
  • Doesn't spawn if the picked spawner is under <min-dist> distance from the party (to avoid seeing monsters appearing out of nowhere)


Let me know of any issue - I'll post to the wiki soon.
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
User avatar
zeltak
Posts: 119
Joined: Fri May 04, 2012 2:33 am

Re: [Script] - Smart Spawner

Post by zeltak »

Thank you! Have to test this out. I was pondering something like this myself, but it was just ouside my scripting skills.

edit: any ideas how to incorporate monster levels into that script? I mean if I would like to spawn level 3 crowerns for example.
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

Re: [Script] - Smart Spawner

Post by Xanathar »

First of all, read this post from Grimwald about designing spawners for high level monsters:

viewtopic.php?f=14&t=3770&sid=2c140181a ... ebc#p38581

And define, say, the "level2_snail", "level3_snail" etc.
Then, let's say you want to have a 25% chance of spawning a level 5 snail and 75% chance of spawning a level 3 snail:

1) Create 2 spawners (let's call them lvl5snailspawn and lvl3snailspawn)
2) Use a non-equally distributed table when passing spawners to the function:

local myspawners = { lvl3snailspawn, lvl3snailspawn, lvl3snailspawn, lvl5snailspawn}

smartSpawning.spawnChecked(3, myspawners, { "level3_snail", "level5_snail" }, 12, 9)
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: [Script] - Smart Spawner

Post by Grimwold »

Great script. Thanks for sharing this. One possible enhancement would be to change the spawned entity on-the-fly and have the script randomly choose entity and spawner independently

So you'd include something like this (untested)

Code: Select all

local spawnedEntityName = spawnedEntityNames[math.random(1, #spawnedEntityNames)]
local spawner = spawners[math.random(1, #spawners)]

spawner:setSpawnedEntity(spawnedEntityName)
spawner:activate()

and you would call it with something like:

Code: Select all

smartSpawning.spawnChecked(5, {spawner_1,spawner_2,spawner_3},{"crowern","crowern","crowern","wyvern"},16,5)
Ixnatifual

Re: [Script] - Smart Spawner

Post by Ixnatifual »

I've got 3 snail spawners and are using the following.

Code: Select all

function spawnGo()
   local spawners =
   {
      spawner_156,
      spawner_160,
      spawner_157
   }
   
   smartSpawning.spawnChecked(14, spawners, { "snail" }, 2, 1)   
end   
As I understand it at most 2 snails are supposed to be in the level at one time given the above. Yet it seems to keep endlessly spawning snails. Am I missing something here?
User avatar
HaunterV
Posts: 676
Joined: Mon Apr 16, 2012 9:54 pm
Location: Barrie, Ontario, Canada

Re: [Script] - Smart Spawner

Post by HaunterV »

hmm I think I like this. Since the spawners have no ai on the go, If you control when a monster spawns you reduce the number of monster AIs running in the background.

I mean, Ive noticed all teh monsters in your dungeon will run around doing their own thing which to me means the computer is tracking their movements n such even if the player cant see them. This must be needless CPU usage, or at the very least a spot that could do with some optimization, which I think this idea helps get a handle on.
Grimrock Community 'FrankenDungeon 2012. Submit your entry now!: http://tinyurl.com/cnupr7h
SUBMIT YOUR ASSETS! Community Asset Pack (C.A.P.): http://tinyurl.com/bqvykrp
Behold! The HeroQuest Revival!: http://tinyurl.com/cu52ksc
Ixnatifual

Re: [Script] - Smart Spawner

Post by Ixnatifual »

Think about it this way:

- Monsters on levels outside the one you're at are probably updated a lot less frequently, similar to how scripts running on different levels work. The further away from your level, the less frequently they are updated.
- A game like StarCraft can have hundreds of units off-screen being controlled with super frequency with no slowdown issues.

That being said, completely filling levels with monsters the player may never see probably isn't so smart.

Edit: I just tested monster movement in my dungeon - I went to level 14 and looked at the monsters through the editor map at level 1. It took like a minute for a monster up there to move even a single square. So the game seems to have its own smart method of reducing CPU load for less relevant monsters.
Ixnatifual

Re: [Script] - Smart Spawner

Post by Ixnatifual »

Ixnatifual wrote:As I understand it at most 2 snails are supposed to be in the level at one time given the above. Yet it seems to keep endlessly spawning snails. Am I missing something here?
I called the script thinking I was on level 14, when really I was on level 15. Since no snails were on level 14 the conditions for spawning extra snails kept being true.

On the plus side I learned some extra LUA from debugging effort. :)

This part

Code: Select all

for e in allEntities(level) do
      for _, t in ipairs(spawnedEntityNames) do
         if (e.name == t) then
            count = count + 1
         end
      end
   end
seems kind of heavy duty, though. Even on a super simple level it looped the second for 117 times. I tried on one of the larger levels and it was a whopping 1968! If only there was an allMonsters function instead of allEntities.
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

Re: [Script] - Smart Spawner

Post by Xanathar »

I just tested monster movement in my dungeon - I went to level 14 and looked at the monsters through the editor map at level 1. It took like a minute for a monster up there to move even a single square. So the game seems to have its own smart method of reducing CPU load for less relevant monsters.
If I remember a petri post correctly:
  • The level you are in is updated every frame
  • The level above is updated every odd frame
  • The level below is updated every even frame
  • All other levels are updated in a round-robin fashion
But I might have completely misunderstood that post and/or remember it wrong.
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

Re: [Script] - Smart Spawner

Post by Xanathar »

Even on a super simple level it looped the second for 117 times. I tried on one of the larger levels and it was a whopping 1968! If only there was an allMonsters function instead of allEntities.
Another solution could be to keep the count at the spawn and in the onDie hooks, but then one must be aware of monsters falling in pits which could alter the count (so maybe also keep count in onMove). If there is a real performance problem it might be worth rewriting it with jkos hooks this way.
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
Post Reply