Spike trap script help

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
minmay
Posts: 2790
Joined: Mon Sep 23, 2013 2:24 am

Re: Spike trap script help

Post by minmay »

Isaac wrote:

Code: Select all

0000010
This is wrong in two different ways.
1. Numeric literals in Lua are decimal by default. "0000010" will evaluate to decimal 10.
2. Even if this were a binary literal, you would have the bits reversed. Ignore immunities is bit 6, not bit 1.
The constant you want to use is 0x40 or decimal 64. Lua does not have binary or octal literals.
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

minmay wrote:
Isaac wrote:

Code: Select all

0000010
This is wrong in two different ways.
1. Numeric literals in Lua are decimal by default. "0000010" will evaluate to decimal 10.
2. Even if this were a binary literal, you would have the bits reversed. Ignore immunities is bit 6, not bit 1.
The constant you want to use is 0x40 or decimal 64. Lua does not have binary or octal literals.
Thank you, I remember now from the LoG2 script ref. 8-)
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

Okay need some more help here, I got the damage portion of my script running fine with the help so far. Now, I'm trying to activate/disable the TriggeredByParty/Monster variables on the pressure plates here when the lever is activated/deactivated but it's tossing me an "attempt to call method 'setTriggeredByParty' (a nil value)" error when the lever is switched. I've dabbled with this now all morning and cannot for the life of me figure out what I did wrong. Here's a copy of the script I have below any help would be great <3 :
SpoilerShow
function spiketrap()
local plates = {"dm_spikes_floortrap_2",
"dm_spikes_floortrap_3",
"dm_spikes_floortrap_4",
"dm_spikes_floortrap_5",
"dm_spikes_floortrap_6",
"dm_spikes_floortrap_7",
"dm_spikes_floortrap_8",
"dm_spikes_floortrap_9"}

for i=1, #plates do
findEntity(plates)
if lever_4:getLeverState() == "deactivated" then
plates:setTriggeredByParty(false)
plates:setTriggeredByMonster(false)
playSound("pressure_plate_released")
else
if lever_4:getLeverState() == "activated" then
plates:setTriggeredByParty(true)
plates:setTriggeredByMonster(true)
playSound("pressure_plate_pressed")
end
end
end
end


It's been edited about a million times too, the website says that the variables need to be 'enable' 'disable' but what I've found on the forums says 'true' 'false'
Last edited by Killcannon on Mon Apr 20, 2015 11:25 pm, edited 1 time in total.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

findEntity(plates) Does not actually assign anything here. It needs to either be used in the script in place of the object, or it needs to be assigned to a variable, and the variable used as the object.

Code: Select all

function spiketrap()
	local plates = {"dm_spikes_floortrap_2",
					"dm_spikes_floortrap_3",
					"dm_spikes_floortrap_4",
					"dm_spikes_floortrap_5",
					"dm_spikes_floortrap_6",
					"dm_spikes_floortrap_7",
					"dm_spikes_floortrap_8",
					"dm_spikes_floortrap_9"
					}
	
	for i=1, #plates do
		local plate = findEntity(plates[i])
		if lever_4:getLeverState() == "deactivated" then
				plate:setTriggeredByParty(false)
				plate:setTriggeredByMonster(false)
				playSound("pressure_plate_released")
		else
			if lever_4:getLeverState() == "activated" then
				plate:setTriggeredByParty(true)
				plate:setTriggeredByMonster(true)
				playSound("pressure_plate_pressed")
			end
		end
	end
end

EDIT:
The lever_4 object also needs to be attached to spikeTrap, in order to update the plates, once they don't respond to the party. This would cause the plate press/release sound to play when not wanted. Here is a modified version that accounts for the lever.

Code: Select all

function spiketrap(caller)
	local plates = {"dm_spikes_floortrap_2",
					"dm_spikes_floortrap_3",
					"dm_spikes_floortrap_4",
					"dm_spikes_floortrap_5",
					"dm_spikes_floortrap_6",
					"dm_spikes_floortrap_7",
					"dm_spikes_floortrap_8",
					"dm_spikes_floortrap_9"
					}
	
	for i=1, #plates do
		local plate = findEntity(plates[i])
		if lever_4:getLeverState() == "deactivated" then
				plate:setTriggeredByItem(false)
				plate:setTriggeredByParty(false)
				plate:setTriggeredByMonster(false)
		else
				plate:setTriggeredByItem(true)
				plate:setTriggeredByParty(true)
				plate:setTriggeredByMonster(true)
		end
		soundEffect(caller)
	end
end		
		
function soundEffect(caller)
	if caller.name ~= "lever" then	
		if caller:isUp() then
			playSound("pressure_plate_released")
		else playSound("pressure_plate_pressed")
		end	
	end			
end
https://www.dropbox.com/s/o5ehl651416iu ... e.zip?dl=0
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

Thank you so much for the quick replies on this and helping me out with all these silly little problems. I also thank everyone that's helped me so far and have taken the time out of the day to do so. It really means a lot to me. I'm quite the noob, but I'm figuring this out with each encountered problem. Speaking of problems, I ran into another problem adapting this to a different trap. This one involving the pit trap. What I've done is added a hidden pressure plate over the pit traps which triggers the following script. The script is supposed to check if the pit trap is open, and if it is to "kill" the character/monster on the tile. The problem I'm running into is that it's not actually applying the damage.

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() == "true" then
			damagescript.deathtrap(t)
		else
			return false	
		end
	end
