Breakable Obstacles triggering other things

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
Mortis_of_Midian
Posts: 14
Joined: Wed Dec 10, 2014 6:07 pm

Breakable Obstacles triggering other things

Post by Mortis_of_Midian »

Yet another question from me because things don't work quite the way I'd expect

The basic aim here is to have a room full of breakable obstacles (example: terracotta_jars_block) and have the player break them all to open a door (via a counter). I also like elsewhere in my dungeon to have breakable objects that trigger other things when broken.

The initial problem here is that breakable obstacles don't have connectors

My first experiment involved putting the Jars on Floor Triggers - this of course did not work because floor triggers don't detect obstacles / obstacles don't count as Items

So my first thought was to use the Jar's Heath reaching 0 and it seemed simple enough. Note because this was a experiment I wired one directly to the door rather than to a counter.

Code: Select all

 if terracotta_jars_block_3.health:getHealth() == 0 then dungeon_secret_door_50.door:open() 
this however doesn’t work, because (I think) the 'terracotta_jars_block' object is replaced with a 'terracotta_jars_block_damaged' object and eventually a 'terracotta_jars_block_broken_1' - so I get a Nil Value error.

So I decided on a different approach using what I learned about spawning Monsters with connectors

Code: Select all

 spawn("terracotta_jars_block", 8, 14, 17, 1, 0)health:addConnector("onDie", dungeon_secret_door_50.door:open() ) 
this also gives me a Nil Value error, but this time on the Health Component for reasons I don't understand (according to the scripting reference page the Health Component does have an onDie)


So what next? Do I really need to go about making custom versions of the Breakable Obstacles with added Connectors? (and if so, how? I'm going to need pointing to a good tutorial)
User avatar
THOM
Posts: 1280
Joined: Wed Nov 20, 2013 11:35 pm
Location: Germany - Cologne
Contact:

Re: Breakable Obstacles triggering other things

Post by THOM »

Do you have the LoG2 Asset Pack?

You can look there at the definitions of the breakable object. It will show you: You can add to the Health-Component a line like:

Code: Select all

			onDie = function(self)
				counterXY.counter:increment()
			end,
THOM formaly known as tschrage
_______________________________________________
My MOD (LoG1): Castle Ringfort Thread
My MOD (LoG2): Journey To Justice Thread | Download
minmay
Posts: 2788
Joined: Mon Sep 23, 2013 2:24 am

Re: Breakable Obstacles triggering other things

Post by minmay »

You wanted this:

Code: Select all

spawn("terracotta_jars_block", 8, 14, 17, 1, 0).health:addConnector("onDie","dungeon_secret_door_50","open")
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.
User avatar
Zo Kath Ra
Posts: 940
Joined: Sat Apr 21, 2012 9:57 am
Location: Germany

Re: Breakable Obstacles triggering other things

Post by Zo Kath Ra »

Mortis_of_Midian wrote:this however doesn’t work, because (I think) the 'terracotta_jars_block' object is replaced with a 'terracotta_jars_block_damaged' object and eventually a 'terracotta_jars_block_broken_1' - so I get a Nil Value error.

So what next? Do I really need to go about making custom versions of the Breakable Obstacles with added Connectors? (and if so, how? I'm going to need pointing to a good tutorial)
You're right, when a "terracotta_jars_block" dies, it spawns a "terracotta_jars_block_damaged".
And when a "terracotta_jars_block_damaged" dies, it spawns a "terracotta_jars_block_broken".

You need to create new versions of these objects, like this:

Code: Select all

defineObject{
	name = "terracotta_jars_block_new",
	baseObject = "base_obstacle",
	components = {
		{
			class = "Model",
			model = "assets/models/env/terracotta_jars_block.fbx",
		},
		{
			class = "Obstacle",
			hitSound = "terracotta_jar_hit",
			hitEffect = "hit_terracotta_jar",
		},
		{
			class = "Health",
			health = 15,
			immunities = { "poison" },
			spawnOnDeath = "terracotta_jars_block_damaged_new",
		},
	},
	editorIcon = 260,
}

defineObject{
	name = "terracotta_jars_block_damaged_new",
	baseObject = "base_obstacle",
	components = {
		{
			class = "Model",
			model = "assets/models/env/terracotta_jars_block_damaged.fbx",
		},
		{ 
			class = "Obstacle",
			hitSound = "terracotta_jar_hit",
			hitEffect = "hit_terracotta_jar",
		},
		{
			class = "Health",
			health = 15,
			immunities = { "poison" },
			spawnOnDeath = "terracotta_jars_block_broken_new",
			onDie = function(self)
				self.go:playSound("terracotta_jar_die")
				
				for entity in self.go.map:entitiesAt(self.go.x, self.go.y) do
				    if (entity.counter) then
				        entity.counter:decrement()
				    end
				end
			end,
		},
	},
	editorIcon = 260,
}


defineObject{
	name = "terracotta_jars_block_broken_new",
	baseObject = "base_floor_decoration",
	components = {
		{
			class = "Model",
			model = "assets/models/env/terracotta_jars_block_broken.fbx",
		},
	},
}
When a "terracotta_jars_block_damaged_new" dies, it decrements all counters on the same square.
Put a counter on the same square as the "terracotta_jars_block_new", set the counter's value to 1, and connect the counter to anything you want. You can connect it to another counter to implement the kind of room you described.
Mortis_of_Midian
Posts: 14
Joined: Wed Dec 10, 2014 6:07 pm

Re: Breakable Obstacles triggering other things

Post by Mortis_of_Midian »

Thanks guys :)

Minmay's correction to my code worked, but triggered the door when the original object died.

So … it looks like I'm treading into the territory of defining new objects

and here come my next (newbie) question:

where do I enter the defineObject code that Zo Kath Ra has kindly worked out for me?

And since I'm now headed that was I also have further questions about custom objects which will follow if that's ok :)
User avatar
Isaac
Posts: 3188
Joined: Fri Mar 02, 2012 10:02 pm

