Page 1 of 1

{script} Valid destination / "Floor availability check"

Posted: Wed Oct 10, 2012 5:20 pm
by Leki
Hi. I am thinking about some idea and function conected with it. Maybe someone can help me with that.
We can use it in many ways. For example, to create a teleport to random valid location in the level (or dungeon as well).

I guess that this "floor availability" check can be based on this viewtopic.php?p=31998#p31998, but test must be improved in some way.

Edit: Maybe we can teleport an object to cell address and then check if object exist there?

Re: {script} Valid destination / "Floor availability check"

Posted: Wed Oct 10, 2012 10:06 pm
by Edsploration
Teleport to random location!? Awesome Idea Leki!!! And I realized I know a way to do it! So I did it!

My method works around the logic of a monster spawner won't spawn a monster if the space is blocked. This is a way to detect if a space is solid rock or not, even if there are no entities there. I'll probably repost this in the useful script repository/thread as well.

I included a few extra parameters and checks for non-valid target teleport locations.

Options
allowTeleFrag = true | false :arrow: Whether to teleport on top of a monster, killing it (no XP gained this way), or reroll for a new target location.
allowRocked = true | false :arrow: Whether to teleport into rock, killing the whole party! OUCH! (1000 damage to all split 50% physical, 50% earth), or reroll for a new target location.
dodgeRockLuck = 0 to 1 :arrow: The probability to reroll instead of rocking the party. This parameter is to reduce the chance of landing in rock, because it can be a little too likely for dungeons with many rock spaces.

Setup
We need three pieces to get the random teleport working:
  1. A custom monster type definition. (The "probe".) This is used for a "valid location" check where a monster spawner is placed which then attempts to place the monster probe.

    Code: Select all

    cloneObject{
    	name = "teleport_probe",
    	baseObject = "snail",
    }
    
  2. A timer helper object. To teleport the party we must place a teleporter on top of it, and then delete the teleporter after a tiny delay.
    • The timer's ID must be "teleport_timer" to work with the script.
    • The timer interval can be short. I used 0.1 seconds.
    • The timer must call the tpCleanup() function, as well as deactivate itself.
  3. The teleport script itself! Call the teleportRandom() function to trigger a random teleport! You can use a button, pressure plate, item, spell, whatever can call it!

    Code: Select all

    function teleportRandom()
    
    	---- Define teleporter behavior ----
    	local allowTeleFrag = true      ----
    	local allowRocked = true        ----
    	local dodgeRockLuck = 0.8       ----
    	------------------------------------
    	
    	local rockedMessage = "Teleported into Rock! A gruesome death!"
    	
    	local allMonsters = {"crab", "crowern", "goromorg", "green_slime", "herder", "herder_big", "herder_small", "herder_swarm", "ice_lizard", "ogre", "scavenger", "scavenger_swarm", "shrakk_torr", "skeleton_archer", "skeleton_archer_patrol", "skeleton_warrior", "snail", "spider", "tentacles", "uggardian", "warden", "wyvern"}
    	
    	local targetX = math.floor(math.random()*32)
    	local targetY = math.floor(math.random()*32)
    	local targetFacing = math.floor(math.random()*4)
    	
    	local teleportSuccess = false
    	
    	spawn("spawner", party.level, targetX, targetY, 0, "probe"):setSpawnedEntity("teleport_probe"):activate()
    	
    	for i in entitiesAt(party.level, targetX, targetY) do
    		if i.name == "teleport_probe" then
    			teleportSuccess = true
    			i:destroy()
    			spawn("teleporter", party.level, party.x, party.y, 0, "teleport_random"):setTeleportTarget(targetX, targetY, targetFacing)
    			teleport_timer:activate()
    			break
    		end
    	end
    	
    	probe:destroy()
    	
    	if teleportSuccess == false then
    	
    		local rockTarget = false
    		local monsterTarget = false
    		
    		-- Test for reason of teleport fail --
    		if allowRocked or allowTeleFrag then
    			local tempBlockage = entitiesAt(party.level, targetX, targetY)
    			if tempBlockage() == nil then
    				rockTarget = true
    			end
    			for i in entitiesAt(party.level, targetX, targetY) do
    				for j=1,# allMonsters do
    					if i.name == allMonsters[j] then
    						monsterTarget = true
    						break
    					end
    				end
    				if monsterTarget == true then
    					break
    				end
    			end
    		end
    		
    		-- Should we rock the party? --
    		if allowRocked and rockTarget and math.random() > dodgeRockLuck then
    			spawn("teleporter", party.level, party.x, party.y, 0, "teleport_random"):setTeleportTarget(targetX, targetY, targetFacing)
    			teleport_timer:activate()
    			hudPrint(rockedMessage)
    			-- Everyone takes 1000 damage, 50% physical, 50% earth --
    			for i=1,4 do
    				party:getChampion(i):damage(500, "physical")
    				party:getChampion(i):damage(500, "poison")
    				party:getChampion(i):playDamageSound()
    			end
    			return
    		end
    		
    		-- Should we telefrag a monster? --
    		if allowTeleFrag and monsterTarget then
    			spawn("teleporter", party.level, party.x, party.y, 0, "teleport_random"):setTeleportTarget(targetX, targetY, targetFacing)
    			teleport_timer:activate()
    			return
    		end
    		
    		-- No suitable location found, try again --
    		teleportRandom()
    	end
    end
    
    function tpCleanup()
    	findEntity("teleport_random"):destroy()
    end
    
Those three options I mentioned are manually editable at the top of the code. They could easily be changed to arguments accepted by the function, but I did it this way because variable scoping in LUA is still weird and scary to me.

Cheers!

Re: {script} Valid destination / "Floor availability check"

Posted: Wed Oct 10, 2012 10:15 pm
by Komag
can you use a table of the monster names instead of the big list of "or"s?

Re: {script} Valid destination / "Floor availability check"

Posted: Wed Oct 10, 2012 10:58 pm
by Edsploration
Komag wrote:can you use a table of the monster names instead of the big list of "or"s?
Good idea. The code has been updated.

Edit: Fixed another bug where snails could not be telefragged despite being in the monster table.

Re: {script} Valid destination / "Floor availability check"

Posted: Thu Oct 11, 2012 11:53 am
by Leki
Good solution for teleporting Ed!

But what we have to do with "is there floor",test? Does not matter if object is there or monster etc...
Can we use level map in dungeon.ini file in some way - without manual copy of this part and creating table in our script - if its possible?

Re: {script} Valid destination / "Floor availability check"

Posted: Thu Oct 11, 2012 5:52 pm
by Edsploration
There very well may be a simpler way to check for floor, but I didn't see anything that would work in the scripting reference. If there is a way to pull data straight from the level map, I don't know of it. That was the first thing I considered doing, by the way. I've conceded more and more that hacky solutions are acceptable because the editor is still young and while it is a great piece of work, it is still somewhat limiting.

This method does work fairly seamlessly and effectively in my tests. And it does clean-up all the objects which are generated for the teleport to work. Although more functionality could be added. For example, I make no checks for blockages like statues and default to reroll if those spaces are landed on.