Jump to content

Help with item mod


Recommended Posts

So, I've been working on an item mod. It's working perfectly so far except I just can't figure out how to add one of the features I want to.

 

It's meant to be a character specific item that lets the character regain a small amount of sanity over time whilst being kept in their inventory. However, it's not an equipable item.

 

Could anyone help me figure out the code for this? Everything I've tried so far has resulted in a crash.

Link to comment
Share on other sites

@LordMogar You could create a PeriodicTask to run when the item is given to the character (picked up), and remove it when it's taken away (dropped, put in chest, etc).

The inventoryitem component pushes events: onputininventory, ondropped, and onpickup. You can see how they function in "..\scripts\components\inventoryitem.lua".

 

Syntax.

-- Where inst is the item's instance-- Replace event_name according to your code designinst:ListenForEvent("event_name", function(inst, data)    -- Activate PeriodicTask    local task = inst:DoPeriodicTask(1, function()        -- Heal or something    end)    -- Deactivate PeriodicTask    -- Ideally, this would be associated with another event listener, not inside this function    task:Cancel()end)
Link to comment
Share on other sites

I've been messing with the stuff you gave me for a while now and it keeps crashing. I'm not sure I'm doing this entirely right. :/

 

    inst:ListenForEvent("onputininventory", function(inst, data)
    local task = inst:DoPeriodicTask(1, function(inst) inst.components.sanity:DoDelta(20) end)
 
    inst:ListenForEvent("ondropped", function(inst, data)
    task:Cancel()
end)
 
 
Here's the error it keeps giving.
 
42: ')' expected (to close '(' at line 30) near 'return'
Link to comment
Share on other sites

@LordMogar I don't think you've completely grasped the concept of functions and variables yet.

Does this make more sense?

-- This function will be called when the ondropped event is pushed.local function SomeFunction(inst, data)    print("Item dropped!")end-- Associates the SomeFunction function with the ondroppped event.inst:ListenForEvent("ondropped", SomeFunction)

-

 

Edit: Couldn't find the post explaining this topic in detail.

 

Edit 2:

local taskinst:ListenForEvent("onputininventory", function(inst, data)	task = inst:DoPeriodicTask(1, function()		-- Do something	end)end)inst:ListenForEvent("ondropped", function(inst, data)	if task then		task:Cancel()		task = nil	endend)
Link to comment
Share on other sites

No, I'm not very good with this stuff unfortunately, I'm surprised I've gotten as far in with the process of making mods as I have.

 

I tried applying the script from your second edit. I added in the sanity component and got past the main menu and ingame, a step up from previous attempts. This time however upon picking up the item the game crashes and prints the error, "attempt to index field 'sanity' (a nil value)".

 

Here's the whole .lua file for my item's prefab. Did I forget to add something?

local assets ={    Asset("ANIM", "anim/bear.zip"),    Asset("SOUND", "sound/common.fsb"),}local function fn()    local inst = CreateEntity()    inst.entity:AddTransform()    inst.entity:AddAnimState()    inst.entity:AddNetwork()    MakeInventoryPhysics(inst)    inst.AnimState:SetBank("bear")    inst.AnimState:SetBuild("bear")    inst.AnimState:PlayAnimation("idle")    if not TheWorld.ismastersim then        return inst    end    inst:AddComponent("inspectable")    inst:AddComponent("inventoryitem")    inst.components.inventoryitem.atlasname = "images/inventoryimages/bear.xml"local task inst:ListenForEvent("onputininventory", function(inst, data)    task = inst:DoPeriodicTask(1, function()    inst.components.sanity:DoDelta(20)    end)end) inst:ListenForEvent("ondropped", function(inst, data)    if task then        task:Cancel()        task = nil    endend)    MakeHauntableLaunch(inst)    return instendreturn Prefab( "common/inventory/bear", fn, assets) 
Link to comment
Share on other sites

@LordMogar I figured this would arise. The inst you are referring to isn't the player instance, it's the item's instance.

You can access the owner of the item like so.

inst.owner.components.sanity:DoDelta(20)

I'd suggest checking if everything is valid too.

if inst.owner and inst.owner.components.sanity then    -- ...end
Link to comment
Share on other sites

Well, the game isn't crashing at all anymore. However the item has gone back to doing nothing at all when in the inventory, so the desired effect isn't working. :/ I'm probably not using this correctly? Like I've mentioned I'm not good with this.

if inst.owner and inst.owner.components.sanity thenlocal task inst:ListenForEvent("onpickup", function(inst, data)   inst.task = inst:DoPeriodicTask(1, function() inst.owner.components.sanity:DoDelta(20) end)end)inst:ListenForEvent("ondropped", function(inst, data)    if task then        task:Cancel()        task = nil    endend)end
Link to comment
Share on other sites

@LordMogar

-- inst.owner may be nil over here-- you don't want to check it until the person has the itemlocal task  inst:ListenForEvent("onpickup", function(inst, data)   -- Why was this inst.task? it should be just task   -- Unless you're going to use inst.task elsewhere too.   task = inst:DoPeriodicTask(1, function()      if inst.owner and inst.owner.components.sanity then      -- If statement is for this part         inst.owner.components.sanity:DoDelta(20)      end   end)end) inst:ListenForEvent("ondropped", function(inst, data)    if task then        task:Cancel()        task = nil    endend) 

