[mod-wip] Treasury - General Help Me

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: [mod-wip] Treasury - General Help Me

Post by Isaac »

Glew wrote:So I have made some progress with the map, but had to put it to rest, because of work and school.
But I have got an idea and ran into a problem. It seems that scripts can't find items within the inventory: they return nil. I think I read about this somewhere but couldn't find it.

Is there a way to access items that are in the inventory? From the scripting reference it seems there is a way to access items in equipemnt slots with Champion:getItem(slot). But what about non-equipped items? I guess party:getChampion(1):containedItems() won't work, would it?
The non-equipped items are in slots higher than 10; [up to 32].
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: [mod-wip] Treasury - General Help Me

Post by Glew »

Oh okay. I'm not sure how to iterate through the items. Would something like this work? I think something is missing between the 2nd FOR loop and the IF statement.

Code: Select all

for a=1, 4 do  
for b=1, 32 do party:getChampion(a):getItem(b) 
if b.id=="thing_1" then 
spwan("poison_cloud", party.level, party.x, party.y, party.facing)
end
end 
end 
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: [mod-wip] Treasury - General Help Me

Post by Isaac »

Glew wrote:Oh okay. I'm not sure how to iterate through the items. Would something like this work? I think something is missing between the 2nd FOR loop and the IF statement.

Code: Select all

for a=1, 4 do  
for b=1, 32 do party:getChampion(a):getItem(b) 
if b.id=="thing_1" then 
spwan("poison_cloud", party.level, party.x, party.y, party.facing)
end
end 
end 
That wont do it; b isn't used correctly, it's defined as a number [for loop], but is next used in place of the item itself ~for the comparison.
Try this:

Code: Select all

function search()
	    for a=1, 4 do 
		    for b=1, 31 do
			local c = party:getChampion(a):getItem(b)
		       	if c and c.name == "thing_1" then
		      	 spawn("poison_cloud", party.level, party.x, party.y, party.facing)
		        end
			end	   
	    end 
end 
What exactly are you trying to do with this script?
(Spawn a trap if they pick the thing_1 up?)

The object itself can be defined with an onEquipItem hook. This function runs whenever the item gets placed in inventory; with no need to search for it ~it's there if the code runs, and the hook even provides which champion equipped it.

Code: Select all

	defineObject{
		name = "poison_gem",
		class = "Item",
		uiName = "Mysterious Emerald",
		gameEffect = "(trapped)",
		model = "assets/models/items/green_gem.fbx",
		gfxIndex = 119,
		weight = 0.2,
		onEquipItem = function(champion, slot)
				spawn("poison_cloud", party.level, party.x, party.y, party.facing)
				hudPrint("") hudPrint("") hudPrint("")
				hudPrint("Handling the "..string.lower(champion:getItem(slot):getUIName()).." has sprung")
				hudPrint("a magical trap!")
			end,
	}
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: [mod-wip] Treasury - General Help Me

Post by Glew »

I'll try this, thanks.

What I wanted to do, is make a "poison gem", that emits clouds of poison when a function is called. I haven't worked out the exact details yet. But if the party picks it up, it would -when triggered- shroud the party in poison too.
spawn("poison_cloud"; gem.level, gem.x, gem.y, gem.facing) works fine until the party picks up the thing, then it crashes saying "global gem is a nil value".

