Monster spawning monster which spawns monster etc
Posted: Thu Mar 07, 2013 9:03 pm
First and foremost: hi to all
Second: as a novice Grimrock scripter, I was thinking about having monsters which, when killed, spawn other monsters around (or, for what matters, open/close doors, destroy objects, and so on). I was - also - thinking of a method of achieving that which was "monster independent"; i.e., I do not want monster X to spawn monster Y when it dies: I want a general monster which spawns another general one as he dies. And the solution I've found (not a very practical one, I admit) is to give the spawned monster an id of the form (for example)
spawn{my_monster}{spawn{my_other_monster}{open{that_door}}}
In this case, I have a monster (my_monster) which, when killed, spawns a monster (my_other_monster) which, when killed, opens a door (that_door).
In order for this to work, I need to create (in monsters.lua) a cloned monster (my_monster, my_other_monster) which launches an onDie(self) function which 'parses' the monster id in its 2 (or 3, or more) parts: a 'command' (spawn, open, close, destroy) and various parameters: 1 for 'open' and 'close', the door to open, for example; 2 for 'spawn' (the name of the monster to spawn, and its id, which, as in the example above, may be another string of 'commands').
Here is the code I wrote, but I was wondering: is there another way to achieve such results?
Thanks in advance,
alois
---------
- In monsters.lua
- In a script entity named ondie
The first two functions 'parse' the id string in its components command{parameter1}{parameter2} etc; the third is the true onDie routine.
And then I create a dying_scavenger with "spawn{dying_scavenger}{spawn{dying_scavenger}{open{dd1}}}" as id (here "dd1" is a door in the dungeon).
Second: as a novice Grimrock scripter, I was thinking about having monsters which, when killed, spawn other monsters around (or, for what matters, open/close doors, destroy objects, and so on). I was - also - thinking of a method of achieving that which was "monster independent"; i.e., I do not want monster X to spawn monster Y when it dies: I want a general monster which spawns another general one as he dies. And the solution I've found (not a very practical one, I admit) is to give the spawned monster an id of the form (for example)
spawn{my_monster}{spawn{my_other_monster}{open{that_door}}}
In this case, I have a monster (my_monster) which, when killed, spawns a monster (my_other_monster) which, when killed, opens a door (that_door).
In order for this to work, I need to create (in monsters.lua) a cloned monster (my_monster, my_other_monster) which launches an onDie(self) function which 'parses' the monster id in its 2 (or 3, or more) parts: a 'command' (spawn, open, close, destroy) and various parameters: 1 for 'open' and 'close', the door to open, for example; 2 for 'spawn' (the name of the monster to spawn, and its id, which, as in the example above, may be another string of 'commands').
Here is the code I wrote, but I was wondering: is there another way to achieve such results?
Thanks in advance,
alois
---------
- In monsters.lua
Code: Select all
cloneObject{
name = "dying_scavenger",
baseObject = "scavenger",
onDie = function(self)
return ondie.onDie(self)
end,
}
Code: Select all
function findpattern(t,p,s)
local start = string.find(t,p,s)
print(start)
if (start == nil) then
return 0,0
else
local part = string.sub(t,string.find(t,p,s))
return start + 1, start + #part - 2
end
end
function findparts(str)
local parts = {}
local finish = false
local start = 1
while (not finish) do
local sta, fin = findpattern(str,'%b{}',start)
if (sta * fin == 0) then
return parts
else
if (start == 1) then
table.insert(parts,string.sub(str,1,sta-2))
end
table.insert(parts,string.sub(str,sta,fin))
start = fin
if (start == (#str - 1)) then
finish = true
end
end
end
return parts
end
function onDie(self)
local facingDirs = {{x=0,y=1},{x=-1,y=0},{x=0,y=-1},{x=1,y=0}}
local monsterId = self.id
local parts = findparts(monsterId)
if (#parts == 0) then
return true
else
local doCommand = parts[1]
if (doCommand == "open") and (#parts == 2) then
findEntity(parts[2]):open()
end
if (doCommand == "close") and (#parts == 2) then
findEntity(parts[2]):close()
end
if (doCommand == "spawn") and (#parts == 3) then
local newPos = {x = self.x+facingDirs[self.facing+1].x, y = self.y+facingDirs[self.facing+1].y}
if not isWall(self.level,newPos.x,newPos.y) then
spawn(parts[2],self.level,newPos.x,newPos.y,self.facing,parts[3])
end
end
if (doCommand == "destroy") and (#parts == 2) then
findEntity(parts[2]):destroy()
end
return true
end
end
And then I create a dying_scavenger with "spawn{dying_scavenger}{spawn{dying_scavenger}{open{dd1}}}" as id (here "dd1" is a door in the dungeon).