Jump to content

How to make an item unequippable when it runs out of uses?


Recommended Posts

Yo, me again.

This time i need help making an item unusable when it runs out of uses. I have an item that works in some sorta fuel fashion, so i want it when it reaches 0 uses left, the item is left uniquippable untill it has uses. How can i do this?

Link to comment
Share on other sites

2 minutes ago, ZupaleX said:

Use the onequip function to check if it has some usage remaining. If it doesn't, call Unequip immediately.

How do i do that? i'm not really too knowledgable on coding

Link to comment
Share on other sites

2 minutes ago, ZupaleX said:

Your item must have an inventoryitem component attached to it. You can override the onequip function from this component to do what I was talking about.

If you need more hints let me know.

I do have components for inventory item, i'm just not really sure how to call the unequip function

Link to comment
Share on other sites

I made a "typo", it's the equippable component.

it would be something along these lines

assets = {
	[... some assets ...]
}

prefabs = {
	[... some prefabs ...]
}

local function MyOnEquip(inst, owner)
	[... do your stuffs to check the usage ...]

	if [you are not happy with what you got] and inst.components.equippable then
		inst.components.equippable:Unequip(owner)
	end
end

local function prefabfn()
	local inst = CreateEntity()

	[... do some stuffs ...]

	if not TheWorld.ismastersim then
		return inst
	end

	[... do some other stuffs ...]

	inst:AddComponent("equippable")
	inst.components.equippable:SetOnEquip(MyOnEquip)

	[... let's get crazy and do even more stuffs ...]
end

return  Prefab("common/inventory/myprefab", prefabfn, assets, prefabs)

 

Edited by ZupaleX
Link to comment
Share on other sites

7 minutes ago, ZupaleX said:

I made a "typo", it's the equippable component.

it would be something along these lines


local function MyOnEquip(inst, owner)
	[... do your stuffs to check the usage ...]

	if [you are not happy with what you got] and inst.components.equippable then
		inst.components.equippable:Unequip(owner)
	end
end

local function prefabfn()
	local inst = CreateEntity()

	[... do some stuffs ...]

	if not TheWorld.ismastersim then
		return inst
	end

	[... do some other stuffs ...]

	inst:AddComponent("equippable")
	inst.components.equippable:SetOnEquip(MyOnEquip)
end

 

Doesn't seem to work. All it did is set the item's state to unequipped, even if it's equipped. Right clicking the item in the inventory will just re-do the equipping (Instead of unequipping, like all other items do when right clicked on the player's hand)

Link to comment
Share on other sites

Hmmm yes it's because the equippable.onequip is called too early for what I wanted it to do. Beginner's mistake. You could put it in a DoTaskInTime so it is called after the Equip function is done running but that might lead to clunky results.

Why not remove the Equippable component when the usage falls to 0 and add it back when it goes above 0?

Edited by ZupaleX
Link to comment
Share on other sites

4 minutes ago, ZupaleX said:

Hmmm yes it's because the equippable.onequip is called too early for what I wanted it to do. Beginner's mistake. You could put it in a DoTaskInTime so it is called after the Equip function is done running but that might lead to clunky results.

Why not remove the Equippable component when the usage falls to 0 and add it back when it goes above 0?

And how do i do that?

Link to comment
Share on other sites

use inst:RemoveComponent("equippable"). I do not guarantee the result and I think there must be a more elegant wat but I am too sleepy to think about it right now. Maybe I'll come up with something better tomorrow :)

Link to comment
Share on other sites

I checked the possessedaxe.lua component (the one handling the fact that only woodie can hold lucy) and they actually use the DoTaskInTime trick.

I am not sure actually I understand why the OnEquip thingy is not working since I checked the even pushed after OnEquip function is called and it doesn't restore the equipped item actually.

