Monster Invocation 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!
User avatar
Khollik
Posts: 171
Joined: Tue Aug 29, 2017 6:44 pm
Location: France

Re: Monster Invocation spell

Post by Khollik »

I'd really love to have a spirit ally spinning around the party and firing lightning to anyone getting too close, THAT would be very fun :lol:

Meanwhile, I made some good progress and guess what?... It WORKS!! ... Almost.

Code: Select all

		{
			class = "Monster",
			meshName = "undead_mesh",
			footstepSound = "skeleton_footstep",
			hitSound = "skeleton_hit",
			dieSound = "undead_die",
			hitEffect = "hit_dust",
			capsuleHeight = 0.7,
			capsuleRadius = 0.25,
			collisionRadius = 0.6,
			health = 125,
			immunities = { "sleep" },
			resistances = { ["poison"] = "immune" },
			traits = { "undead" },
			evasion = 0,
			exp = 0,
			onInit = function(self)
				self:performAction("rise")
			end,
			onPerformAction = function(self,basicAttack)
			playSound("spell_fizzle")  -- used to check how often onPerformAction is called
			local bx,by = getForward(bodyguard.facing)	
			  for each in party.map:entitiesAt(bodyguard.x+bx,bodyguard.y+by) do
			   if each:getComponent("monster") ~= nil and each.elevation == bodyguard.elevation then
			   local sound = each.name	
			   local strike = math.random(-100,100)
			   if strike >= each.monster:getEvasion() then
			     damageTile(bodyguard.level,bodyguard.x+bx,bodyguard.y+by,bodyguard.facing,bodyguard.elevation,0,"physical",19)
			     playSoundAt(sound.."_hit",bodyguard.level,bodyguard.x+bx,bodyguard.y+by)
			   end
			   end
			  end
			end,
			headRotation = vec(0, 0, 90),
		},
		{
			class = "Brain",
			sight = 5,
			morale = 100,
			onThink = function(self)
local danger = false
local bx,by = getForward(bodyguard.facing)  	
--checks if the bodyguard is in front of a foe
for each in party.map:entitiesAt(bodyguard.x+bx,bodyguard.y+by) do 
   if each:getComponent("monster") ~= nil and each.elevation == bodyguard.elevation then
   danger = true
   self:performAction("basicAttack")
   self:wait()
   else danger = false
   end
end

local h = bodyguard.x - 3
local v = bodyguard.y - 3
local hsup = bodyguard.x + 3
local vsup = bodyguard.y + 3

--checks if there is a foe nearby and moves toward it
for x = h,hsup do       
  for y = v,vsup do
	for each in party.map:entitiesAt(x,y) do
	if each:getComponent("monster") ~= nil and each.name~="bodyguard" then
	   danger = true
	   local target = each.id	
	   self:goTo(target)
	   --local d = each.facing + 2  -- this part doesn't work well
	   --self:turnTowardsDirection(d)
	end
	end
  end
end

--if there is no foe, the bodyguard comes closer to the party
if self.partyOnLevel and danger == false then 
self:moveTowardsParty()
end

			end,
The code may be a little sloppy but I hope it's clear enough.

Now, I do have a companion who checks the presence of ennemies and attack them or just come closer to the party if the area is safe. Still two minor and one major issues :

- I don't know why, the onPerformAction() is called quite often, even if there is no foe at reach.

- I can't find a way to make the Bodyguard turn towards the direction of the target, unless it is just next to it. I tried with turnTowardsDirection() (and would have to script all the possibilities to get right) but I hope there is an easier way. Any help would be warmly welcomed :?:

- And most importantly, as presumed by Zimberzimber, the other monsters simply ignore my bodyguard. I tried by adding a "party" Component to the bodyguard, but then the game crashes. I'm still sratching my head to find a way to go through it :? . Or I will have to find a way to implement that in my mod in a realistic way (an invisible bodyguard??? Only visible to its Master???).

K.
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Monster Invocation spell

Post by akroma222 »

zimberzimber wrote: Fri Jun 15, 2018 8:29 pm What you could do, is have "spirits" that aren't monsters at all, just objects with an attached model and an ethereal looking texture.
Said spirits would have a slight offset from the middle of the tile so they don't collide with monsters visually.
They would also be invulnerable, but either tied to a small radius, have a lifespan, or drain the summoners energy as long as its alive until there's no energy to drain and the spirit dies off.
The spirit, upon detecting a monster on the tile, does stuff. Spawn a tile damage, spawn a projectile, etc...
But this will require creating your own brain from scratch since you don't have a monster component on it.
Zimber, are you referring to something similar to this:
viewtopic.php?f=22&t=9522&p=91725&hilit ... tuo#p91725

Khollik, I played around with various versions of Ganamir's will'o'wisp - it def is an option to consider here (as zimber mentioned)
- as well - alot of the base behaviour is already coded up, you just need to make a few adjustments to Ganamir's script
EG - this is my adapted script for the willowisp
SpoilerShow

Code: Select all

--spawn("timer", willowispScript.level, willowispScript.x, willowispScript.y , willowispScript.facing, willowispScript.elevation, "willowispTimer")
--willowispTimer:addConnector("onActivate", willowispScript, "fuocoFatuo")


spawn("will_o_wisp", willowispScript.level, willowispScript.x, willowispScript.y ,willowispScript.facing, willowispScript.elevation, "wispRestore1")		--, 

datiFuoco = {}

function fuocoFatuo()

	----------------------------
	--- starting settings	 ---
	----------------------------
	
	-- set a timer, calling 'fuocoFatuo' function, timerInterval to 0.001
	
	local xMin = -0.5		---------------------------------------
	local xMax = 0.5		---									---
	local yMin = -0.5		---  area of will o wisp movements	---
	local yMax = 0.5		---  								---
	local zMinimo = -0.5	---									---
	local zMassimo = 0.5	---------------------------------------
	
	local incrementoX = 0.002	-----------------------------------------------------------
	local incrementoY = 0.002	--- will o wisp position incrementon each function call	---
	local incrementoZ = 0.002	-----------------------------------------------------------
	
	local valoreSalto = 0.0	--- jump distance while changing direction ---
	
	-- looking for wisps
	local nFuocoFatuo = 1
	local fuocoFatuo = findEntity("will_o_wisp_" .. nFuocoFatuo)
		
	-- turning on and off cicle and movement
	while fuocoFatuo ~= nil do -- if u make it killable u need to change this cicle with a for cicle, from 1 to higher number of will o wisp u put in a map
	
		zMin = (fuocoFatuo:getElevation() * 3) +1 + zMinimo
		zMax = (fuocoFatuo:getElevation() * 3) +1 + zMassimo
		
		-- starting a table at game start
		if datiFuoco[nFuocoFatuo] == nil then
			datiFuoco[nFuocoFatuo] = {}
			datiFuoco[nFuocoFatuo]["x"] = xMin
			datiFuoco[nFuocoFatuo]["y"] = yMin
			datiFuoco[nFuocoFatuo]["z"] = zMin
			datiFuoco[nFuocoFatuo]["xAumenta"] = true
			datiFuoco[nFuocoFatuo]["yAumenta"] = true
			datiFuoco[nFuocoFatuo]["zAumenta"] = true
			datiFuoco[nFuocoFatuo]["siAccende"] = false
			datiFuoco[nFuocoFatuo]["inizioSpegnimento"] = 0
			datiFuoco[nFuocoFatuo]["tempoSpegnimento"] = 0
			datiFuoco[nFuocoFatuo]["inizioAccensione"] = 0
			datiFuoco[nFuocoFatuo]["tempoAccensione"] = 0
			datiFuoco[nFuocoFatuo]["dannoExp"] = 0
		else
		
		end
		
		if fuocoFatuo.light ~= nil then
		
			-- turn on
			if datiFuoco[nFuocoFatuo]["siAccende"] == true then
				if Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then -- bigger value after >= more time they remain off
					
					datiFuoco[nFuocoFatuo]["inizioAccensione"] = Time.currentTime()
					local tempoAccensione = math.random() +1
					datiFuoco[nFuocoFatuo]["tempoAccensione"] = tempoAccensione
					fuocoFatuo.light:fadeIn(tempoAccensione)
					fuocoFatuo.particle:fadeIn(tempoAccensione)
					datiFuoco[nFuocoFatuo]["siAccende"] = false
					
				else
				end
				
			-- turn off
			elseif datiFuoco[nFuocoFatuo]["siAccende"] == false then
				if Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioAccensione"] + (datiFuoco[nFuocoFatuo]["tempoAccensione"] * 2) then -- bigger value after >= more time they remain on
					
					datiFuoco[nFuocoFatuo]["inizioSpegnimento"] = Time.currentTime()
					local tempoSpegnimento = (math.random()* 3)+1
					datiFuoco[nFuocoFatuo]["tempoSpegnimento"] = tempoSpegnimento
					fuocoFatuo.light:fadeOut(tempoSpegnimento)
					fuocoFatuo.particle:fadeOut(tempoSpegnimento)
					datiFuoco[nFuocoFatuo]["siAccende"] = true
					
				else
				end

			end
		
		else
		end
		
		-- x axis random direction change
		if Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
			if math.random(1,100) == 1 then
				
				if datiFuoco[nFuocoFatuo]["xAumenta"] == true then
					datiFuoco[nFuocoFatuo]["xAumenta"] = false
				else
					datiFuoco[nFuocoFatuo]["xAumenta"] = true
				end
				
				-- jump
				if datiFuoco[nFuocoFatuo]["xAumenta"] == true then
					if datiFuoco[nFuocoFatuo]["x"] + valoreSalto < 1.4 then
						datiFuoco[nFuocoFatuo]["x"] = datiFuoco[nFuocoFatuo]["x"] + valoreSalto
					else
						datiFuoco[nFuocoFatuo]["x"] = 1.4
					end
				else
					if datiFuoco[nFuocoFatuo]["x"] - valoreSalto > -1.4 then
						datiFuoco[nFuocoFatuo]["x"] = datiFuoco[nFuocoFatuo]["x"] - valoreSalto
					else
						datiFuoco[nFuocoFatuo]["x"] = -1.4
					end
				end
				
			else
			end
		else
		end
		
		-- y axis random direction change
		if Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
			if math.random(1,100) == 1 then
				
				if datiFuoco[nFuocoFatuo]["yAumenta"] == true then
					datiFuoco[nFuocoFatuo]["yAumenta"] = false
				else
					datiFuoco[nFuocoFatuo]["yAumenta"] = true
				end
				
				-- jump
				if datiFuoco[nFuocoFatuo]["yAumenta"] == true then
					if datiFuoco[nFuocoFatuo]["y"] + valoreSalto < 1.4 then
						datiFuoco[nFuocoFatuo]["y"] = datiFuoco[nFuocoFatuo]["y"] + valoreSalto
					else
						datiFuoco[nFuocoFatuo]["y"] = 1.4
					end
				else
					if datiFuoco[nFuocoFatuo]["y"] - valoreSalto > -1.4 then
						datiFuoco[nFuocoFatuo]["y"] = datiFuoco[nFuocoFatuo]["y"] - valoreSalto
					else
						datiFuoco[nFuocoFatuo]["y"] = -1.4
					end
				end
				
			else
			end
		else
		end
		
		-- z axis random direction change
		if Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
			if math.random(1,100) == 1 then
				
				if datiFuoco[nFuocoFatuo]["zAumenta"] == true then
					datiFuoco[nFuocoFatuo]["zAumenta"] = false
				else
					datiFuoco[nFuocoFatuo]["zAumenta"] = true
				end
				
				-- jump
				if datiFuoco[nFuocoFatuo]["zAumenta"] == true then
					if datiFuoco[nFuocoFatuo]["z"] + valoreSalto < (fuocoFatuo:getElevation()* 3) +1 + 1.4 then
						datiFuoco[nFuocoFatuo]["z"] = datiFuoco[nFuocoFatuo]["z"] + valoreSalto
					else
						datiFuoco[nFuocoFatuo]["z"] = (fuocoFatuo:getElevation()* 3) +1 + 1.4
					end
				else
					if datiFuoco[nFuocoFatuo]["z"] - valoreSalto > (fuocoFatuo:getElevation()* 3) +1 -1.4 then
						datiFuoco[nFuocoFatuo]["z"] = datiFuoco[nFuocoFatuo]["z"] - valoreSalto
					else
						datiFuoco[nFuocoFatuo]["z"] = (fuocoFatuo:getElevation()* 3) +1 - 1.4
					end
				end
				
			else
			end
		else
		end
		
		-- moving on x axis
		if datiFuoco[nFuocoFatuo]["xAumenta"] == true then
			if datiFuoco[nFuocoFatuo]["x"] < xMax then
				datiFuoco[nFuocoFatuo]["x"] = datiFuoco[nFuocoFatuo]["x"] + incrementoX
			elseif datiFuoco[nFuocoFatuo]["x"] >= xMax and Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
				datiFuoco[nFuocoFatuo]["xAumenta"] = false
			end
		elseif datiFuoco[nFuocoFatuo]["xAumenta"] == false then
			if datiFuoco[nFuocoFatuo]["x"] > xMin then
				datiFuoco[nFuocoFatuo]["x"] = datiFuoco[nFuocoFatuo]["x"] - incrementoX
			elseif datiFuoco[nFuocoFatuo]["x"] <= xMin and Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
				datiFuoco[nFuocoFatuo]["xAumenta"] = true
			end
		end
		
		-- moving on y axis
		if datiFuoco[nFuocoFatuo]["yAumenta"] == true then
			if datiFuoco[nFuocoFatuo]["y"] < yMax then
				datiFuoco[nFuocoFatuo]["y"] = datiFuoco[nFuocoFatuo]["y"] + incrementoY
			elseif datiFuoco[nFuocoFatuo]["y"] >= yMax and Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
				datiFuoco[nFuocoFatuo]["yAumenta"] = false
			end
		elseif datiFuoco[nFuocoFatuo]["yAumenta"] == false then
			if datiFuoco[nFuocoFatuo]["y"] > yMin then
				datiFuoco[nFuocoFatuo]["y"] = datiFuoco[nFuocoFatuo]["y"] - incrementoY
			elseif datiFuoco[nFuocoFatuo]["y"] <= yMin and Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
				datiFuoco[nFuocoFatuo]["yAumenta"] = true
			end
		end
		
		-- moving on z axis
		if datiFuoco[nFuocoFatuo]["zAumenta"] == true then
			if datiFuoco[nFuocoFatuo]["z"] < zMax then
				datiFuoco[nFuocoFatuo]["z"] = datiFuoco[nFuocoFatuo]["z"] + incrementoZ
			elseif datiFuoco[nFuocoFatuo]["z"] >= zMax and Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
				datiFuoco[nFuocoFatuo]["zAumenta"] = false
			end
		elseif datiFuoco[nFuocoFatuo]["zAumenta"] == false then
			if datiFuoco[nFuocoFatuo]["z"] > zMin then
				datiFuoco[nFuocoFatuo]["z"] = datiFuoco[nFuocoFatuo]["z"] - incrementoZ
			elseif datiFuoco[nFuocoFatuo]["z"] <= zMin and Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then
				datiFuoco[nFuocoFatuo]["zAumenta"] = true
			end
		end
		
		-- tile change and damage to party
		local xParty, yParty, dParty, lParty = party:getPosition()
		local xFuoco, yFuoco, dFuoco, lFuoco = fuocoFatuo:getPosition()
		local eParty = party:getElevation()
		local eFuoco = fuocoFatuo:getElevation()
		
		-- when it's off
		if Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioSpegnimento"] + (datiFuoco[nFuocoFatuo]["tempoSpegnimento"] * 2) then		
			
			-- stop damage
			local timerFuoco = findEntity("timerDanno_" .. nFuocoFatuo)
			if timerFuoco ~= nil then
				findEntity("timerDanno_" .. nFuocoFatuo):destroy()
			else
			end
			
			-- normal brightness
			if fuocoFatuo.light:getBrightness() > 8 then
				fuocoFatuo.light:setBrightness(8)
			else
			end
			
			-- normal color
			if fuocoFatuo.particle:getParticleSystem() == "will_o_wisp_attack" then
				fuocoFatuo.particle:setParticleSystem("tomb_wall_lantern")
			else
			end
			
			-- x axis tile movement
			if eParty >= eFuoco - 1 and eParty <= eFuoco + 1 and yParty >= yFuoco - 1 and yParty <= yFuoco + 1 then
				if xParty == xFuoco + 1 then
					xFuoco = xFuoco + 1
				elseif xParty == xFuoco - 1 then
					xFuoco = xFuoco - 1
				end
			else
			end
			
			-- y axis tile movement
			if eParty >= eFuoco - 1 and eParty <= eFuoco + 1 and xParty >= xFuoco - 1 and xParty <= xFuoco + 1 then
				if yParty == yFuoco + 1 then
					yFuoco = yFuoco + 1
				elseif yParty == yFuoco - 1 then
					yFuoco = yFuoco - 1
				end
			else
			end
			
			-- z axis tile movement
			if xParty >= xFuoco - 1 and xParty <= xFuoco + 1 and yParty >= yFuoco - 1 and yParty <= yFuoco + 1 then
				if eParty == eFuoco + 1 then
					eFuoco = eFuoco + 1
					datiFuoco[nFuocoFatuo]["z"] = datiFuoco[nFuocoFatuo]["z"] + 3
				elseif eParty == eFuoco - 1 then
					eFuoco = eFuoco - 1
					datiFuoco[nFuocoFatuo]["z"] = datiFuoco[nFuocoFatuo]["z"] - 3
				end
			else
			end
			
			fuocoFatuo:setPosition(xFuoco,yFuoco,dParty,eFuoco,lFuoco)
		
		-- when it's on
		elseif Time.currentTime() >= datiFuoco[nFuocoFatuo]["inizioAccensione"] and Time.currentTime() < datiFuoco[nFuocoFatuo]["inizioAccensione"] + (datiFuoco[nFuocoFatuo]["tempoAccensione"] * 2) + datiFuoco[nFuocoFatuo]["tempoSpegnimento"] then
			
			if xParty == xFuoco and yParty == yFuoco and  eParty == eFuoco then
				
				-- more brightness
				if fuocoFatuo.light:getBrightness() < 9 then
					fuocoFatuo.light:setBrightness(16)
				else
				end
				
				-- color change
				if fuocoFatuo.particle:getParticleSystem() == "tomb_wall_lantern" then
					fuocoFatuo.particle:setParticleSystem("will_o_wisp_attack")
				else
				end
				
				-- damage
				local timerFuoco = findEntity("timerDanno_" .. nFuocoFatuo)
				if timerFuoco == nil then
					spawn("timer", lParty, xParty, yParty, 0, 0, "timerDanno_" .. nFuocoFatuo)
					local timerFuoco = findEntity("timerDanno_" .. nFuocoFatuo)
					timerFuoco.timer:setTimerInterval(2)
					timerFuoco.timer:setDisableSelf(false)
					timerFuoco.timer:setTriggerOnStart(true)
					timerFuoco.timer:setCurrentLevelOnly(true)
					timerFuoco.timer:addConnector("onActivate", self.go.id, "danniExp")
					timerFuoco.timer:start()
				else
				end
				
			else
				
				-- stop damage
				local timerFuoco = findEntity("timerDanno_" .. nFuocoFatuo)
				if timerFuoco ~= nil then
					findEntity("timerDanno_" .. nFuocoFatuo):destroy()
				else
				end
				
				-- normal brightness
				if fuocoFatuo.light:getBrightness() > 8 then
					fuocoFatuo.light:setBrightness(8)
				else
				end
				
				-- normal color
				if fuocoFatuo.particle:getParticleSystem() == "will_o_wisp_attack" then
					fuocoFatuo.particle:setParticleSystem("tomb_wall_lantern")
				else
				end
			
			end
		end
				
		-- chamges activation
		fuocoFatuo:setSubtileOffset(datiFuoco[nFuocoFatuo]["x"], datiFuoco[nFuocoFatuo]["y"])
		fuocoFatuo:setWorldPositionY(datiFuoco[nFuocoFatuo]["z"])
		
		-- starting cicle again
		nFuocoFatuo = nFuocoFatuo + 1
		fuocoFatuo = findEntity("will_o_wisp_" .. nFuocoFatuo)
		
	end
end

-- damage function
function danniExp()
	
	for i=1, 4 do
		if party.party:getChampion(i):getEnabled() and party.party:getChampion(i):isAlive() then
			
			local e = party.party:getChampion(i):getMaxEnergy()
			local c = party.party:getChampion(i):getEnergy()
			local restore = math.random(1, party.party:getChampion(i):getSkillLevel("concentration"))
			party.party:getChampion(i):regainEnergy(restore)
			local e = findEntity("wispRestore1")
			if e then
				e:setHealth(math.floor(e:getHealth() / 2))
				print(e:getHealth())
			end
		end
	end
	party.party:playScreenEffect("wisp_restore_screen")
	playSound("magic_majestic_06")
	hudPrint("The benevalent Will'o'Wisp radiates arcane energy...")
end
(it drains energy when it attacks the party, atm, but ive made it do plenty of diff things)
User avatar
Khollik
Posts: 171
Joined: Tue Aug 29, 2017 6:44 pm
Location: France

Re: Monster Invocation spell

Post by Khollik »

Hello

Thanks again for the will o' the wisp. That doesn't fit exactly in the story I want to tell in my future mod, but maybe I'll have to adapt it a little :roll: . I hoped to make a follower who actually took a tile because I have some puzzles in mind in relation with that. But I will certainly look through the code, it seems very interesting and maybe I can find a way to adapt it... Or I could plan two types of followers : the wisp and the dead.
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Monster Invocation spell

Post by Isaac »

Abe's Odyssey featured puzzles that were probably similar. In that game, he had several occasional companions that he had to ensure didn't get killed, and in many cases had to instruct them when to help him solve environmental puzzles that stopped their escape. He did this by voice commands. Something like that might be possible to script.
User avatar
THOM
Posts: 1266
Joined: Wed Nov 20, 2013 11:35 pm
Location: Germany - Cologne
Contact:

Re: Monster Invocation spell

Post by THOM »

A quiet similar (but also quiet different) feature is Vaporum providing: You can create an apparition of yourself which is attacked by the monsters. Usefull to ged rid of some enemies or for taktics...
THOM formaly known as tschrage
_______________________________________________
My MOD (LoG1): Castle Ringfort Thread
My MOD (LoG2): Journey To Justice Thread | Download
SalimTheHobbitBard
Posts: 2
Joined: Sat Jul 13, 2019 11:19 am

Re: Monster Invocation spell

Post by SalimTheHobbitBard »

This is no very practical remark, but from story perspective, necromancy is usually considered as very dark magic. Do you really think that "good" player's "good" heroes should use it? It would make more sense to summon spirits as zimberzimber suggested, or if you want it to be not walkable and be able to triger pressure_plates, maybe those summoned-stone-guys-that-i-hate-if-i-dont-have-shock-spell might work.
If you decide to go for spirits, i think it would be nice to make them as everything in original game in four version, one for each element. Fire spirits are already done, just one change is needed - let them hit more than once (perhaps depending on skill level), ice could look same just in light blue and able to freeze enemy, air spirit could do same think as lightning wyvern, just look diferent and earth spirit might look just like green fireflies decoration but they would drain life from enemy and heal party members - think that could finaly make earth magic more desirable and add some balance ;) between elemental magic.
After few days I got an idea, if you could make other monsters to see your companion as party by companion's trait. I haven't seen suggestion about it, so it could be briliant idea or idea so stupid everybody know that it can't work :lol: i haven't played with changing Brains so I honesty dont know
Last edited by SalimTheHobbitBard on Mon Aug 26, 2019 5:02 pm, edited 1 time in total.
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Monster Invocation spell

Post by Isaac »

The original Prey, by 3D Realms, allowed for Astral Projection that let the player pass through obstacles, and (strangely) to open locks on the other side.

In Realms of Arkania (a blobber/dungeoncrawler), the party could spilt up into smaller groups, and each explore their own path.
Post Reply