Spike trap script help

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

<3 I'm still trying to figure that part out. I also realized last night that I'm probably making the code harder on myself than it actually needs to be. I don't really need to be spawning a spawner that spawns another entity that then is used to check where to teleport too. All I need to do is either spawn a spawner and use that or spawn the entity itself and use that. Also as I'm having the spawner activated on the pressure plates which are themselves always safe to land on; I can just destroy any entities of the same name at those locations and spawn a new entity at the parties location to teleport too. The teleporting itself is a completely separate function inside the script and needs only run when the party falls into the pit and that calls the teleport timer which calls back to the cleanup script after a delay. (to ensure the party gets successfully teleported before the teleporter is destroyed.) Which leaves me with this so far:

Code: Select all

function trapexit()

	local safespots = {"dungeon_pressure_plate_1",
						"dm_pressure_plate_1",
						"dm_pressure_plate_2",
						"dm_pressure_plate_3",
						"dm_pressure_plate_4",
						"dm_pressure_plate_5",
						"dm_pressure_plate_6",
						"dm_pressure_plate_7",
						"dm_pressure_plate_8"}

	local targetX = findEntity("probe", probe.X)
	local targetY = findEntity("probe", probe.Y)
	local targetFacing = party.facing

   local teleportSuccess = false
   
	for i #safespots, do
		if i.name == "probe" then
			i:destroy
			spawn("spawner", party.level, party.X, party.Y, 0, "probe"):setSpawnedEntity("blocker")
                else
                        spawn("spawner", party.level, party.X, party.Y, 0, "probe"):setSpawnedEntity("blocker")
   		end
	end
end

function trapteleporter(teleport)

	spawn("teleporter", party.level, party.x, party.y, 0 "teleport_destination"):setTeleportTarget(targetX, targetY, targetFacing)
   	teleport_timer:activate()
   	break
end


function tpCleanup()
   findEntity("teleport_destination"):destroy()
end
What I'm working on right now is finding the proper syntax to get the X, Y coordinates for the entity named "probe" in the targetX and targetY statements.
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

I made a quick working analog of what I've done so far with this particular trap. So people can hopefully see what I'm attempting to do with this.

https://www.dropbox.com/s/tc5kt27j3lamo ... t.rar?dl=0
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

I would suggest that spawners are only useful for vanilla connected actions in the editor. If you are going to actually script the behavior, you can probably skip using spawners altogether.
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

<3 okay, and the reason you don't recommend it? What I need is an entity (that won't block monster pathing) that I can reference back to as the target for the teleport. This entity would spawn at the players location when the party steps on one of the pressure plates. The idea is to pull the player back to the last pressure plate they were on should they fail the puzzle and fall into a pit either intentionally or by accident.

I could do a clone object of one of the monsters and use that instead of just a spawner. Then all I'd need to do to is find that specific monster and grab the X and Y from that. That would resolve any potential spawner issues and resolve my trying to figure out how to get the X and Y value of the spawner itself.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

Killcannon wrote:<3 okay, and the reason you don't recommend it?
It's just that the spawner is a script-less convenience to produce or repeatedly produce a monster or projectile of some kind (like a blob or a fireball). If you are going to devise a scripted situation, then I would think that the spawn function would work just as well or better than the spawner entity.

I have tried the demo map, and followed the solution, and the door opened; however there are situations where the open sound effect plays while the door remains closed. I suspect the door is perhaps being opened and closed in the same instant at times.

Code: Select all

door_name = "dungeon_door_portcullis_25"
door_name1 = "dungeon_door_portcullis_24"

function pitCheck()
  findEntity(door_name):open()
  findEntity(door_name1):open()
 ... 
looking at the script... unless there is a reason I have missed, it would be faster to name dungeon_door_portcullis_25 and 26 to
door_name and door_name1, and just use them without the call to findEntity().

Code: Select all

 --Slightly altered version of the original demo map script.--

-- Pit trap puzzle to open portcullis doors

function pitCheck()
 door_name:open() 
 door_name1:open()
	pits = {{"dungeonpit1", false},
          {"dungeonpit2", false},
          {"dungeonpit3", false},
          {"dungeonpit4", false},
          {"dungeonpit12", false},
          {"dungeonpit13", true},
          {"dungeonpit14", true},
          {"dungeonpit15", false}}
	dts = {{"doortorch1", true},
		  {"doortorch2", true},
		  {"doortorch3", false}}
		
	for i = 1, #pits do
		if findEntity(pits[i][1]):isOpen() ~= pits[i][2] then
			door_name:close()
			door_name1:close()
		end
	for i = 1, #dts do
		if findEntity(dts[i][1]):hasTorch() ~= dts[i][2] then
    		door_name:close()
			door_name1:close()
    	end
  	end
	end
