Help with teleport spell?

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
Post Reply
User avatar
jxjxjf
Posts: 33
Joined: Fri Oct 24, 2014 6:26 am

Help with teleport spell?

Post by jxjxjf »

So, like the title suggests, I'm working on a spell that teleports the party a short distance in the direction they're facing. It shouldn't function exactly like a teleport, because I want them to be stopped by walls/doors, but I don't want it to be stopped by monsters. The idea is to give some more spells to a kind of "support mage", so moving through monsters is pretty important to the concept.

The problem is, Map:isBlocked() and Map:isObstacle() both return true for tiles with a monster on it (I really don't know what the difference is between these functions). checkLineofFire() (which is necessary to detect doors) also catches on monsters (as you would expect), but checkLineOfSight() DOESN'T catch on a bunch of things, including trees.

I've tried coding my own checkLineOfFire(), but I really don't know how that's done, because I can't figure out how to access component lists and I'm not even sure how I would check what kind of components an entity held even if I could access them dynamically.

So, to reiterate, the spell should check some number of tiles in front of the party based on the direction they're facing. If it finds any kind of obstacle besides a monster, it should stop and try to teleport the party to the tile farthest before the obstacle, otherwise it moves them to the farthest checked tile. Some checks to stop the party from teleporting on top of a monster should also be done (no free tele-frags).

Does anyone have any ideas how, really, any of this could be done? It really seems like a custom checkLineOfFire() is the key, but maybe I'm missing something far simpler?
GoldenShadowGS
Posts: 168
Joined: Thu Oct 30, 2014 1:56 am

Re: Help with teleport spell?

Post by GoldenShadowGS »

I just started working on my own teleport spell. My plan is to use a projectile that teleports the party to the impact site. If you want it to teleport through monsters, you could set the projectile to ignore monsters.
minmay
Posts: 2789
Joined: Mon Sep 23, 2013 2:24 am

Re: Help with teleport spell?

Post by minmay »

IIRC in Grimrock 1 this was accomplished by creating a spawner and trying to spawn a monster from it. If it succeeded, that meant the square was clear, so you'd delete the resulting monster and teleport the party there. If it failed, that meant there was something in the way.
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.
GoldenShadowGS
Posts: 168
Joined: Thu Oct 30, 2014 1:56 am

Re: Help with teleport spell?

Post by GoldenShadowGS »

Here is what I have so far.

Script Entity in dungeon named "script_teleport"

Code: Select all

function partyteleport(self, what, entity)
	local x = self.go.x
	local y = self.go.y
	local facing = party.facing
	local elevation = self.go.elevation
	local level = self.go.level
	local movingmonster = false
	local pfacing = self.go.facing
	local partyblock = false
	if entity ~= nil then
		if entity:getComponent("monster") then
			if entity.monster:isMoving() then
				movingmonster = true
			end
		end
	end
	if party.x == x and party.y == y and party.elevation == elevation and party.level == level then
		playSound("spell_fizzle")
	else
		if party.map:isObstacle(x, y, elevation) or party.map:isBlocked(x, y, elevation) then
			if pfacing == 0 then
				y = y + 1
			elseif  pfacing == 1 then
				x = x - 1
			elseif  pfacing == 2 then
				y = y - 1
			elseif  pfacing == 3 then
				x = x + 1
			end
			if party.map:isObstacle(x, y, elevation) or party.map:isBlocked(x, y, elevation) then
				playSound("spell_fizzle")
			elseif party.x == x and party.y == y and party.elevation == elevation and party.level == level then
				playSound("spell_fizzle")
			else
				party:setPosition(x, y, facing, elevation, level)
				spawn("teleportation_effect",level,x,y,facing,elevation)
			end
		else
			if movingmonster == true then
				if pfacing == 0 then
					y = y + 1
				elseif  pfacing == 1 then
					x = x - 1
				elseif  pfacing == 2 then
					y = y - 1
				elseif  pfacing == 3 then
					x = x + 1
				end
				if party.x == x and party.y == y and party.elevation == elevation and party.level == level then
					partyblock = true
				end
				if party.map:isObstacle(x, y, elevation) or party.map:isBlocked(x, y, elevation) and partyblock == false then
					if pfacing == 0 then
						y = y + 1
					elseif  pfacing == 1 then
						x = x - 1
					elseif  pfacing == 2 then
						y = y - 1
					elseif  pfacing == 3 then
						x = x + 1
					end 
					if party.x == x and party.y == y and party.elevation == elevation and party.level == level then
						playSound("spell_fizzle")
					else
						if partyblock == true then
							if pfacing == 0 then
								y = y - 2
							elseif  pfacing == 1 then
								x = x + 2
							elseif  pfacing == 2 then
								y = y + 2
							elseif  pfacing == 3 then
								x = x - 2
							end
							party:setPosition(x, y, facing, elevation, level)
							spawn("teleportation_effect",level,x,y,facing,elevation)
						else
							party:setPosition(x, y, facing, elevation, level)
							spawn("teleportation_effect",level,x,y,facing,elevation)
						end
					end
				else
					if pfacing == 0 then
						y = y - 1
					elseif  pfacing == 1 then
						x = x + 1
					elseif  pfacing == 2 then
						y = y + 1
					elseif  pfacing == 3 then
						x = x - 1
					end
					party:setPosition(x, y, facing, elevation, level)
					spawn("teleportation_effect",level,x,y,facing,elevation)
				end
			else
				party:setPosition(x, y, facing, elevation, level)
				spawn("teleportation_effect",level,x,y,facing,elevation)
			end
		end
	end
end
spells.lua

Code: Select all

defineSpell{
	name = "teleport_spell",
	uiName = "Teleport",
	skill = "air_magic",
	requirements = {"air_magic", 3, "concentration", 3},
	gesture = 1478963,
	manaCost = 50,
	icon = 14,
	spellIcon = 13,
	description = "Teleport the party a short distance",
	onCast = function(champion, x, y, direction, elevation, skillLevel)
		local s = spawn("open_door",party.level,party.x,party.y,party.facing,party.elevation)
		s.projectile:setIgnoreEntity(party)
		s.projectile:setVelocity(15)
		s.projectile:addConnector("onProjectileHit", "script_teleport", "partyteleport")
	end,
}
Everything works except for one case I've found so far. If your projectile hits a monster, it correctly teleports you in front of it, but if the monster is moving towards you, you will end up teleporting behind it due to the logic of the script. What happens is when you hit a monster moving towards you, the hit registers on the tile it is leaving and that tile is not flagged as an obstacle anymore, so you end up being teleported behind it. What I need to do is put some kind of check like:

if entity.monster:isMoving() then
--fizzle spell
end

However, the entity can be anything and the game doesn't like you to call components that don't exist. So if you shoot the spell at a door, the game will crash.


Otherwise, casting the spell sends a little ball of light that teleports you to the tile it lands on. There are checks to make sure you don't end up inside a blocked tile. The script tries to move you one space back from where the teleport lands if it is blocked(which always happens when you hit a monster). If for somereason that space becomes blocked too, then the spell fizzles. The point blank spell always fizzles.

EDITED updated with improved script
Last edited by GoldenShadowGS on Sun Nov 30, 2014 6:56 am, edited 2 times in total.
GoldenShadowGS
Posts: 168
Joined: Thu Oct 30, 2014 1:56 am

Re: Help with teleport spell?

Post by GoldenShadowGS »

Also, does anyone know how I can avoid needing to split the script into two sections. I don't know else to write the part with the onProjectileHit connector.
GoldenShadowGS
Posts: 168
Joined: Thu Oct 30, 2014 1:56 am

Re: Help with teleport spell?

Post by GoldenShadowGS »

I finally got it working as I initially intended. No teleporting behind enemies walking towards you, you can teleport right next to enemies walking away from you.

Updated above post with new script.
Post Reply