Useful scripts repository

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Komag
Posts: 3654
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Useful scripts repository

Post by Komag »

Spawn a new button/lever/etc and then connect it to something:

item:addConnector(Event, Target, Action)
-- all parameters must be strings

example adapted from djoldgames:

Code: Select all

function buttonconnect()
       spawn("wall_button", 1, 10, 21, 2, "MyWallbutton1")
       MyWallbutton1:addConnector("toggle","mydoor1","toggle")
end
- create a pressure plate which links to the script with "buttonconnect"
- when you step on the plate, the script will create the wall button at the specified location, and it will add the connection from the button to "mydoor1". Now you can press the button and open the door
- make sure the plate is on "activate once" or else it will try to make another of the same button

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3242
Finished Dungeons - complete mods to play
User avatar
Komag
Posts: 3654
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Useful scripts repository

Post by Komag »

insta-death square

example by Montis and Xzalander

- script:

Code: Select all

function instadeath()
     damageTile(party.level, party.x, party.y, party.facing, 128, "physical", 9001)
     hudPrint("You Foolish Adventurers, MWAHAHAHA!!!")
end
- create a hidden plate that is ONLY triggered by the party (not monsters or items)
- connect plate to script
- any number of plates can be similarly connected to the script


-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3248
Finished Dungeons - complete mods to play
Lmaoboat
Posts: 359
Joined: Wed Apr 11, 2012 8:55 pm

Re: Useful scripts repository

Post by Lmaoboat »

Three different alcoves for left/right/middle item placement:

Stacking them on top of each other gives the appearance of one alcove with three points for placing items. Can be used for more precise item placement, precise items stacking inside each other, and more compact puzzles.

Code: Select all

cloneObject{
name = "dungeon_alcove_left",
baseObject = "dungeon_alcove",
anchorPos = vec(-0.4,0.85,0.2),
targetPos = vec(-0.5,0.85,0.2),
targetSize = vec(0.25,1,0.25)
}

cloneObject{
name = "dungeon_alcove_right",
baseObject = "dungeon_alcove",
anchorPos = vec(0.4,0.85,0.2),
targetPos = vec(0.5,0.85,0.2),
targetSize = vec(0.25,1,0.25)
}

cloneObject{
name = "dungeon_alcove_center",
baseObject = "dungeon_alcove",
targetPos = vec(0,0.85,0.2),
targetSize = vec(0.25,1,0.25)
}
-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3223&p=32845#p32845
User avatar
Montis
Posts: 340
Joined: Sun Apr 15, 2012 1:25 am
Location: Grimrock II 2nd playthrough (hard/oldschool)

Re: Useful scripts repository

Post by Montis »

since I edited my initial post with an index, here's my first script again:

Remove (disable) a random character from the party + print message on the screen

Code: Select all

function charBeGone()

	-- loop to find a valid target for the function (an enabled character)
	-- the local variable is defined before so I can use the variable later in the function
	local charnumber = ""
	repeat
		charnumber = math.random(1,4)
	until party:getChampion(charnumber):getEnabled() == true

	-- get the character name so I can use his name in the message easier
	local charname = party:getChampion(charnumber):getName()

	-- set up the message so the correct pronoun is used, checks for character's gender
	local pronoun = ""
	if party:getChampion(charnumber):getSex() == "male" then
		pronoun = "he"
		else
		pronoun = "she"
	end

	-- the message. the ".." are used to concatenate the string with the variables
	hudPrint(charname.." vanishes and  "..pronoun.." is never seen again.")

	-- and here the last piece: disable the character and play a death sound
	party:getChampion(charnumber):setEnabled(false)
	playsound("champion_die")

end
A few notes on this that I might fix in a future version of the script:
  • if the removed character had a light source in his hands, it will continue to glow
  • when the last character is removed from the party, the game will continue to run
  • when triggered after the last character was removed, will go into an infinite loop (aka. crash)
-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3043&p=31390#p31390
Last edited by Montis on Mon Sep 24, 2012 10:45 pm, edited 1 time in total.
When destiny calls, the chosen have no choice.

My completed dungeon (LoG1): Hypercube
User avatar
Komag
Posts: 3654
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Useful scripts repository

Post by Komag »

Getting rid of "First time playing Grimrock?" on new game
(and option to add your own new game message)

- create a script, called "newgamescript" with code:

Code: Select all