You can try to add DoTaskInTime(0, ... before the function I proposed yesterday.

Otherwise you could try instead of putting it in the OnEquip, something like this

inst.checkusage = function(inst, data)
	if [... check for usage and whatever you want ...] then
		inst:DoTaskInTime(0, function() inst.components.equippable:Unequip(data.owner))
	end
end

inst:ListenForEvent("equipped", inst.checkusage)

Untested so it might not work as is, but that's the idea.

Link to comment
Share on other sites

10 hours ago, ZupaleX said:

I checked the possessedaxe.lua component (the one handling the fact that only woodie can hold lucy) and they actually use the DoTaskInTime trick.

I am not sure actually I understand why the OnEquip thingy is not working since I checked the even pushed after OnEquip function is called and it doesn't restore the equipped item actually.

You can try to add DoTaskInTime(0, ... before the function I proposed yesterday.

Otherwise you could try instead of putting it in the OnEquip, something like this


inst.checkusage = function(inst, data)
	if [... check for usage and whatever you want ...] then
		inst:DoTaskInTime(0, function() inst.components.equippable:Unequip(data.owner))
	end
end

inst:ListenForEvent("equipped", inst.checkusage)

Untested so it might not work as is, but that's the idea.

:36: unexpected symbol near ')'

It gives me that error (:36: is the line i put that code in)

Link to comment
Share on other sites

1 minute ago, ZupaleX said:

Can you post the complete code?

Otherwise an immediate issue I see is that the function inside the DoTaskInTime is missing an "end" to close it.

I did notice the lack of an end so i put it there myself

Here's the entire code in the Prefab

Spoiler

local assets =
{
    Asset("ANIM", "anim/giita.zip"),
    Asset("ANIM", "anim/swap_giita.zip"),
    
    Asset("ATLAS", "images/inventoryimages/giita.xml"),
    Asset("IMAGE", "images/inventoryimages/giita.tex"),
}
local prefabs =
{
}

local function ShouldAcceptItem(inst, item)
    if item.prefab == "silk" then
       return true
    end
    return false
end

local function OnGetItemFromPlayer(inst, giver, item)
    if item.prefab == "silk" then
       inst.components.finiteuses.current = inst.components.finiteuses.current + 25
    end
    if inst.components.finiteuses.current > inst.components.finiteuses.total then
       inst.components.finiteuses.current = inst.components.finiteuses.total
    end
end


local function OnEquip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "swap_giita", "swap_giita")
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
    inst.checkusage = function(inst, data)
    if inst.components.finiteuses.current <= 0 then
        inst:DoTaskInTime(0, function() inst.components.equippable:Unequip(data.owner))
    end
end

inst:ListenForEvent("equipped", inst.checkusage)
end
end

local function OnUnequip(inst, owner)
    owner.AnimState:Hide("ARM_carry")
    owner.AnimState:Show("ARM_normal")
end

local function fn()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()
    
    local sound = inst.entity:AddSoundEmitter() 
    MakeInventoryPhysics(inst)

    inst.AnimState:SetBank("giita")
    inst.AnimState:SetBuild("giita")
    inst.AnimState:PlayAnimation("idle")
    
    inst:AddTag("sharp")
    
    if not TheWorld.ismastersim then
        return inst
    end
    

    inst.entity:SetPristine()

   

    inst:AddComponent("weapon")
    inst.components.weapon:SetDamage(50)
    
    inst:AddComponent("finiteuses")
    inst.components.finiteuses:SetMaxUses(150)
    inst.components.finiteuses:SetUses(150)
    if inst.components.finiteuses.current < 0 then
       inst.components.finiteuses.current = 0
    end
    
    inst:AddComponent("trader")
    inst.components.trader.onaccept = OnGetItemFromPlayer
    inst.components.trader:SetAcceptTest(ShouldAcceptItem)

    

    inst:AddComponent("inspectable")

    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "giita"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/giita.xml"

    inst:AddComponent("equippable")
    inst.components.equippable:SetOnEquip( OnEquip )
    inst.components.equippable:SetOnUnequip( OnUnequip )

    MakeHauntableLaunch(inst)

    return inst
end

STRINGS.NAMES.GIITA = "Giita the Guitar"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.GIITA = "Smells like cake."

return  Prefab("common/inventory/giita", fn, assets, prefabs)

 

Link to comment
Share on other sites

local function OnEquip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "swap_giita", "swap_giita")
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
    inst.checkusage = function(inst, data)

    if inst.components.finiteuses and inst.components.finiteuses.current <= 0 then
        inst:DoTaskInTime(0, function() 
			inst.components.equippable:Unequip(data.owner) 
 		end)
                                                                            
		inst:ListenForEvent("equipped", inst.checkusage)
    end
