Page 1 of 2

[Solved]Assistance in creating a proper floor_trigger puzzle

Posted: Thu Feb 19, 2015 12:20 am
by Slayer82
I added this issue to the 'Ask a simple question, get a simple answer thread', but the issue has yet to be resolved.

I am trying to put three particular items on a floor trigger to open some mine_door_spears nearby. The items are dropped - not placed, so an alcove is not wanted. Once the items are dropped they open the door_ spear, but I need the items to be destroyed. I wanted it to only accept three specific items, and any other item dropped is obviously lost. I have used a script_auto_trigger to achieve this, but dropping any item opens the spear doors.
I have looked through the forums, but I am unable to make the script work. I have added destroy terms, but that just crashes back to the editor.
SpoilerShow
function execute(trigger)
function surfaceContains(surface, item)
for v,i in surface:contents() do
if i.go.name == item then return true
end
end
end

function spawnSecretItems()
if surfaceContains(floor_trigger_12.surface, "blue_gem") or
surfaceContains(floor_trigger_12.surface, "green_gem") or
surfaceContains(floor_trigger_12.surface, "red_gem") then
mine_door_spear_79.door:open()
else
mine_door_spear_79.door:close()
end
end

end
self.go.floortrigger:addConnector('onActivate',self.go.id,'execute')
Specifically, I would like the blue gem to open mine_spear_door_79, the green gem for mine_spear_door_80, and red for number 81. Not only should the gems open an individual door, but they should also spawn items in each of their designated areas/lots.

Any help would be appreciated.

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Thu Feb 19, 2015 1:05 am
by minmay
FloorTrigger is not an appropriate class for this as it cannot be triggered every time a new item is added to the square (without a lot of hacks), only the first item. You should use Map:entitiesAt() on a timer to iterate over all items on the square instead. If you find the item and want to destroy it, don't use GameObject:destroy(), use GameObject:destroyDelayed().

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Thu Feb 19, 2015 2:56 am
by Slayer82
Thanks for the advice.

I'm still trying to understand lua scripting and your advice makes a lot of sense. I feel better knowing there's another solutions now.
I'll try and make something that'll work and post it when I've made it.

Cheers.

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Thu Feb 19, 2015 11:42 am
by Slayer82
I'm unable to figure this out and require help.
I don't properly understand what scripting is required to manage this problem.
Once I drop the items from the height, I need each one to open a different door adjacent to the pit. There isn't a floor_trigger or script now, just a normal tile.
Item 1 opens one nearby gate and spawns the reward. Item 2 another, and so on.
The items need to be destroyed so that the player can add another item in the future. I do not know how to make this work.
Your suggestion of adding a timer confuses me, as the concept of the puzzle is to add choice. Nothing you have mentioned would seem difficult to others, but it is to me; I'm lost.

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Thu Feb 19, 2015 2:01 pm
by Frenchie
I'm thinking in the line of this, but it might not be 100% correct (maybe 50%):

Code: Select all

local x12 = floor trigger 12 X coordinate - - should be known
local y12 = floor trigger 12 Y coordinate - - should be known
local gem = { "blue_gem", "green_gem", "red_gem" }
     for i = 1,3 do
          for e in map:entitiesAt(x12,y12) do if e == gem[ i ] then mine_door_spear_79.door:open()
          e:destroyDelayed()
          spawn( "reward" )
          end
     end 
end
It checks for items at x12,y12 3x and if it is one of the gems it opens the door and destroys the item. At least that is what I intended to do in my poor lua programming skills. It probably gets an error if 2 or 3 gems are there.

If you want each gem to open a different door it should look like this:

Code: Select all

local x12 = floor trigger 12 X coordinate - - should be known
local y12 = floor trigger 12 Y coordinate - - should be known
local gem = { "blue_gem", "green_gem", "red_gem" }
local exit = { "mine_door_spear79", "mine_door_spear80", "mine_door_spear81" }
local rew-x = { ... } - - X coordinates rewards
local rew-y = { ... } - - Y coordinates rewards
     for i = 1,3 do
          for e in map:entitiesAt( x12, y12 ) do if e == gem[ i ] then exit[ i ].door:open()
          e:destroyDelayed()
          spawn( "reward", rew-x[ i ], rew-y[ i ] ) 
          end
     end 