Edit: Read comments above again, changed them a bit.

Edit2: Changed code a bit. Re-read.

Link to comment
Share on other sites

Just tried it with your revisions, it still isn't doing anything. I have no idea what's up with it.

 

Edit: Just saw your edit woops, I'll try it out again.

Edit2: Nope, it still isn't doing anything.

Link to comment
Share on other sites

@LordMogar Just looked through the inventoryitem code. I think the inst.owner variable might not be set upon picking up items. Luckily, the event passes that information.

 

Change this part.

inst:ListenForEvent("onpickup", function(inst, data)   -- data.owner contains the instance of whoever picked the item   if data.owner and data.owner.components.sanity then      task = inst:DoPeriodicTask(1, function()         data.owner.components.sanity:DoDelta(20)      end)   endend)
Link to comment
Share on other sites

Works like a charm! Now just gotta tweak it to a more reasonable value. Thank you very much for the help. :-)

 

Edit: Except for one thing. It doesn't seem to be cancelling the task when the item is dropped.

Link to comment
Share on other sites

@LordMogar Ensure the "task" variable is only being used once, and you're using it consistantly. Not inst.task and task, just one or the other.

local task -- Puts variable in outer scope so it can be accessed in both functions-- Inside the pickup function    if not task then -- Ensure it won't be overwritten unless it's nil        task = something    end-- Inside the drop function    if task then        task:Cancel()    end

Edit: fixed "if not task"

Link to comment
Share on other sites

Only task is being used, no inst.task or anything like that.

local task   inst:ListenForEvent("onpickup", function(inst, data)   if data.owner and data.owner.components.sanity then      task = inst:DoPeriodicTask(1, function()         data.owner.components.sanity.dapperness = 0.1      end)   endend)  inst:ListenForEvent("ondropped", function(inst, data)    if task then        task:Cancel()        task = nil    endend) 
Link to comment
Share on other sites

@LordMogar Re-read my post, notice the if statements. Try to figure it out, this one is simple if you give it some thought. If you still can't get it, ask. Programming is all about figuring out solutions for problems, you're gonna have to practice it yourself if you wanna make something worthwhile.

Link to comment
Share on other sites

I'm afraid I still don't get it. Maybe I've been staring at it for too long? I've noted that in your post you said to include "if task then" inside the pickup function, which my code lacks. However I don't see where or how to apply that if needed, considering it doesn't fit in the context of mine.

 

Does that have anything to do with why it isn't working?

Link to comment
Share on other sites

@LordMogar Yup, that's the part.

local task    inst:ListenForEvent("onpickup", function(inst, data)   if data.owner and data.owner.components.sanity then      if not task then -- Fits right here         -- You don't want the task variable below to be overwritten unless it's nil         task = inst:DoPeriodicTask(1, function()            data.owner.components.sanity.dapperness = 0.1         end)      end   endend)   inst:ListenForEvent("ondropped", function(inst, data)    if task then        task:Cancel()        task = nil    endend)

Edit: Whoops, completely reversed that. Should be "if not task then". Fixed. Sorry bout that, haha.

Link to comment
Share on other sites

@LordMogar Ah.. I just realize you changed the sanity DoDelta command to a dapperness value.

 

If you're using dapperness, then you won't have to use a PeriodicTask at all.

local ownerinst:ListenForEvent("onpickup", function(inst, data)   owner = data.owner   if owner and owner.components.sanity then      owner.components.sanity.dapperness = 0.1   endend)inst:ListenForEvent("ondropped", function(inst, data)   if owner and owner.components.sanity then      owner.components.sanity.dapperness = 0   endend)
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...