Item Specific Container

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
EnochDagor
Posts: 25
Joined: Fri Mar 27, 2015 10:53 pm

Item Specific Container

Post by EnochDagor »

I was thinking a neat item might be a container for a specific type of item.

For example, an herb satchel.

So, I created the item from a base_item. Here's my container definition where I was trying the theory in general... basically, if I can get the item to remove itself and reattach to the mouse, I want to do that... then I can do it by type.

Code: Select all

	{
		class = "ContainerItem",
		containerType = "chest",
		onInsertItem = function(self, item, slot)
			local theObj = self:getItem(slot)
			if theObj ~= nil then
				self:removeItemFromSlot(slot) 
				setMouseItem(item)
			end
			return false
		end 
	},
This code works but the mouse item does not get set. Well, that's not entirely accurate. The Mouse Item gets set while I'm in scope of the function (if I do a getMouseItem and print the ID its the correct ID). But once the scope is left, I lose the item.

Any ideas on what I am doing wrong?
MrChoke
Posts: 324
Joined: Sat Oct 25, 2014 7:20 pm

Re: Item Specific Container

Post by MrChoke »

You need to call setMouseItem() in a delayedCall and it should work.

Replace setMouseItem with something like:

Code: Select all

delayedCall("script_entity_01", 0.1, "giveMouseItem", item.go.id)
In a script entity with id of "script_entity_01", define this function:

Code: Select all

function giveMouseItem(itemId)
    local itemGO = findEntity(itemId)
    setMouseItem(itemGO.item)
end
Dunkler
Posts: 73
Joined: Thu Jul 10, 2014 3:20 pm

Re: Item Specific Container

Post by Dunkler »

Did you guys ever suceed in this script?

I tried to create a Spellbook item that can only fit "SpellScrollItem" but i failed :)

When i try to put an item into the Spellbook it just vanishes. Im probably just too bad at scripting though :)
EnochDagor
Posts: 25
Joined: Fri Mar 27, 2015 10:53 pm

Re: Item Specific Container

Post by EnochDagor »

Unfortunately, no. I tried to do the delay but it still did not work 100% (and actually lead to a nasty bug where items insta-charged which I saved for later use).

Instead, I simply allowed it for my current scenario and put an OOC to not mess with the item. I will go back at some point and try again when I get time.

-E
Dunkler
Posts: 73
Joined: Thu Jul 10, 2014 3:20 pm

Re: Item Specific Container

Post by Dunkler »

Thanks for the reply :)

At least i know that i dont have to bother with the "spellbook" anymore. I am using another Spell scroll learn script now anyway..so no spellbook needed :)
User avatar
Zo Kath Ra
Posts: 944
Joined: Sat Apr 21, 2012 9:57 am
Location: Germany

Re: Item Specific Container

Post by Zo Kath Ra »

Put a script entity called "script_entity_1" in your mod, and put this code in it:

Code: Select all

function giveMouseItem(item_id, altar_id)
	local item_local = findEntity(item_id)
	local altar_local = findEntity(altar_id)
	
	if ((item_local ~= nil) and (altar_local ~= nil)) then
		setMouseItem(item_local.item)
		altar_local:destroy()
	end
end
This bag only accepts keys:

Code: Select all