end
I've also tried this this way as well:

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() == "true" then
			damageTile(t.level, t.x, t.y, 0, 6, "poison", 9001)
		else
			return false	
		end
	end
end
I was thinking it had to do with how it's checking the " if deathpit:isOpen() == "true" then " statement but I checked and have tried every variable I can think of and the syntax for pit:isOpen() appears to be correct. Also for some reason this seems to need the "else -> return false" bit of the statement or it crashes when stepping over a closed pit. So I cannot tell if it's always returning false ... I'm using the wrong syntax ... or I dun simply goofed up in my translation of what I learned previously.
alois
Posts: 112
Joined: Mon Feb 18, 2013 7:29 am

Re: Spike trap script help

Post by alois »

You are damaging the tile where "t" is (damageTile(t.level etc)), but you have not defined "t"; I think that

Code: Select all

     damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 9001)
should do the trick...

Alois :)
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

Thank you for that Alois, that fixed the 'returns nil' error I was getting. Which brings up a question in the script that Issac gave; I'm not seeing where 't' was defined either unless it was defined in the deathtrap(t) portion of the script?

I did manage to also resolve another issue where the trap wasn't triggering when crossing an open pit. It appears that the trigger pit:isOpen() is an auto check itself and doesn't need a quantifying check to ensure it is true or false. I.E. the statement pit:isOpen == "true" is redundant as the isOpen already just returns a true or false. Meaning the check somehow was wiping the statements check and interestingly enough while not producing any errors was causing anything in the following statement to simply be skipped until it reached an else or end. As an example:

Code: Select all

	local deathpit = findEntity(deathpits[i])
		if deathpit:isOpen() ~= "true" then
                        return false
                else
			damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 9001)
Would kill anything that passed over the tile regardless of what the state actually was. The solution of course is to simply remove the x="true/false" bit of code and you end up with the following as the final code for this:

Code: Select all

	local deathpit = findEntity(deathpits[i])
		if deathpit:isOpen() then
			damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 9001)
Now I can move onto the next iteration of this trap. I don't actually want to outright kill the party at any point of the adventure. This was just to get the traps and damage to work properly at this level. What I now need to do is figure out how to significantly damage and then teleport the player back to the tile that they were on previously; while killing monsters that pass over it. I believe something like this will work:

Code: Select all

if class.monster then
damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 9001)
else
damageTile(deathpit.level, deathpit.x, deathpit.y, 0, 6, "poison", 20)
Teleport:setTeleportTarget(x, y, facing, [level])
I've yet to look up the actual syntax and write the code. The biggest problem I see here is going to be figuring out how to tell the program that I need it to teleport the party to the previous tile they were on instead of a fixed coordinate. A solution being when they step on a pressure plate the script records that position and the position is rewritten every time a pressure plate is activated then the teleporters simply call the X,Y, Facing of that script. If anyone has any ideas on how to accomplish that I'd be really appreciative.
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Spike trap script help

Post by Killcannon »

After fiddling with this today and a metric ton of research, this is what I've come up with so far. It's no where near complete but it's a start.

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("blocker")
	local targetY = findEntity("blocker")
	local targetFacing = party.facing

   local teleportSuccess = false
   
   spawn("spawner", party.level, targetX, targetY, 0, "probe"):setSpawnedEntity("blocker"):activate()
   
function trapteleporter()

   for i in entitiesAt(party.level, targetX, targetY) do
      if i.name == "blocker" then
         	teleportSuccess = true
         	i:destroy()
         	spawn("teleporter", party.level, party.x, party.y, 0 "teleport_destination"):setTeleportTarget(targetX, targetY, targetFacing)
         	teleport_timer:activate()
         	break
      end
   end
end


function tpCleanup()
   findEntity("teleport_destination"):destroy()
end
Essentially what I have here is a script to be activated when one of the safe spots is activated. Activating the pressure plate will destroy any spawned "blocker" that are active and spawn a "blocker" at that location. Then a second part for when you go over the pit to spawn the teleporter with it's destination set to the the same location as the blocker. The third part is to clean up the teleporter that's spawned itself via a timer. Now the question is, can I leave this in a single script and call the parts I need via other scripts when I need them? Or do I have to figure out a way to call the destination in the first script into the second?
alois
Posts: 112
Joined: Mon Feb 18, 2013 7:29 am

Re: Spike trap script help

Post by alois »

Killcannon wrote:

Code: Select all

	local targetX = findEntity("blocker")
	local targetY = findEntity("blocker")
In the lines above, both targetX and targetY refer to the same object (the blocker whose id is "blocker"), not to its (X,Y) position; I do not think that the script can work in this way...

Alois :)
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Spike trap script help

Post by Isaac »

@Killcannon: If you post a step by step list of the exact intentions ~what you need to happen from the script. There are some here who will look through it, and not just spot needed corrections, but could then suggest better ways to implement it. Myself, I'm not entirely sure of what your script is attempting/compensating. Parts of the script seem a little bit round-about.
Post Reply