Re: Breakable Obstacles triggering other things

Post by Isaac »

Try this script. Place it on the map and edit the breakable_set table to contain the object ids of all of the breakable objects you will use.
Edit the trigger action to suit your purpose.

Code: Select all

--Works with most breakable objects

breakable_puzzle_count = 0  --==========================[ In-script counter, (no need for a counter object) ]
breakable_set = { --==[ Add the id below for each breakable object in the puzzle; change names to suit ]
				"terracotta_jars_block_1",
				"barrel_crate_block_1",
				"forest_thorn_blocker_1",
				"beach_thicket_01_1",
				"spider_eggs_1",
				"beach_cattail_blocker_1",
				}
				
--==[ Adds the 'onDie' connector to all breakable objects; when they die, they call getDamageId() ]				
for x = 1, #breakable_set do findEntity(breakable_set[x]).health:addConnector("onDie", self.go.id, "getDamageId") end			



function increment() --==[ increments and then checks the value of breakable_puzzle_count; triggers action when all objects are broken]
		breakable_puzzle_count = breakable_puzzle_count +1
		if breakable_puzzle_count >= #breakable_set then
		
		-----------------------------------------------------trigger action; change actions to suit	
			
			dungeon_door_wooden_1.door:open()

		-----------------------------------------------------	
			self.go:destroyDelayed()  --deletes script after it completes
		end
end

--============================[ Derives the damaged object ID from the dying object, and calls updateDamaged() ]
function getDamageId(object)
	if object.go.health then 
		for each in object.go.map:entitiesAt(object.go.x, object.go.y) do
			if each.name == object.go.health:getSpawnOnDeath() then
				updateDamaged(each.id)
				return
			end
		end
	end	
end

--============================[ Adds 'onDie' connector to newly spawned damage object; calls increment() ]
function updateDamaged(damageId)
		if findEntity(damageId) and findEntity(damageId).health then
			findEntity(damageId).health:addConnector("onDie", self.go.id, "increment")
		 else increment()	
		end	
end
Demo project: https://www.dropbox.com/s/xhjd5ncbhmz39 ... g.zip?dl=0
Mortis_of_Midian wrote:where do I enter the defineObject code that Zo Kath Ra has kindly worked out for me?
Usually in the object.lua file; found in the project folder for your map.
*On Windows OS [vista/7+?] this is commonly: c:\Users\%username%\Documents\Almost Human\Legend of Grimrock 2\Dungeons\ (the name of your map) \mod_assets\scripts\object.lua

Check your documents folder for "Almost Human".
Mortis_of_Midian
Posts: 14
Joined: Wed Dec 10, 2014 6:07 pm

Re: Breakable Obstacles triggering other things

Post by Mortis_of_Midian »

Isaac, excellent! Thank you, I was hoping there was a solution that didn't involve custom objects as I don't want to get into that just yet. :-)

Having said that I'm starting to feel the need for 2 Custom objects, both based on the Fire Trap Rune - an arrow marked on the floor and a magic circle - should prove simple enough?

Anyway the script worked perfectly :-)
Post Reply