Useful scripts repository

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
Lmaoboat
Posts: 359
Joined: Wed Apr 11, 2012 8:55 pm

Re: Useful scripts repository

Post by Lmaoboat »

Updated my script so that it puts the display on a wall in the direction of the script entities' facing.
Batty
Posts: 509
Joined: Sun Apr 15, 2012 7:04 pm

Re: Useful scripts repository

Post by Batty »

Earthquake!

Camera shake by Neikun

Code: Select all

function scareshake()
   party:shakeCamera(1,1)
end
Note: shakeCamera(d,t) d is a number that controls degree of shaking & t is a number controlling the time duration of the shake.
Try decimal values <1 for a little shake and go >5 for end of the world stuff. Scripting reference says d can only be 0-1 but it can go >1.
Thanks to Ixnatifual for pointing this out.

Earthquake sound

Code: Select all

playSound("earthquake")
However, this results in an endless loop of rumbling.
So, thanks to Neikun, you have to define a new sound which will rumble for 8-10 seconds then end abruptly:

Code: Select all

    defineSound{
       name = "earthquakestop",
       filename = "assets/samples/env/earthquake_01.wav",
       loop = false,
       volume = 1,
       minDistance = 1,
       maxDistance = 6,
    }
Earthquake particle effect

Code: Select all

spawn("fx", 1, 15, 15, 3, "dust")
dust:setParticleSystem("earthquake_dust")
Note: spawn(object, level, x, y, facing, [id])
Thanks to Lmaoboat's LED dungeon display code.

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3339
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 »

3 scripts in one post:
  1. Get the name of a random, living champion
  2. Check how many champions are alive
  3. Easy character dialogue!


I post these in one post since the character dialogue script uses the other two, but those might useful on their own as well.

Get the name of a random, living champion:
SpoilerShow

Code: Select all

-- returns the name of a random living and not disabled champion
function getRandomLivingChamp()
	local charnumber = ""
	repeat charnumber = math.random(1,4)
	until party:getChampion(charnumber):getEnabled() and party:getChampion(charnumber):isAlive()
	return party:getChampion(charnumber):getName()
end
Get the lifesigns of the party, i.e. how many are currently alive:
SpoilerShow

Code: Select all

-- returns how many characters are still alive and enabled
function checkLifeSigns()
	local lifesigns = 0
	for i=1,4 do
		if party:getChampion(i):getEnabled() and party:getChampion(i):isAlive() then
			lifesigns = lifesigns+1
		end
	end
	return lifesigns
end
Easy character dialogue:
(note that this will need the other two scripts present in the same script entity!)
SpoilerShow

Code: Select all

-- lets two random champions talk with each other
-- if only one champion is alive, he will talk with himself
function champTalk(line1,line2,line3)
	local firstTalker = getRandomLivingChamp()
	local secondTalker = firstTalker
	if line1 == nil then
		return
	else
		hudPrint(firstTalker..": "..line1)
	end
	if line2 ~= nil then
		if checkLifeSigns() > 1 then
			repeat secondTalker = getRandomLivingChamp()
			until secondTalker ~= firstTalker
		end
		hudPrint(secondTalker..": "..line2)
	end
	if line3 ~= nil then
		hudPrint(firstTalker..": "..line3)
	end
end
Usage for the 3rd is that you call it from another script or through a hidden plate:

Code: Select all

function banter()
	your_script_entity.champTalk("How are YOU doin'?", "Seriously? We're in the middle of a bloody dungeon!", "T'was worth a shot.")
end
This would then output two champion names and result in something like:
Contar Stoneskull: How are YOU doin'?
Yennicka Whitefeather: Seriously? We're in the middle of a bloody dungeon!
Contar Stoneskull: Well... it was worth a shot.
Beware though: since the characters that talk are random, it might just be Mork chatting with Sancsaron ;)
Last edited by Montis on Tue Oct 30, 2012 12:32 pm, edited 2 times in total.
When destiny calls, the chosen have no choice.

My completed dungeon (LoG1): Hypercube
User avatar
Neikun
Posts: 2457
Joined: Thu Sep 13, 2012 1:06 pm
Location: New Brunswick, Canada
Contact:

Re: Useful scripts repository

Post by Neikun »

Double Locks!
Paste into your objects.lua

Code: Select all

cloneObject{
	name = "lock_high",
	baseObject = "lock",
	height = 1.743,
	placement = "wall",
	editorIcon = 20,
}
This will give you a working lock that can be placed on the same wall as a regular lock, but this one will be above it.
"I'm okay with being referred to as a goddess."
Community Model Request Thread
See what I'm working on right now: Neikun's Workshop
Lead Coordinator for Legends of the Northern Realms Project
  • Message me to join in!
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Useful scripts repository