hudPrint(" ")
hudPrint(" ")
hudPrint(" ")
hudPrint(" ")
-- remove the -- from the next four lines if you want to add your own message
-- newgametimer:activate()
-- function newgametext()
-- 	hudPrint("Welcome to the Dungeon of Luuuuvvvvv!!!!")
-- end
- create a timer, called "newgametimer", set to 8.5 or 9 seconds
- connect the timer to the script (Action - newgametext)
- connect the timer to itself (Action - deactivate)
- all set!

notes:
- It takes four blank hud prints to clear the default "played Grimrock before?" text. If that's all you want to do, then you can forgo the timer and either leave the -- comments in the script or delete them all.
- The timer will give a chance for the initial "game saved" text to fade before showing your message (if you have Autosave turned on in the Options, which is common).
- You don't need any hidden pressure plate or anything, the script will run on map start.

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3255
Finished Dungeons - complete mods to play
User avatar
Montis
Posts: 340
Joined: Sun Apr 15, 2012 1:25 am
Location: Grimrock II 2nd playthrough (hard/oldschool)

Re: Useful scripts repository

Post by Montis »

Adding a custom colored light source object to the dungeon:

Put the following in objects.lua

Code: Select all

cloneObject{
   name = "red_ceiling_light",
   baseObject = "temple_ceiling_lamp",
   particleSystem = false,
   lightColor = vec(1,0,0), -- sets light to red. edit the numbers to any r,g,b values between 0 and 1 to change the color
}
You can copy this multiple times to get different lights, remember to change the name in the code and the light color.
Change the vec(1,0,0) to any values between 0 and 1 to achieve any color inside the RGB (red, green,blue) spectrum.

A few examples:
White: vec(1,1,1)
Teal: vec(0,1,1)
Yellow: vec(1,1,0)
Purple: vec(.75,0,1)
"Desert sun": vec(.8,.6,.4)

Now once you reload your dungeon, you can place your new light source anywhere as a dungeon object.

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3212
When destiny calls, the chosen have no choice.

My completed dungeon (LoG1): Hypercube
User avatar
Emciel
Posts: 34
Joined: Fri Sep 14, 2012 2:19 am

Re: Useful scripts repository

Post by Emciel »

Check for and Remove a held item, then Return the same item to Inventory

A script to check if any of the champions are holding an item in their hands, if they are, it is removed and placed in an empty slot in their inventory (if no slots are there, it should drop it on the floor).

- create a timer and a script entity
- set the timer to running and connect it on activate to the checkTorch() function

Code: Select all

function itemCheck(item)
	-- checks for the item in champions hands
	for champ = 1,4 do
	for slot = 7,8 do
		x = party:getChampion(champ):getItem(slot)
		if x ~= nil then
		if x.name == item then
			-- if found it is removed and the returnItem function is triggered
            party:getChampion(champ):removeItem(slot)
			print("item removed")
			returnItem(item,champ)
		end
        end   
	end    
	end   
end

function returnItem(item,champ)
	-- checks backpacks for empty slot
	for slot = 11,32 do
			if slot < 32 then
				if party:getChampion(champ):getItem(slot) == nil then
					-- once found, the item is placed in a slot and the player is told where
					print("item returned")
					party:getChampion(champ):insertItem(slot,x)
					hudPrint("The torch is too hot to hold,\nso is put into "..party:getChampion(champ):getName().."'s bag.")
					break
				end
			else
				-- if no slots are empty, the item is dropped
				spawn(item,party.level,party.x,party.y,party.facing)
				hudPrint("The torch is too hot to hold,\nand drops to the floor")
				break
			end
	end
end

function checkTorch()
	itemCheck("torch")
end
-------------------
note from Xzalander:

To expand slightly on Emciel;

To change the item you wish to search for and have replaced into inventory only alter

Code: Select all

function checkTorch()
   itemCheck("torch")
end
Where it says "torch" in quotes. The first three functions should work the same but look for the new item. You can also hook up this script to other entities to have it occur on pressure or lever press.

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3272
roachburn
Posts: 17
Joined: Wed Sep 19, 2012 11:22 am

Re: Useful scripts repository

Post by roachburn »

Rotating 2 portals around a room clockwise:
First off, thanks to Petri, Shroom, and Grimwold for helping me get this script to work. This is a puzzle from the main game on lvl 3 and how to set it up. This was a small room with a pit in the middle and 2 portals on opposite sides of the room rotate around the room. You had to throw an item on a pressure plate to close the pit then quickly put another item on another plate to open the door and run through it before the portal picked up the item off the plate, shutting the door. Anyway, all this code will do is rotate the portals.
Here is a picture of the puzzle.
SpoilerShow
Image
Here is the code
SpoilerShow