So I want to be able to trigger a spell at the gem's location, but if it is in the inventory then it must be at the party's location. So I need to check that if the gem is not found, then is it in the inventory? (now with this in mind, I'll surely not place any containers on the map!)
I guess it's possible that it would also return nil if it was on an alcove or in a socket?

edit: Your search() function works fine. Thanks!
I'm not sure if there is an easier way than this. Because I don't (necessarily) want it to trigger on equip. Though that one could come in handy later too.

Also, now that I have looked at the define object script: Is there a way to hudPrint the value of a non-string variable? For example I make a global variable that increases when a button is pressed. hudPrint(x) will tell me that "a string is expected" and hudPrint("x") will obviously just print "x".

And can you tell me why gfxIndex=119 and what gameEffect7("trapped") does?
Now I wonder if on a completely unrelated note I could define a red coloured gem that can be inserted into an eye socket (as many before me). And I'm not sure what that would need. Would I just clone the blue_gem and give it model = "assets/models/items/blue_gem.fbx"?
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: [mod-wip] Treasury - General Help Me

Post by Glew »

Oh, and thanks a lot for all the help you have given me this far. Have a very happy new year! :mrgreen:
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: [mod-wip] Treasury - General Help Me

Post by Isaac »

Happy New Year! :)
  • Red gems exist in the game; no need to make one. The sockets also exist in the game, and the asset pack.
    eye_socket_right ; eye_socket_left ; (there is even one for the mouth)
    By default the eye sockets check for blue gems, but they can be defined to look for red ones.

    Code: Select all

    defineObject{
    	name = "eye_socket_left_RED",
    	class = "Alcove",
    	anchorPos = vec(0.21, 1.58, -0.45),
    	targetPos = vec(0.2, 1.65, -0.45),
    	targetSize = vec(0.1, 0.1, 0.1),
    	placement = "wall",
    	onInsertItem = function(self, item)
    		return item.name == "red_gem" and self:getItemCount() == 0
    	end,
    	editorIcon = 92,
    }
    
    defineObject{
    	name = "eye_socket_right_RED",
    	class = "Alcove",
    	anchorPos = vec(-0.21, 1.58, -0.45),
    	targetPos = vec(-0.2, 1.65, -0.45),
    	targetSize = vec(0.1, 0.1, 0.1),
    	placement = "wall",
    	onInsertItem = function(self, item)
    		return item.name == "red_gem" and self:getItemCount() == 0
    	end,
    	editorIcon = 92,
    }
  • To print non-string with hudPrint(), you must convert the numbers to strings. LUA has a standard tostring() function for this.

    Code: Select all

    hudPrint(tostring(3.14159))
  • The value gameEffect is just a descriptive string. It prints just below the item name in the player's inventory when hovering the mouse on the item. It doesn't have any other effect; just prints the string. In this case, by the time they can read it, they already know it's trapped.
  • The value gfxIndex defines the the mouse icon shown in the game for an object. There is a companion value gfxAtlas that is the Icon file itself. gfxIndex is the number index for the icon in gfxAtlas. AH has a description of these here: http://www.grimrock.net/modding_log1/cr ... om-assets/
    (About halfway down the page.)

    *John Wordsworth has made an easy tool for editing the icon atlas, or making new ones. http://www.johnwordsworth.com/legend-of-grimrock/
  • The Party hook onPickUpItem might also work for what you want with the poison_gem. Instead of triggering when the player equips an item, it triggers as soon as the item is touched.

    [Notice that the poison_gem definition is updated to remove the onEquipItem hook.]

    Code: Select all

    defineObject{
    	name = "party",
    	class = "Party",
    	editorIcon = 32,
    	onPickUpItem = function(party, item)
    					if item.name == "poison_gem" then
    						spawn("poison_cloud", party.level, party.x, party.y, party.facing)
    						hudPrint("") hudPrint("") hudPrint("")
    						hudPrint("Handling the "..string.lower(item:getUIName()).." has sprung")
    						hudPrint("a magical trap!")
    					end
    				end
    }
    
    defineObject{
    	name = "poison_gem",
    	class = "Item",
    	uiName = "Mysterious Emerald",
    	gameEffect = "(trapped)",
    	model = "assets/models/items/green_gem.fbx",
    	gfxIndex = 119,
    	weight = 0.2,
    }
    
    
    
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: [mod-wip] Treasury - General Help Me

Post by Glew »

Yeah, I know there are red gems and eye sockets. Just that by default you can only insert blue gems into the sockets. But I should be able to use these new sockets then for red gems (and as template as well I guess). I guess they'll work just like the default eyesockets: they will activate on the insertion of a red gem and can have connectors etc right?

Thanks for the tostring tip! It makes testing SO MUCH easier! :lol: 8-)

Also, I just realized that this trapped, onpickup item may be the kind of thing I need for an other puzzle I have put away and forgot. But I would like to understand it a bit better.
Can I use it to call a function that has been defined in a script entity inside the mod? Or do I need to script it all in the asset definition?
SpoilerShow
I want to make a trapped room. When the treasure is picked up, the room (gradually) fills with poison gas and the party must escape quickly through a hidden exit.
Though it is not a whole bunch of code, it would be more convenient to be able to adjust the trap itself from inside the editor instead of having to close the project, open the .lua file, save it, reopen project etc. Also I'm not sure what this hook is capable of and what it can't do. Can it for example be used to close a specific door?

Btw, when does the onEquip hook trigger? Only if the item is put into a hand or even if into the inventory? And how many times does it trigger?
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: [mod-wip] Treasury - General Help Me

Post by Isaac »

Glew wrote:...
  • The sockets should work just the same, but with red gems.
  • Image
  • You can usually call a defined function from the hooks by using the full path. eg. myScriptName.myFunctionInTheScript()
  • The onEquipItem code runs every time that the item is placed in the hand, or in the inventory.
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: [mod-wip] Treasury - General Help Me

Post by Glew »

Isaac wrote: [*]The onEquipItem code runs every time that the item is placed in the hand, or in the inventory.[/list]
So even when moved around? (so if it is placed from hand to inventory, or from one inventory to an other)
And just to make sure which .lua does the party re-definition and the eye-socket go into? I know that items belong in items.lua, but not sure about those. I would guess that the sockets go into objects.lua; but the party? And will making the new party automatically replace the default one? Could this cause bugs?
edit:from the original asset definition pack, I guess the party goes to objects.lua too. Correct?

About the sockets again: Is it possible to make them in a way so they accept multiple, different objects? For example poison_gems and fake_poison_gems?

edit:
THIS actually works (at least this far)

Code: Select all

defineObject{
       name = "poison_mouth_socket",
       class = "Alcove",
       anchorPos = vec(0, 1.1, -0.38), 
       targetPos = vec(0, 1.1, -0.38),
       targetSize = vec(0.3, 0.3, 0.3),
       placement = "wall",
       onInsertItem = function(self, item)
          return ((item.name == "poison_gem") or (item.name == "fake_poison_gem")) and self:getItemCount() == 0 
       end,
       editorIcon = 92,
    }
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: [mod-wip] Treasury - General Help Me

Post by Isaac »

The Party definition is usually placed in the "object.lua" file in the mod's scripts folder.

The onEquipItem hook runs even when moving the item between inventory slots of the same PC.
The onPickUpItem hook runs only when the item is picked up from the ground, or an alcove.
Post Reply