Jump to content

Recommended Posts

Hi, I can't believe this...

I was doing fueled container and started with perish fn, and made it...

But perish doesn't have add fuel... OMG

I don't know how fueled component works, but I knew how perishable component works... Meh

How can I add fuel that will prolong perishing?

I mean this.

Spoiler

local function UpdateISR(inst, dt)
	local modifier = inst.components.perishable.GetModifier()
    if modifier then
        local old_val = inst.components.perishable.perishremainingtime
        local delta = dt or (10 + math.random()*FRAMES*8)
        inst.components.perishable.perishremainingtime = inst.components.perishable.perishremainingtime - delta*modifier
        if math.floor(old_val*100) ~= math.floor(inst.components.perishable.perishremainingtime*100) then
            inst:PushEvent("perishchange", {percent = inst.components.perishable:GetPercent()})
        end
        if inst.components.perishable.perishremainingtime <= 0 then
            inst.components.perishable:Perish()
        end
    end
end

 

 

Edited by zetake
Link to comment
https://forums.kleientertainment.com/forums/topic/109053-solved-fueled-item/
Share on other sites

Why would a component controlling perishing have fuel? Those are two very different things. Unless your container is supposed to rot over time or something, it should not have a perishable component. The fueled component is pretty straightforward, though its functionality can be made very complex, since it's highly flexible. Look at the fueled component; study it. It's one of the least confusing components IMO. And you have plenty of good examples of its usage in e.g. the campfire and firepit prefabs. It is, however, two prefabs which make use of several sections (to trigger the different animations depending on how much fuel is left. You just need 1 section (which is default), and when it reaches section 0, that means your fuel has run out. The default fuel is "BURNABLE", so by default your container will accept logs, twigs etc., just like a campfire. If you want to change that, you'd have to either use one of the other fuel types (e.g., CAVE, which is what the mininglantern prefab uses), or make your own custom fuel type. If I were you, I'd start by getting the fueled component working with BURNABLE fuel first.

Edited by Ultroman

Nevermind...

When I started modding I considered this part to be most challenging, but thanks to previous parts: it was way too easy. LUL

Spoiler

modmaid

Spoiler


AddClassPostConstruct("components/container", function(self, inst)
	function self:CountAll()
		local num_found = 0
		for k,v in pairs(self.slots) do
			if v then
				if v.components.stackable ~= nil then
					num_found = num_found + v.components.stackable:StackSize()
				else
					num_found = num_found + 1
				end
			end
		end
		return num_found
	end
end)

 

prefab

Spoiler


local function OnPerish(inst)
	local inv = inst.components.inventoryitem.owner.components.inventory
	local item = SpawnPrefab("notisr")
	local slot = inv:GetItemSlot(inst)
	local con = inst.components.container
	con:DropEverything()
    inst:Remove()
	inv:GiveItem(item, slot)
end

local function OnGetConsume(inst)
	local fueled = inst.components.fueled
	if fueled then
		inst:DoTaskInTime(0.01, function()	-- in case when items will perish inside
			local con = inst.components.container
			fueled:StopConsuming()
			fueled.depletionmultiplier = 2*con:CountAll()
			fueled:StartConsuming()
		end)
	end
end

local function OnLoseConsume(inst)
	local fueled = inst.components.fueled
	if fueled then
		fueled:StopConsuming()
		local con = inst.components.container
		if not con:IsEmpty() then
			fueled.depletionmultiplier = 2*con:CountAll()
			fueled:StartConsuming()
		end
	end
end

and fn()



	inst:AddComponent("fueled")
    inst.components.fueled.accepting = true
    inst.components.fueled.fueltype = "NIGHTMARE"
    inst.components.fueled:InitializeFuelLevel(100)
    inst.components.fueled:SetDepletedFn(OnPerish)
	
	inst:ListenForEvent("itemget", OnGetConsume)
	inst:ListenForEvent("itemlose", OnLoseConsume)
	inst:ListenForEvent("dropitem", OnLoseConsume)

 

 

This makes container to start deplete if items are inside, and speed of depleting is multiplied by quantity of items.

But there is 1 bug... Eh...

When item is in container and you will add more to stack with shift + left mouse, it doesn't update... WHY?

Well, I can make depleting by occupied slot quantity, but I don't think it should work like this...

Edited by zetake

If you look at GiveItem, it seems to bypass all the paths which push the "itemget" event, when adding to a stack. Try swapping "itemget" with "containergotitem", if that's possible, or also listen to "containergotitem" and do something when that event is pushed.

You don't need to use AddClassPostConstruct. That's only if you want to add something to ALL containers. Since you only want to add your extra functions to YOUR container prefab, you can just move that code into your prefab file.

-- In your prefab Lua's fn()
inst.components.container:CountAll()
	local num_found = 0
	for k,v in pairs(self.slots) do
		if v then
			if v.components.stackable ~= nil then
				num_found = num_found + v.components.stackable:StackSize()
			else
				num_found = num_found + 1
			end
		end
	end
	return num_found
end

 

Ok, but I'm doing 3 types of containers that will work the same with a different extra fn.

containergotitem didn't work either...

But can you tell me from where comes sound effect when container get new items to stack?

I could change this part... (I could add new event push and bound this fn to my container...)

 

Edited by zetake
37 minutes ago, zetake said:

But can you tell me from where comes sound effect when container get new items to stack?

Not sure.

38 minutes ago, zetake said:

I could change this part... (I could add new event push and bound this fn to my container...)

Not sure what you mean.

BTW, if you want to study an existing function further, you can temporarily overwrite it with the original code, but add print-statements to it, so you can follow the whole chain of events. Something like this in your container prefab's fn() function, and then just add a bunch of print-statements to it. When you've figured out what you wanted, you can delete it again or comment it out if you want to use it again later.

Spoiler

inst.components.container:GiveItem = function(item, slot, src_pos, drop_on_fail, skipsound)
    drop_on_fail = drop_on_fail == nil and true or drop_on_fail
	
    if item and item.components.inventoryitem and self:CanTakeItemInSlot(item, slot) then
		
		--try to burn off stacks if we're just dumping it in there
		if item.components.stackable and slot == nil and self.acceptsstacks then
            for k = 1,self.numslots do
				local other_item = self.slots[k]
				if other_item and other_item.prefab == item.prefab and not other_item.components.stackable:IsFull() then
					
					if self.inst.components.inventoryitem and self.inst.components.inventoryitem.owner and not skipsound then
						self.inst.components.inventoryitem.owner:PushEvent("containergotitem", {item = item, src_pos = src_pos})
					end
					
		            item = other_item.components.stackable:Put(item, src_pos)
		            if not item then
						return true
		            end
				end
            end
		end
		
        local use_slot = slot and slot <= self.numslots and not self.slots[slot]
        local in_slot = nil
        if use_slot then
            in_slot = slot
        elseif self.numslots > 0 then
            for k = 1,self.numslots do
                if not self.slots[k] then
                    in_slot = k
                    break
                end
            end
        end
        
        if in_slot then

			local owner = item.components.inventoryitem.owner
			--weird case where we are trying to force a stack into a non-stacking container. this should probably have been handled earlier, but this is a failsafe        
			if item.components.stackable and item.components.stackable:StackSize() > 1 and not self.acceptsstacks then
				item = item.components.stackable:Get()
				self.slots[in_slot] = item
				item.components.inventoryitem:OnPutInInventory(self.inst)
				self.inst:PushEvent("itemget", {slot = in_slot, item = item, src_pos = src_pos, owner = owner})	
				return false
			end
			
			self.slots[in_slot] = item
			item.components.inventoryitem:OnPutInInventory(self.inst)
			self.inst:PushEvent("itemget", {slot = in_slot, item = item, src_pos = src_pos, owner = owner})

			if self.inst.components.inventoryitem and self.inst.components.inventoryitem.owner and not skipsound then
				self.inst.components.inventoryitem.owner:PushEvent("containergotitem", {item = item, src_pos = src_pos})
            elseif self.type == "boat" and not skipsound then 
                GetPlayer():PushEvent("containergotitem", {item = item, src_pos = src_pos})
			end
			
			return true
        else
            if drop_on_fail then
				item.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
				if item.components.inventoryitem then
	                item.components.inventoryitem:OnDropped(true)
				end
			end				
            return false
        end
    end
end

 

 

That's what I done.

Correction, any operation that edits stack in container doesn't push event...

Here's code from ctrl + left mouse to container existing stack...

                    item = other_item.components.stackable:Put(item, src_pos)
                    if not item then
                        return true

But, rest is somewhere else... >.<

Is there a way to detect when content of container was changed?

Or maybe I should do depleting only if container is not empy?

Edited by zetake

How about this: trigger a recalculation when the container is closed, and leave this little bug in there. It'll be a hassle to fix, since you'd have to edit the stackable component of all the perishable items (you know, because you could do something with item.components.stackable:Put()). That's what I would do. Good enough is good enough.

On 19.07.2019 at 8:02 PM, Ultroman said:

You don't need to use AddClassPostConstruct. That's only if you want to add something to ALL containers. Since you only want to add your extra functions to YOUR container prefab, you can just move that code into your prefab file.


-- In your prefab Lua's fn()
inst.components.container:CountAll()
	local num_found = 0
	for k,v in pairs(self.slots) do
		if v then
			if v.components.stackable ~= nil then
				num_found = num_found + v.components.stackable:StackSize()
			else
				num_found = num_found + 1
			end
		end
	end
	return num_found
end

 

This code isn't working...

On 19.7.2019 at 11:24 PM, zetake said:

OMG. Thanks, that solved it!


inst:ListenForEvent("stacksizechange", OnGetConsume)

 

Yeah, that's what I advocated against doing. A container mod that applies changes to all stackable items, and even hooks up event-triggers for every single time their stack size changes is, in my opinion, getting a bit out of hand. Unless you only hook up the listeners to items when they're put into your container and remove the listener again when they leave your container.

2 hours ago, zetake said:

This code isn't working...

Where did you put it?

47 minutes ago, Ultroman said:

Yeah, that's what I advocated against doing. A container mod that applies changes to all stackable items, and even hooks up event-triggers for every single time their stack size changes is, in my opinion, getting a bit out of hand. Unless you only hook up the listeners to items when they're put into your container and remove the listener again when they leave your container.

...

Just don't accuse without grounds.

Event "stacksizechange" is provided for containers and it's only triggering inside of its container...

47 minutes ago, Ultroman said:

Where did you put it?

Ofc in fn(), where else I could put it when you said I should there?

Edited by zetake
Just now, zetake said:

Just don't accuse without grounds.

Event "stacksizechange" is provided for containers and it's only triggering inside its container...

Yeah, ok. That's great :)

Just now, zetake said:

Ofc in fn(), where else I could when you said I should there?

You'd be surprised where people end up copy/pasting code xD
How does it not work? Does it not allow you to call the function afterwards? Does it crash?

It says that end is missing some line later...

So, my guess, it doesn't recognize it as a function...

 

P.S: I learned that catching triggering events depends on where listeners are put.

And in 3 var you can put source, just like I did with "continuefrompause"

Edited by zetake

Try this instead, then

inst.components.container:CountAll = function()
	local num_found = 0
	for k,v in pairs(self.slots) do
		if v then
			if v.components.stackable ~= nil then
				num_found = num_found + v.components.stackable:StackSize()
			else
				num_found = num_found + 1
			end
		end
	end
	return num_found
end

 

Worked with dot instead of colon, and with self parametr...

inst.components.container.CountAll = function(self)

I tried this before, but will small letters only, because you misguided me with removeitem...

EDIT: I misguided myself... IDK where come from idea with small letters...

Edited by zetake

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...