defineObject{
    name = "key_bag",
    baseObject = "base_item",
    components = {
        {
            class = "Model",
            model = "assets/models/items/sack_empty.fbx",
        },
        
        {
            class = "Item",
            uiName = "Key Bag",
            gfxIndex = 82,
            gfxIndexContainer = 482,
            weight = 0.4,
            fitContainer = false,
        },
        
        {
            class = "ContainerItem",
            containerType = "sack",
            openSound = "container_sack_open",
            closeSound = "container_sack_close",
            
            onInit = function(self)
                if self:getItemCount() > 0 then
                    self.go.model:setModel("assets/models/items/sack_full.fbx")
                    self.go.item:setGfxIndex(81)
                    self.go.item:updateBoundingBox()
                end
            end,
            
            onInsertItem = function(self, item, slot)
                if (item:hasTrait("key")) then
                    self.go.data:set("item_id", nil)
                    self.go.data:set("altar_id", nil)
                    
                    -- convert to full sack
                    if self.go.item:getGfxIndex() == 82 then
                    self.go.model:setModel("assets/models/items/sack_full.fbx")
                    self.go.item:setGfxIndex(81)
                        self.go.item:updateBoundingBox()
                    end
                else
                    hudPrint("This bag only accepts keys!")
                    
                    self.go.data:set("item_id", item.go.id)
                    
                    local altar_local = spawn("altar", party.level, party.x, party.y, party.facing, party.elevation)
                    self.go.data:set("altar_id", altar_local.id)
                    altar_local.surface:addItem(item)
                    
                    self:removeItemFromSlot(slot)
                    
                    if (getMouseItem() ~= nil) then
                        if (getMouseItem().go.id ~= item.go.id) then
                            self:insertItem(slot, getMouseItem())
                        end
                    end
                end
            end,
            
            onRemoveItem = function(self, item)
                if ((self.go.data:get("item_id") ~= nil) and (self.go.data:get("altar_id") ~= nil)) then
                    delayedCall("script_entity_1", 0, "giveMouseItem", self.go.data:get("item_id"), self.go.data:get("altar_id"))
                    self.go.data:set("item_id", nil)
                    self.go.data:set("altar_id", nil)
                end
                
                -- convert to empty sack when last item is removed
                if self:getItemCount() == 0 and self.go.item:getGfxIndex() == 81 then
                    self.go.model:setModel("assets/models/items/sack_empty.fbx")
                    self.go.item:setGfxIndex(82)
                    self.go.item:updateBoundingBox()
                end
            end,
        },
        
        {
            class = "Script",
            name = "data",
            source = [[
                data = { ["item_id"] = nil, ["altar_id"] = nil }
                
                get = function(self, name)
                return self.data[name]
                end
                
                set = function(self, name, value)
                self.data[name] = value
                end
            ]],
        }
    },
}
Based on viewtopic.php?f=22&t=8464&p=93490#p93489
User avatar
Zo Kath Ra
Posts: 944
Joined: Sat Apr 21, 2012 9:57 am
Location: Germany

Re: Item Specific Container

Post by Zo Kath Ra »

Simpler version of the bag code:

Code: Select all

defineObject{
    name = "key_bag",
    baseObject = "base_item",
    components = {
        {
            class = "Model",
            model = "assets/models/items/sack_empty.fbx",
        },
        
        {
            class = "Item",
            uiName = "Key Bag",
            gfxIndex = 82,
            gfxIndexContainer = 482,
            weight = 0.4,
            fitContainer = false,
        },
        
        {
            class = "ContainerItem",
            containerType = "sack",
            openSound = "container_sack_open",
            closeSound = "container_sack_close",
            
            onInit = function(self)
                if self:getItemCount() > 0 then
                    self.go.model:setModel("assets/models/items/sack_full.fbx")
                    self.go.item:setGfxIndex(81)
                    self.go.item:updateBoundingBox()
                end
            end,
            
            onInsertItem = function(self, item, slot)
                if (item:hasTrait("key")) then
                    -- convert to full sack
                    if self.go.item:getGfxIndex() == 82 then
                    self.go.model:setModel("assets/models/items/sack_full.fbx")
                    self.go.item:setGfxIndex(81)
                        self.go.item:updateBoundingBox()
                    end
                else
                    hudPrint("This bag only accepts keys!")
                    
                    local altar_local = spawn("altar", party.level, party.x, party.y, party.facing, party.elevation)
                    altar_local.surface:addItem(item)
                    
                    self:removeItemFromSlot(slot)
                    
                    delayedCall("script_entity_1", 0, "giveMouseItem", item.go.id, altar_local.id)
                    
                    if (getMouseItem() ~= nil) then
                        if (getMouseItem().go.id ~= item.go.id) then
                            self:insertItem(slot, getMouseItem())
                        end
                    end
                end
            end,
            
            onRemoveItem = function(self, item)
                -- convert to empty sack when last item is removed
                if self:getItemCount() == 0 and self.go.item:getGfxIndex() == 81 then
                    self.go.model:setModel("assets/models/items/sack_empty.fbx")
                    self.go.item:setGfxIndex(82)
                    self.go.item:updateBoundingBox()
                end
            end,
        },
    },
}
User avatar
Eleven Warrior
Posts: 752
Joined: Thu Apr 18, 2013 2:32 pm
Location: Australia

Re: Item Specific Container

Post by Eleven Warrior »

Zo would you be able to create a new (Mortar) eg: The dm_tool_box from Germmany. When you put items in the Tool Box you can make things like a Torch, hammer etc... It will need to have a recipe function like the mortar though. Ok if you can give me a pm please. This would be super awesome for everyone thxs :)
Post Reply