LisaMcRad Posted September 12, 2021 Share Posted September 12, 2021 (edited) Hey everyone, So for Freya, I wanted to give her the Lazy Forager effect (of picking up items). However, I've tried to go to the amulet.lua files and copy over the lazy forager effect to my name.lua file and I haven't gotten anything working yet. If anybody could help me out with this, it would be greatly appreciated. Edited September 14, 2021 by LisaMcRad Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/ Share on other sites More sharing options...
Thomas_klei Posted September 13, 2021 Share Posted September 13, 2021 Who's Freya and how have you copied of the code and can you show me it. Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494401 Share on other sites More sharing options...
LisaMcRad Posted September 13, 2021 Author Share Posted September 13, 2021 1 hour ago, Thomas Die said: Who's Freya and how have you copied of the code and can you show me it. 1. The character I've been working on 2. I've literally copied this portion from the orange amulet portion of the amulet.lua file. It was placed in the freya.lua file just before the revive code. local function pickup(inst, owner) if owner == nil or owner.components.inventory == nil then return end local x, y, z = owner.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x, y, z, TUNING.ORANGEAMULET_RANGE, ORANGE_PICKUP_MUST_TAGS, ORANGE_PICKUP_CANT_TAGS) local ba = owner:GetBufferedAction() for i, v in ipairs(ents) do if v.components.inventoryitem ~= nil and v.components.inventoryitem.canbepickedup and v.components.inventoryitem.cangoincontainer and not v.components.inventoryitem:IsHeld() and owner.components.inventory:CanAcceptCount(v, 1) > 0 and (ba == nil or ba.action ~= ACTIONS.PICKUP or ba.target ~= v) then if owner.components.minigame_participator ~= nil then local minigame = owner.components.minigame_participator:GetMinigame() if minigame ~= nil then minigame:PushEvent("pickupcheat", { cheater = owner, item = v }) end end --Amulet will only ever pick up items one at a time. Even from stacks. SpawnPrefab("sand_puff").Transform:SetPosition(v.Transform:GetWorldPosition()) inst.components.finiteuses:Use(1) local v_pos = v:GetPosition() if v.components.stackable ~= nil then v = v.components.stackable:Get() end if v.components.trap ~= nil and v.components.trap:IsSprung() then v.components.trap:Harvest(owner) else owner.components.inventory:GiveItem(v, nil, v_pos) end return end end end The only thing I've seen is that it doesn't work. It's maybe that I'm missing something else to go along with it, maybe something to activate the effect passively (like an aura?) Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494418 Share on other sites More sharing options...
Nelzanger Posted September 13, 2021 Share Posted September 13, 2021 (edited) First and foremost, check that ORANGE_PICKUP_CANT_TAGS and ORANGE_PICKUP_MUST_TAGS do exists in your file, and are correctly copied, since they are local to amulet.lua. Then, if you copied the code for the Lazy Forager and changed nothing to it, and have no crashes, I think this would be linked to calling your special function every x frames. The copied code needs to be called and can be only executed once, unless you create a task that runs periodically with that function. Check the code below ; the lazy forager function, whose effect are periodically called with DoPeriodicTask : local function onequip_orange(inst, owner) owner.AnimState:OverrideSymbol("swap_body", "torso_amulets", "orangeamulet") inst.task = inst:DoPeriodicTask(TUNING.ORANGEAMULET_ICD, pickup, nil, owner) end local function onunequip_orange(inst, owner) owner.AnimState:ClearOverrideSymbol("swap_body") if inst.task ~= nil then inst.task:Cancel() inst.task = nil end end The onequip_orange function is the one called when your character equips the amulet, and the onunequip_orange is the one when you remove it. Since the amulet can be equipped, it has the "equippable" component attached to it, which contains OnEquip and OnUnequip methods, and those will call the specified ones for the lazy forager as seen with those lines : inst.components.equippable:SetOnEquip(onequip_orange) inst.components.equippable:SetOnUnequip(onunequip_orange) And that's how the effect is triggered when equipping the amulet. In your case, if the effect is meant to be automatic like the amulet, you will also need to create a periodic task. Otherwise, if it's an action (like Wortox' soul hop), no need to make a periodic task, but you will have to create a custom action. I don't know how to create one, but some mods did (Ex: Warfarin with dashes), so you can check how they managed to do it. Edited September 13, 2021 by Nelzanger 1 Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494426 Share on other sites More sharing options...
LisaMcRad Posted September 13, 2021 Author Share Posted September 13, 2021 2 hours ago, Nelzanger said: First and foremost, check that ORANGE_PICKUP_CANT_TAGS and ORANGE_PICKUP_MUST_TAGS do exists in your file, and are correctly copied, since they are local to amulet.lua. Then, if you copied the code for the Lazy Forager and changed nothing to it, and have no crashes, I think this would be linked to calling your special function every x frames. The copied code needs to be called and can be only executed once, unless you create a task that runs periodically with that function. Check the code below ; the lazy forager function, whose effect are periodically called with DoPeriodicTask : local function onequip_orange(inst, owner) owner.AnimState:OverrideSymbol("swap_body", "torso_amulets", "orangeamulet") inst.task = inst:DoPeriodicTask(TUNING.ORANGEAMULET_ICD, pickup, nil, owner) end local function onunequip_orange(inst, owner) owner.AnimState:ClearOverrideSymbol("swap_body") if inst.task ~= nil then inst.task:Cancel() inst.task = nil end end The onequip_orange function is the one called when your character equips the amulet, and the onunequip_orange is the one when you remove it. Since the amulet can be equipped, it has the "equippable" component attached to it, which contains OnEquip and OnUnequip methods, and those will call the specified ones for the lazy forager as seen with those lines : inst.components.equippable:SetOnEquip(onequip_orange) inst.components.equippable:SetOnUnequip(onunequip_orange) And that's how the effect is triggered when equipping the amulet. In your case, if the effect is meant to be automatic like the amulet, you will also need to create a periodic task. Otherwise, if it's an action (like Wortox' soul hop), no need to make a periodic task, but you will have to create a custom action. I don't know how to create one, but some mods did (Ex: Warfarin with dashes), so you can check how they managed to do it. It's supposed to be an automatic task like the amulet, but I'm also having trouble with that. Mostly since I can't find any good API documents for DST. The main issue I'm having is an error where the game crashes after I load in since it doesn't know any variables like self or the owner tag from the Orange Amulet code. I found it odd it didn't know self since I thought that would be a global variable? Maybe it could be due to me puting the DoPeriodicTask in the master_postinit function. Maybe not, I'm not sure. I've uploaded the file here if anybody would like to check. freya.lua Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494475 Share on other sites More sharing options...
Nelzanger Posted September 14, 2021 Share Posted September 14, 2021 (edited) I've looked at your file. I can't be sure at 100% because I also struggle with what I'm manipulating at times, because we don't have an API, IDE's powerful features (autocompletion, debugger, etc.) and lua does not really help since it's too high level and does not propose strong typing (I love/hate lua about that), but I'll try to guide you where the issue should be. Let's check your master post init with the following line : inst:DoPeriodicTask(1.0, pickup, nil, owner) First, the line above will never stops, and you will have no way to access the task. If you want to do so, to pause or stop it, I strongly suggest to put your task in a variable like the following, only if pickup has only one parameter, which is inst : -- Create a task that is kept into pickupTask variable, belonging to your instance. inst.pickupTask = inst:DoPeriodicTask(1.0, pickup) Then we have your pickup method. However, we know that the pickup function is for an amulet at the origin, which is an equippable and inventory item. Therefore, the amulet needs to have access to two parameters : inst, the amulet instance itself, to change the amulet variables, like the finite uses ; owner, the owner of the amulet, aka, the player prefab when wearing it, to apply effect to the player, or, accordingly to its actions/position. Back to master post init : since the parameter in master post init is "inst", the inst is probably your character prefab itself. In that case, you can already see a contradiction here in your own context, by wanting the player to pickup, and not an equippable object. Since you have already access to the player instance, you already know the "owner" : it's your prefab instance itself. And the "amulet instance" here does not exists because your player is not an amulet, so the following line makes no sense for your player : -- Makes no sense because inst is supposed here to be an amulet, containing finiteuses component to reduce its usage inst.components.finiteuses:Use(1) Therefore, the signature for your method should be the following : -- Copied and pasted from amulet.lua : Wrong because inst is expected to be an amulet, and the owner, the player prefab local function pickup(inst, owner) -- Your pickup function with your own context : Makes more sense because inst is the player prefab, so you can manipulate it already local function pickup(inst) And your pickup function should look like this, with all "owner" replaced by "inst" : -- Pickup Stuff local ORANGE_PICKUP_MUST_TAGS = { "_inventoryitem" } local ORANGE_PICKUP_CANT_TAGS = { "INLIMBO", "NOCLICK", "knockbackdelayinteraction", "catchable", "fire", "minesprung", "mineactive" } local function pickup(inst) if inst == nil or inst.components.inventory == nil then return end local x, y, z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x, y, z, TUNING.ORANGEAMULET_RANGE, ORANGE_PICKUP_MUST_TAGS, ORANGE_PICKUP_CANT_TAGS) local ba = inst:GetBufferedAction() for i, v in ipairs(ents) do if v.components.inventoryitem ~= nil and v.components.inventoryitem.canbepickedup and v.components.inventoryitem.cangoincontainer and not v.components.inventoryitem:IsHeld() and inst.components.inventory:CanAcceptCount(v, 1) > 0 and (ba == nil or ba.action ~= ACTIONS.PICKUP or ba.target ~= v) then if inst.components.minigame_participator ~= nil then local minigame = inst.components.minigame_participator:GetMinigame() if minigame ~= nil then minigame:PushEvent("pickupcheat", { cheater = inst, item = v }) end end --Amulet will only ever pick up items one at a time. Even from stacks. SpawnPrefab("sand_puff").Transform:SetPosition(v.Transform:GetWorldPosition()) local v_pos = v:GetPosition() if v.components.stackable ~= nil then v = v.components.stackable:Get() end if v.components.trap ~= nil and v.components.trap:IsSprung() then v.components.trap:Harvest(owner) else inst.components.inventory:GiveItem(v, nil, v_pos) end return end end end Feel free to correct me if I'm wrong. Again, this kind of issues arise quickly in lua because we don't know easily what we are manipulating : it requires more digging inside the methods, but also, their context of execution. Edited September 14, 2021 by Nelzanger Edit code comments so coloration would hopefully work 2 Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494690 Share on other sites More sharing options...
LisaMcRad Posted September 14, 2021 Author Share Posted September 14, 2021 2 hours ago, Nelzanger said: I've looked at your file. I can't be sure at 100% because I also struggle with what I'm manipulating at times, because we don't have an API, IDE's powerful features (autocompletion, debugger, etc.) and lua does not really help since it's too high level and does not propose strong typing (I love/hate lua about that), but I'll try to guide you where the issue should be. Let's check your master post init with the following line : inst:DoPeriodicTask(1.0, pickup, nil, owner) First, the line above will never stops, and you will have no way to access the task. If you want to do so, to pause or stop it, I strongly suggest to put your task in a variable like the following, only if pickup has only one parameter, which is inst : -- Create a task that is kept into pickupTask variable, belonging to your instance. inst.pickupTask = inst:DoPeriodicTask(1.0, pickup) Then we have your pickup method. However, we know that the pickup function is for an amulet at the origin, which is an equippable and inventory item. Therefore, the amulet needs to have access to two parameters : inst, the amulet instance itself, to change the amulet variables, like the finite uses ; owner, the owner of the amulet, aka, the player prefab when wearing it, to apply effect to the player, or, accordingly to its actions/position. Back to master post init : since the parameter in master post init is "inst", the inst is probably your character prefab itself. In that case, you can already see a contradiction here in your own context, by wanting the player to pickup, and not an equippable object. Since you have already access to the player instance, you already know the "owner" : it's your prefab instance itself. And the "amulet instance" here does not exists because your player is not an amulet, so the following line makes no sense for your player : -- Makes no sense because inst is supposed here to be an amulet, containing finiteuses component to reduce its usage inst.components.finiteuses:Use(1) Therefore, the signature for your method should be the following : -- Copied and pasted from amulet.lua : Wrong because inst is expected to be an amulet, and the owner, the player prefab local function pickup(inst, owner) -- Your pickup function with your own context : Makes more sense because inst is the player prefab, so you can manipulate it already local function pickup(inst) And your pickup function should look like this, with all "owner" replaced by "inst" : -- Pickup Stuff local ORANGE_PICKUP_MUST_TAGS = { "_inventoryitem" } local ORANGE_PICKUP_CANT_TAGS = { "INLIMBO", "NOCLICK", "knockbackdelayinteraction", "catchable", "fire", "minesprung", "mineactive" } local function pickup(inst) if inst == nil or inst.components.inventory == nil then return end local x, y, z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x, y, z, TUNING.ORANGEAMULET_RANGE, ORANGE_PICKUP_MUST_TAGS, ORANGE_PICKUP_CANT_TAGS) local ba = inst:GetBufferedAction() for i, v in ipairs(ents) do if v.components.inventoryitem ~= nil and v.components.inventoryitem.canbepickedup and v.components.inventoryitem.cangoincontainer and not v.components.inventoryitem:IsHeld() and inst.components.inventory:CanAcceptCount(v, 1) > 0 and (ba == nil or ba.action ~= ACTIONS.PICKUP or ba.target ~= v) then if inst.components.minigame_participator ~= nil then local minigame = inst.components.minigame_participator:GetMinigame() if minigame ~= nil then minigame:PushEvent("pickupcheat", { cheater = inst, item = v }) end end --Amulet will only ever pick up items one at a time. Even from stacks. SpawnPrefab("sand_puff").Transform:SetPosition(v.Transform:GetWorldPosition()) local v_pos = v:GetPosition() if v.components.stackable ~= nil then v = v.components.stackable:Get() end if v.components.trap ~= nil and v.components.trap:IsSprung() then v.components.trap:Harvest(owner) else inst.components.inventory:GiveItem(v, nil, v_pos) end return end end end Feel free to correct me if I'm wrong. Again, this kind of issues arise quickly in lua because we don't know easily what we are manipulating : it requires more digging inside the methods, but also, their context of execution. Thank you so much! This is exactly what I needed! I'm still a bit new to Lua and DST modding in general so I appreciate all the help you've been giving me! I'll def credit you when the mod releases! 1 Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494730 Share on other sites More sharing options...
Nelzanger Posted September 14, 2021 Share Posted September 14, 2021 I'm also new to modding DST and I can see how people can struggle with lua so I'm glad I could help. 1 Link to comment https://forums.kleientertainment.com/forums/topic/133589-solved-how-to-give-characters-gem-effects/#findComment-1494834 Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now