Code: Select all

step = 1

function cycleTeleports()

if step==1 then
  telport1:activate()
  telport4:deactivate()
  telport5:activate()
  telport8:deactivate()
  step = 2
else if step==2 then
  telport1:deactivate()
  telport2:activate()
  telport5:deactivate()
  telport6:activate()
  step = 3
else if step==3 then
  telport2:deactivate()
  telport3:activate()
  telport6:deactivate()
  telport7:activate()
  step = 4
else
  telport3:deactivate()
  telport4:activate()
  telport7:deactivate()
  telport8:activate()
  step = 1
end
So this code will cause the 2 portals to rotate clockwise.In the picture, A is the pressure plate that activates the portals and makes them start rotation. Connect this to a timer with 1 sec, initial state stopped. Then connect the timer to the lua with the code above, activate-> cycleTeleports. B is the plate that opens door at D. C is the plate that closes the pit. Make sure the other door cannot be opened from inside the portal room. This door is so you can come back through without having to do the puzzle each time. You could also just use another pressure plate to stop the portals once the puzzle is completed. Simply add the following code at the end of the script. Connect a 2nd plate from outside door D to the timer with activate-> timer -> deactivate and also connect the plate to the lua script as activate -> script entity -> reset teleports.
Also note that you will need to fill the room with teleports, not just the 2, and set the teleport location to plate A.

Here is the deactivate portal code.
SpoilerShow

Code: Select all

function resetTeleports()
  telport1:deactivate()
  telport2:deactivate()
  telport3:deactivate()
  telport4:deactivate()
  telport5:deactivate()
  telport6:deactivate()
  telport7:deactivate()
  telport8:deactivate()
  step = 1
end
You can easily adapt this code to many other uses. I hope explained this all enough. Have fun!

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3293
User avatar
Montis
Posts: 340
Joined: Sun Apr 15, 2012 1:25 am
Location: Grimrock II 2nd playthrough (hard/oldschool)

Re: Useful scripts repository

Post by Montis »

Inspired by Daght:
When a party member dies, check for it's killer and open a door if it was a specific enemy

Place the following in the file init.lua
SpoilerShow

Code: Select all

cloneObject{
name = "party",
baseObject = "party",
onDie = function()
	murderMystery.checkWhoDidIt()
end,
}

Place the following in a script_entity with the ID murderMystery
SpoilerShow

Code: Select all

-- change the following line to suit your dungeon
suspectedMurderer = "tentacles"
doorToOpen = "mysteryDoor"

-- you shouldn't need to change any of the following lines
-- except when you want the action to be something else as opening a door
function checkWhoDidIt()
	local x = ""
	local y = ""
	for i=1,4 do
		if i==1 then
			x = party.x+1
		elseif i == 3 then
			x = party.x-1
		else
			x = party.x
		end

		if i==2 then
			y = party.y+1
		elseif i == 4 then
			y = party.y-1
		else
			y = party.y
		end

		for j in entitiesAt(party.level, x, y) do
			if j.name == suspectedMurderer then
				findEntity(doorToOpen):open()
				return
			end
		end
	end
end
Notes:
  • The script entity must be named correctly, or else the editor will crash.
  • Only works when the killer is in melee range, so you'll run into problems on ranged enemies.
  • Will also trigger if the specific monster is in melee range, but was not actually the killer.
-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3295
When destiny calls, the chosen have no choice.

My completed dungeon (LoG1): Hypercube
Lmaoboat
Posts: 359
Joined: Wed Apr 11, 2012 8:55 pm

Re: Useful scripts repository

Post by Lmaoboat »

Adjustable number display and password entry:

Simply place this against a in wall pointed at by the script entities facing and connect two buttons to it: one to it's add function (add), and one to it's subtract (sub), or just use one button with add on since it wraps around. Everything is local to the script, so you can copy and paste multiple without have thing change anything.

Code: Select all


pixelsy = {3.5,3.5,3.5,3.5,3.5,3,3,3,3,3,2.5,2.5,2.5,2.5,2.5,2,2,2,2,2,1.5,1.5,1.5,1.5,1.5}

if self.facing == 0 then
	pixelsx = {-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1}
	pixelsz ={1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3}