Post by Isaac »

Conditional Text walls.

Place text walls that change their content depending on a condition.

This one changes the text each time a pressure plate is activated:
Place a counter, a plate, Lua, and a Text Wall.

Code: Select all

function activate()
if counter_1:getValue() == 5 then                      -- Change the number to match how many text strings that you use.

--[[   Optional place to put code for a trap 
          spawner_1:activate()
          spawner_2:activate()
--]]
counter_1:reset()
return
end
local Info = {"Stay off the plate!", "Stop That!", "You are going to regret this!", "One more time and it's Goodbye! You've been warned."} 
dungeon_wall_text_1:setWallText(Info[counter_1:getValue()])
counter_1:increment()
end
This script could even be modified for use in a combination lock. Change the texture for a custom wall text; make it look like a clockwork Rune display. change the text to reflect the state of the combination lock; IE = {"0-0-1", "0-0-2", 0-0-3, etc...}, or IE[1] = counter_1 .. "-" .. counter_2 .. "-" .. counter_3.

***************************************************************************************************************************

This one presents illegible text unless you have a Minotaur in your party who can read it.
Place a Text Wall, two Lua objects, a hidden pressure plate (directly in front of the text wall), set the wall's text to a default message for those who cannot read the text.
(Plate should be connected to both lua scripts.)
Lua1

Code: Select all

function activate()

for x = 1,4 do
	local PCRace = party:getChampion(x):getRace()
	local isLucid = party:getChampion(x):isAlive()
		if PCRace == "Minotaur" and isLucid then
			dungeon_wall_text_2:setWallText("The etherial wall is to the East.")
		end
	end
end
Lua2

Code: Select all

function deactivated()
dungeon_wall_text_2:setWallText("This text is indecipherable")
end
Last edited by Isaac on Tue Sep 25, 2012 11:38 pm, edited 2 times in total.
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 »

Create a destructible tunnel blockage
Will also spawn a random amount of rocks when destroyed.

add the following to your objects.lua
SpoilerShow

Code: Select all

cloneObject{
	name = "destructible_cave_in",
	baseObject = "dungeon_cave_in", -- you might want to change this to temple_cave_in or the prison one
	brokenModel = "assets/models/env/floor_dirt.fbx", -- if anyone can find a better standard model for this, give me a shout
	health = 50, -- adjust this to your needs
	evasion = -1000,
	hitEffect = "hit_dust",
	hitSound = "impact_generic",
	onProjectileHit = function()
		return false -- projectiles (arrows and such) shouldn't be able to destroy it
	end,
	onHit = false, -- this is used to negate the "indestructible" property
	onDie = function(self)
		-- when blockage is destroyed, spawn 2-5 rocks
		rocks = math.random(1,4)+1
		for i = 1,rocks do
			spawn("rock", self.level, self.x, self.y, i%4)
		end
	end
}
Then simply place it in a tunnel.

Notes:
  • This will only look good from one direction. If you want to create a tunnel that is destructible from two sides, you have to add a script in the "onDie" function. Beware of infinite loops though.
-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3357
When destiny calls, the chosen have no choice.

My completed dungeon (LoG1): Hypercube
User avatar
Neikun
Posts: 2457
Joined: Thu Sep 13, 2012 1:06 pm
Location: New Brunswick, Canada
Contact:

Re: Useful scripts repository

Post by Neikun »

Central Pillars
Copy this into your objects.lua for a pillar in the centre of a square.

Code: Select all

defineObject{
	name = "dungeon_pillar_center",
	class = "Blockage",
	model = "assets/models/env/dungeon_pillar.fbx",
	placement = "floor",
	repelProjectiles = true,
	hitSound = "impact_blade",
	editorIcon = 100,

}
Want other pillar styles?
Prison:

Code: Select all

defineObject{
	name = "prison_pillar_center",
	class = "Blockage",
	model = "assets/models/env/prison_pillar.fbx",
	placement = "floor",
	repelProjectiles = true,
	hitSound = "impact_blade",
	editorIcon = 100,
}
Temple:

Code: Select all

defineObject{
	name = "temple_pillar_center",
	class = "Blockage",
	model = "assets/models/env/temple_pillar.fbx",
	placement = "floor",
	repelProjectiles = true,
	hitSound = "impact_blade",
	editorIcon = 100,
}
Appearance
SpoilerShow
Image
SpoilerShow
Image
NOTE: These are impassible and indestructible objects.
NOTE: You may have noticed that I've switched the editor icon from that of a pillar. This is to make it easier to understand where you've placed it.
"I'm okay with being referred to as a goddess."
Community Model Request Thread
See what I'm working on right now: Neikun's Workshop
Lead Coordinator for Legends of the Northern Realms Project
  • Message me to join in!