end
What I need is an entity (that won't block monster pathing) that I can reference back to as the target for the teleport. This entity would spawn at the players location when the party steps on one of the pressure plates. The idea is to pull the player back to the last pressure plate they were on should they fail the puzzle and fall into a pit either intentionally or by accident.
If I understand correctly, then it would seem that connecting the plates to a function that stores the location of the last plate is all you would need for this.

Something similar to this, placed in your script:

Code: Select all

last_plate = {}
function setLastPlate(caller)
	if party.x == caller.x and party.y == caller.y then --filters plates activated by monsters.
		last_plate = {caller.x, caller.y, party.facing, caller.level} 
		print(unpack(last_plate)) --delete line when finished
	end	
end
You would then have a record of the last plate that the party activated. You could then use that for the teleporter destination.

Updated demo: https://www.dropbox.com/s/7829pg4x4k7jr ... D.rar?dl=0
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

last_plate = {}
function setLastPlate(caller)
if party.x == caller.x and party.y == caller.y then --filters plates activated by monsters.
last_plate = {caller.x, caller.y, party.facing, caller.level}
print(unpack(last_plate)) --delete line when finished
end
I'm having a problem with this script. It keeps crashing when it gets to the actual teleport

Code: Select all

function trapteleporter(teleport)

	spawn("teleporter", party.level, party.x, party.y, 0, "teleport_destination"):setTeleportTarget(caller.x, caller.y, party.facing, caller.level)
   	teleport_timer:activate()   	
end
It's giving me an 'expected number received string/table' message no matter how I try to reference it back to the last_plate. T.T

- Nevermind on the bottom section I found the issue I left out '()' in the previous line.

Also I was trying the original way I'd planned as well but for some reason
spawn("probe", party.level, party.x, party.y, 0, "teleportprobe") is producing a function arguments expected near 'spawn' error. I've looked at the syntax and according to the website the syntax is correct, as well as all the other code I've seen on the forums.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

Killcannon wrote: Also I was trying the original way I'd planned as well but for some reason
spawn("probe", party.level, party.x, party.y, 0, "teleportprobe") is producing a function arguments expected near 'spawn' error. I've looked at the syntax and according to the website the syntax is correct, as well as all the other code I've seen on the forums.
Check nearby in your code... It's probably not the call to Spawn itself.
- Nevermind on the bottom section I found the issue I left out '()' in the previous line.
Those missing parenthesis are what it means by "function arguments expected".
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

Okay I have to admit that this section of code appears to be well beyond me.
SpoilerShow
last_plate = {}
function setLastPlate(caller)
if party.x == caller.x and party.y == caller.y then --filters plates activated by monsters.
last_plate = {caller.x, caller.y, party.facing, caller.level}
print(unpack(last_plate)) --delete line when finished
end
end
I get what it's trying to do, but I'm failing at seeing how I can actually use it as I cannot seem to reference last_plate to the teleporter script at all.

Code: Select all

	spawn("teleporter", party.level, party.x, party.y, 0, "teleport_destination"):setTeleportTarget(caller.x, caller.y, party.facing, caller.level)
returns a 'got nil' error on the setTeleportTarget and

Code: Select all

	spawn("teleporter", party.level, party.x, party.y, 0, "teleport_destination"):setTeleportTarget(last_plate)
returns a 'number expected got table' error on setTeleportTarget as well. None of this is the most frustrating part though. If I make the coordinates static like this:

Code: Select all

spawn("teleporter", party.level, party.x, party.y, 0,"flytosafety1"):setTeleportTarget(12, 11, party.facing, 1)
I get a 'duplicated entity id' message which I can fix by removing the static name but prevents me from destroying the teleporters via a destroy script. To top it off it appears that the teleporter is also triggering on closed pit traps which it shouldn't because it's only supposed to be called after the isOpen:() comes back true; it's also preventing the damage from going through. So yea.... problems galore right now and simplifying the script down doesn't seem to be helping.

Code: Select all

function pittraps()
	local deathpits = {"dungeonpit1",
					"dungeonpit2",
					"dungeonpit3",
					"dungeonpit4",
					"dungeonpit5",
					"dungeonpit6",
					"dungeonpit7",
					"dungeonpit8",
   		    		"dungeonpit9",
    		   		"dungeonpit10",
     		  		"dungeonpit11",
      		 		"dungeonpit12",
       				"dungeonpit13",
       				"dungeonpit14",
       				"dungeonpit15"}

	for i=1, #deathpits do
	local deathpit = findEntity(deathpits[i])
		if deathpit:isOpen() then
			damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 10)
			spawn("teleporter", party.level, party.x, party.y, 0,"flytosafety1"):setTeleportTarget(12, 11, party.facing, 1)
		end
	end