end
Like I said it's not perfect and treat it as a basis to start from and make it working.

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Fri Feb 20, 2015 9:49 am
by Slayer82
Again, cheers on the help Frenchie.
I just can't seem to get it to work as I just receive different errors each time I change the script.

Hopefully, I'll figure it out soon.

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Sun Feb 22, 2015 7:13 pm
by Frenchie
Love to see the final version. Most of the time I do something very simple and if that works expand. And look through lots of scripts of others for inspiration...

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Sun Feb 22, 2015 7:57 pm
by Azel
I had a similar task, where the Player needs to place items on pressure plates that are unreachable (hence a Throw or a Drop). Then, after a certain time interval I clear the pressure plates of any and all items. Originally I was trying to locate the items and then Destroy them as well, but the script became very clunky and after awhile I just felt dirty!

So, I found a much cleaner way to achieve this...

I place an Invisible Teleporter on top of each pressure plate. The default state is "deactivated" and they are triggered only by Items. Under normal conditions Items are freely placed on the pressure plates, but then, after a period of time (or after a Trigger event) I simply activate each Invisible Teleporter and viola! Every single Item is transported to some hidden location on the Map. I typically place a Void tileset somewhere and refer to that location as the Trash Can.

For added realism I shake the camera to indicate that the environment has changed. I recommend this, or at the very least play a Sound.

Granted the items are not destroyed but there is no need to destroy them, since they are placed in a location that is off limits to the Player. This is a very clean way to achieve this, as it eliminates any need to do a map:allEntities, findEntity, locate X,Y coordinates, etc.

Instead, all logic is condensed to two lines of code:

invisible_teleporter_1.controller:activate();
invisible_teleporter_1.controller:deactivate();

Hope this helps!

Re: Assistance in creating a proper teleportation/floor puzz

Posted: Mon Feb 23, 2015 1:35 am
by Slayer82
It's great that you're offering productive solutions. Thank you.

I do however, still need the pressure_plate to recognise the green, blue, and red gem for each of the different gates. Gates which hold the respective spawned prizes.
Thanks to both you and Frenchie, I almost have it... But not yet.
SpoilerShow
function wishingWell()
invisible_teleporter_2.controller:activate();
invisible_teleporter_2.controller:deactivate();
local x23 = beach_pressure_plate_6
local y31 = beach_pressure_plate_6
local gem = { "blue_gem", "green_gem", "red_gem" }
local exit = { "mine_door_spear_79", "mine_door_spear_80", "mine_door_spear_81" }
local rew x = { spawner_4 }
local rew y = { spawner_4 }
end
for i = 1,3 do
for e in map:entitiesAt(x23, y31) do if e == gem[ i ] then exit[ i ].door:open()
e:destroyDelayed()
spawn( "reward", rew-x[ i ], rew-y[ i ] )
end
end
end
I get an "attempt to index global 'map' a nil value" error at the 'map:entitiesAt' part.
If I can get past that, then it should work.

Re: Assistance in creating a proper floor_trigger puzzle

Posted: Mon Feb 23, 2015 1:55 am
by minmay
the "script" frenchie gave you is digital diarrhea and azel's entire post is completely irrelevant

you use a timer because you need to check the tile repeatedly in case new items are added, since only the first item will press down the plate
the way you would normally do this is to create a timer with an interval of, say, 0.1 seconds, then add a connector to a script_entity containing code like this:

Code: Select all

function checkPlate()
  local matches = {
    ["blue_gem"] = "mine_door_spear_79",
    ["green_gem"] = "mine_door_spear_80",
    ["red_gem"] = "mine_door_spear_81",
  }
  for e in beach_pressure_plate_6.map:entitiesAt(beach_pressure_plate_6.x,beach_pressure_plate_6.y) do
    for gem,door in pairs(matches) do
      if e.name == gem then
        findEntity(door).door:open()
        e:destroyDelayed()
        break
      end
    end
  end
end
this way you don't have to destroy or move items that aren't gems
set currentLevelOnly on the timer to true to save cpu time when offlevel

and uh, frenchie and you should probably use your favoured search engine to find a lua tutorial or something, because your approach of typing random junk is extremely unlikely to work