User avatar
Komag
Posts: 3658
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Useful scripts repository

Post by Komag »

Re-create the "Checkered Room" (for practice)

- set up nine pressure plates, and name them oddplate and evenplate like so:
odd1, even1, odd2
even2, odd3, even3
odd4, even4, odd5
- create a door named checkeredport
- create a script item Lua with the following code:

Code: Select all

function openport()
   if
      oddplate1:isUp() and
      oddplate2:isUp() and
      oddplate3:isUp() and
      oddplate4:isUp() and
      oddplate5:isUp() and
      evenplate1:isDown() and
      evenplate2:isDown() and
      evenplate3:isDown() and
      evenplate4:isDown()
   then
      checkeredport:open()
   elseif
      oddplate1:isDown() and
      oddplate2:isDown() and
      oddplate3:isDown() and
      oddplate4:isDown() and
      oddplate5:isDown() and
      evenplate1:isUp() and
      evenplate2:isUp() and
      evenplate3:isUp() and
      evenplate4:isUp()
   then
      checkeredport:open()
   else
      checkeredport:close()
  end
end
- then link each plate to the script with Event:any and Action:openport

Now, please don't put this exact puzzle in your dungeon, but it's still good practice to understand the setup and logic of it. Then you can adapt or change it to something unique for your situation.

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

Re: Useful scripts repository

Post by Komag »

Use a single timer's repeating signal to perform a series of events in a row

If I want to spawn 6 items over the course of 6 seconds, so each pops into view in sequence, 1 second apart, I can do it without scripts by using 6 timers, each set for 1 second, and each connected both to a spawner and to the next timer. Thus the full sequence occurs. But that's a lot of crap on the editor screen. A single script that can manage it all is cleaner:

example by antti

Code: Select all

timecount = 1
function tick()
  if timecount == 1 then
    -- spawn object 1 here
  elseif timecount == 2 then
    -- spawn object 2 here
  elseif timecount == 3 then
    -- spawn object 3 here
  elseif timecount == 4 then
    -- spawn object 4 here
  elseif timecount == 5 then
    -- spawn object 5 here
  elseif timecount == 6 then
    -- spawn object 6 here and in this example it's the last object on our list)
       cooltimer:deactivate()
    -- so then we can loop back to the beginning here by uncommenting the next two lines if we want to:
    -- timecount = 1
    -- return
  end
  timecount = timecount + 1
end
then connect "cooltimer" to the script with the "tick" function.

You can do anything you want in the steps above, such as opening or shutting doors or trapdoors (shutting the next one and opening the previous one), turning off or on teleporters in order, etc

-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3213
Finished Dungeons - complete mods to play
User avatar
Shloogorgh
Posts: 45
Joined: Sat Sep 22, 2012 12:24 am

Re: Useful scripts repository

Post by Shloogorgh »

Sacrificial Dagger script

The dagger demands a sacrifice and can be used to take a party member's life in order to complete the ritual. Use the dagger as a consumable item. You could always adjust it to merely damage the user instead of instant-kill them

The resultant dagger is then used as a piece in a puzzle, or you could change it to be a wand charge weapon (that demands another sacrifice when out of charges)

EDIT: original code largely obsolete due to implementation of emptyItem on the latest patch. Edited the code to show how it can be done easily now, if you wanna see the original struggle, check out the original thread at the bottom of the post

Code: Select all

cloneObject{
	name = "sacrificial_dagger",
	baseObject = "dagger",
	uiName = "Sacrificial Dagger",
	gfxIndex = 142,
	model = "assets/models/items/assassin_dagger.fbx",
	description = "Dark energy emanates from this ritualistic blade",
	gameEffect = "Place against a comrade's throat to complete the dark ritual",
	weight = 1.0,
	emptyItem = "sacrificial_dagger_used",
	onUseItem = function(self, champion)
		playSound("party_crushed")
		champion:damage(10000, "physical")
		hudPrint(champion:getName().." has been sacrificed.")
		return true
	end,
}

cloneObject{
	name = "sacrificial_dagger_used",
	baseObject = "dagger",
	uiName = "Sacrificial Dagger",
	gfxIndex = 142,
	model = "assets/models/items/assassin_dagger.fbx",
	description = "The essence of your comrade pulses within the blade",
	attackPower = 10,
	weight = 1.0,
}
-----
original thread for discussion/questions:
viewtopic.php?f=14&t=3360
Post Reply