end

You had too many "end".

Try this one.

Link to comment
Share on other sites

11 minutes ago, ZupaleX said:

local function OnEquip(inst, owner)
    owner.AnimState:OverrideSymbol("swap_object", "swap_giita", "swap_giita")
    owner.AnimState:Show("ARM_carry")
    owner.AnimState:Hide("ARM_normal")
    inst.checkusage = function(inst, data)

    if inst.components.finiteuses and inst.components.finiteuses.current <= 0 then
        inst:DoTaskInTime(0, function() 
			inst.components.equippable:Unequip(data.owner) 
 		end)
                                                                            
		inst:ListenForEvent("equipped", inst.checkusage)
    end
end

You had too many "end".

Try this one.

There was actually the right amount of ends, if i don't add another one, the function fuses with others.

It seems that it no longer crashes the game. But it doesn't seem to unequip it (I tried equipping it and re-equipping, hitting something, and refueling it and getting its uses back to 0)

Link to comment
Share on other sites

Yes you had the proper amount but they were not were they should sorry for the confusion.

I will have to try it on my end because I don't see a reason why it would not work currently.

I would advise to put a bunch of print function to make sure that the chunks of code are properly executed and in the proper order.

 

EDIT: ok I found the issue, I just read too fast something. I send an updated code proposition in a few.

Edited by ZupaleX
Link to comment
Share on other sites

So this time I actually tested it in game and this works

	inst.checkusetask = function(inst, data)
		if inst.components.equippable then
			inst:DoTaskInTime(0, function() 
				if data.owner and data.owner.components and data.owner.components.inventory then
					local item = data.owner.components.inventory:Unequip(EQUIPSLOTS.HANDS) or nil
					if item ~= nil then
						data.owner.components.inventory:GiveItem(item)
					end
				end
			end)
		end
	end
	
	inst:ListenForEvent("equipped", inst.checkusetask)

Don't forget to add the check for the usage where it belongs.

Link to comment
Share on other sites

It seems to almost work now, but there's still issues.

The item only seems to check uses when equipped, which means that it won't unequip when it reaches 0 uses in the hand (but will prevent re-equipping if unequipped). Another issue is that it can't be equipped back when refueled untill the world is restarted.

Link to comment
Share on other sites

Indeed the code I sent is just for when you equip it.

From there it should not be too hard to write something which check when it is already equipped and the usage reaches 0. Use the same principle and catch a different event, like the event pushed when the item falls to 0 usage.

For the fact it cannot be reequipped, it's because you need to add a function which checks when the usage goes above 0 to disable the function preventing the item to be equipped.

Link to comment
Share on other sites

The thing is that I don't want to write you the code as I did for the previous check because you won't learn anything like that.

Do you understand what the chunk I sent you for the unequip does? I mean line by line? If not try to take a bit of time to understand what's happening. Once it is done you can write the other check by yourself because it will be the same, you will just need to access the proper components.

If you do not understand then we can go over it together.

Link to comment
Share on other sites

16 minutes ago, ZupaleX said:

The thing is that I don't want to write you the code as I did for the previous check because you won't learn anything like that.

Do you understand what the chunk I sent you for the unequip does? I mean line by line? If not try to take a bit of time to understand what's happening. Once it is done you can write the other check by yourself because it will be the same, you will just need to access the proper components.

If you do not understand then we can go over it together.

I also will not really learn anything if i dont have anywhere where to look.

I don't really know much about the coding in this game, so most of the code just goes over my head right now, but as i go, i'll be learning what each of the actions do.

Link to comment
Share on other sites

1 hour ago, Kooby said:

I also will not really learn anything if i dont have anywhere where to look.

Yeah, but you will probably learn more if someone explain you how the code work rather than making same variation of code again and again. If you understand how it works you could make your own variation by searching in the game files for the right names to use and all this stuff. Hence why he is asking if you understand it, i guess, so he could help you better.

Link to comment
Share on other sites

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
 Share

×
  • Create New...