end
Also returned a "duplicated ID" message which is confusing as hell because there's no additional entities with that name in the dungeon. So my only thought is that the game is trying to spawn the teleporter at every single one of the listed pits and either ignoring the variables that tell it to spawn at the parties location; or is spawning them all at the players location. I'm still testing to see what's going on.

edit

A quick test has told me that indeed the teleporter is spawning regardless of the pits state and is spawning multiple teleporters at once with this script:
SpoilerShow
function pittraps()
local deathpits = {"dungeonpit1",
"dungeonpit2",
"dungeonpit3",
"dungeonpit4",
"dungeonpit5",
"dungeonpit6",
"dungeonpit7",
"dungeonpit8",
"dungeonpit9",
"dungeonpit10",
"dungeonpit11",
"dungeonpit12",
"dungeonpit13",
"dungeonpit14",
"dungeonpit15"}

for i=1, #deathpits do
local deathpit = findEntity(deathpits)
if deathpit:isOpen() then
damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 10)
spawn("teleporter", party.level, party.x, party.y, 0):setTeleportTarget(12, 11, party.facing, 1)
end
end
end


This is the simplest form of what I am wanting to do and I'm not entirely sure why it's doing what it is doing.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

Killcannon wrote:

Code: Select all

spawn("teleporter", party.level, party.x, party.y, 0,"flytosafety1"):setTeleportTarget(12, 11, party.facing, 1)
I get a 'duplicated entity id' message which I can fix by removing the static name but prevents me from destroying the teleporters via a destroy script. To top it off it appears that the teleporter is also triggering on closed pit traps which it shouldn't because it's only supposed to be called after the isOpen:() comes back true; it's also preventing the damage from going through. So yea.... problems galore right now and simplifying the script down doesn't seem to be helping.
If you change the code to something like the following, you can get the id for the teleporter.

Code: Select all

 local temp_id = spawn("teleporter", party.level, party.x, party.y, 0)
temp_id:setTeleportTarget(12, 11, party.facing, 1)

findEntity(temp_id.id):destroy()
or (alternatively)

Code: Select all

 local temp_id =spawn("teleporter", party.level, party.x, party.y, 0).id
 findEntity(temp_id):setTeleportTarget(12, 11, party.facing, 1)

findEntity(temp_id):destroy()



_____________________________________
Here is a quick demo of three methods to examine. One of these should be adaptable to your dungeon.

https://www.dropbox.com/s/bmtpng6bjjc5y ... n.zip?dl=1
Last edited by Isaac on Mon Apr 27, 2015 9:50 am, edited 1 time in total.
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

Thank you so much Isaac your help has thus far been invaluable and I'm learning a lot and I was able to resolve an issue I was having with the script on a different trap with this and learned quite a bit I can apply to some of my others. I am still having issues with applying what you had into what I need it to do for this pit trap. You were correct in that the west version of the 3 you gave was the closest to what I want to do. My problem is this:

I am getting an 'attempt to index local 'pit' (a nil value) error when the party steps over one of the pits. It's at line 9 of the code below. if pit:isOpen() then
SpoilerShow
-- attached to dungeonpits to teleport the party to the last pressure plate

function teleport(caller)
local pit
for x in entitiesAt(caller.level, caller.x, caller.y) do
if x.name == "dungeonpit" then
pit = x
end

end
if pit:isOpen() then
local temp = spawn("teleporter", caller.level, caller.x, caller.y, 0):setTeleportTarget(unpack(transport_3.last_plate)):activate()
spawn("timer", caller.level, caller.x, caller.y, 0):setTimerInterval(0.01):addConnector("activate", self.id,"killTeleport"):activate()
pit:setPitState("closed")
else
return nil
end
end

function killTeleport(caller)
for x in entitiesAt(caller.level, caller.x, caller.y) do
if x.name == "dungeonpit" then
x:setPitState("open")
end
if x.name == "teleporter" then
findEntity(x.id):destroy()
end
end
findEntity(caller.id):destroy()
end
This version of the script only really has the names of the entities changed into my dungeon as I wanted to keep it as close to yours as possible for integration into what I had so far. Before I tore it apart, and really set it to work as I need it too.
Post Reply