elseif self.facing == 1 then
	pixelsz = {1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1}
	pixelsx ={1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3,1.3}
elseif self.facing == 2 then
	pixelsx = {1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1,1,0.5,0,-0.5,-1}
	pixelsz ={-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3}
else
	pixelsz = {-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1,-1,-0.5,0,0.5,1}
	pixelsx ={-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3,-1.3}
end




n0 = {1,2,3,4,5,6,10,11,15,16,20,21,22,23,24,25}
n1 = {1,2,3,8,13,18,21,22,23,24,25}
n2 = {1,2,3,4,5,10,11,12,13,14,15,16,21,22,23,24,25}
n3 = {1,2,3,4,5,10,11,12,13,14,15,20,21,22,23,24,25}
n4 = {1,5,6,10,11,12,13,14,15,20,25}
n5 = {1,2,3,4,5,6,11,12,13,14,15,20,21,22,23,24,25}
n6 = {1,2,3,4,5,6,11,12,13,14,15,16,20,21,22,23,24,25}
n7 = {1,2,3,4,5,6,10,15,20,25}
n8 = {1,2,3,4,5,6,10,11,12,13,14,15,16,20,21,22,23,24,25}
n9 = {1,2,3,4,5,6,10,11,12,13,14,15,20,21,22,23,24,25}


function makelight()
	for i=1,25 do 
		local check = findEntity(self.id..i)
		if check == null then	
			spawn("fx", self.level, self.x, self.y, 3, self.id..i)
			local lcd = findEntity(self.id..i)
			lcd:setLight(1,0,0,500,0.3, 360000, false)
			lcd:translate(0,-1,0)
		end
	end
end

function removelight()
		for i=1,25 do
			local check = findEntity(self.id..i)
			if check ~= null then
				local lcd = findEntity(self.id..i)
				lcd:destroy()
			end
		end	
end



function numlist(n)
		if n == 0 then
		for i=1,25 do
		local pix = n0[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end

		if n == 1 then
		for i=1,25 do
		local pix = n1[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end

		if n == 2 then
		for i=1,25 do
		local pix = n2[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 3 then
		for i=1,25 do
		local pix = n3[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 4 then
		for i=1,25 do
		local pix = n4[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 5 then
		for i=1,25 do
		local pix = n5[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 6 then
		for i=1,25 do
		local pix = n6[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 7 then
		for i=1,25 do
		local pix = n7[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 8 then
		for i=1,25 do
		local pix = n8[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
		if n == 9 then
		for i=1,25 do
		local pix = n9[i]
		if pix ~= nil then
			local lcd = findEntity(self.id..i)
			local movex = pixelsx[pix]
			local movey = pixelsy[pix]
			local movez = pixelsz[pix]
			lcd:translate(movex,movey,movez)
			end
		end
	end
end


function addx()
   if X == 9 then
      X = 0
   	makelight()
	numlist(0)
	else
	 X = X + 1
	makelight()
	numlist(X)
	end
end


function minx()
   if X == 0 then
      X = 9
   	  makelight()
	  numlist(9)
 	else
	X = X - 1
    makelight()
	numlist(X)
	
	end
end

function add()
    removelight()
    addx()
end

function sub()
    removelight()
    minx()
end



makelight()
numlist(0)
if X == nil then
	X = 0
end

If you want it to check for a password, use the script, and replace my examples with the names if yours, and your own password. In this one, I have three named lcdA, lcdB, and lcdC:

Code: Select all

    spawn("timer", self.level, self.x, self.y, 3, self.id.."timer"):setTimerInterval(1):addConnector("activate", self.id, "passcheck"):activate()

    function passcheck()
       pass = lcdA.X..lcdB.X..lcdC.X
       if pass == "111" then
          vaultdoor:open()
          timer:deactivate()
       end
    end

Another example: if you want to check the password with a lever that damages the player if they get it wrong, use this and connect a lever to it, in this case named "passlever":

Code: Select all

function passcheck()
	pass = lcdA.X..lcdB.X..lcdC.X
	if pass == "111" then
		vaultdoor:open()
	else
		passlever:setLeverState("deactivated")
		damageTile(passlever.level, passlever.x, passlever.y, 0, 0, "shock", 15)
		playSound("lightning_bolt_hit_small")
	end
end
-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3269
Last edited by Lmaoboat on Mon Oct 08, 2012 3:40 am, edited 7 times in total.
Post Reply