ArcAngela Posted September 15, 2023 Share Posted September 15, 2023 (edited) I'm trying to make an item that you don't equip and just sits on your inventory, and by having it on your inventory you gain sanity. I was told to check InventoryItem components specifically setondroppedfn and setonpickupfn but I couldn't make it work because I don't understand what I'm doing at all, items aren't my specialty. I've attached my poor attempt, but also worth noting that I plan for this item to do more than just sanity, I just need the structure to then apply effects to my heart's content. medal_red.lua Edited September 21, 2023 by ArcAngela Solved! Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/ Share on other sites More sharing options...
Hamurlik Posted September 15, 2023 Share Posted September 15, 2023 Well you could use the "itemaffinity" component: AddPlayerPostInit(function(inst) if inst.components.itemaffinity == nil then inst:AddComponent("itemaffinity") end inst.components.itemaffinity:AddAffinity("medal_red", nil, TUNING.DAPPERNESS_MED, 1) end) This adds the component to every player. Not the item itself. This should go into modmain.lua. "itemaffinity" component is not added to every player prefab, so we have to add it first. The only prefab that uses this component in vanilla is the Wurt prefab. Here is an example of how the Wurt prefab uses it to make having fish in inventory give sanity bonus (or debuff for fish meat): inst:AddComponent("itemaffinity") inst.components.itemaffinity:AddAffinity("hutch_fishbowl", nil, TUNING.DAPPERNESS_MED, 1) inst.components.itemaffinity:AddAffinity(nil, "fish", TUNING.DAPPERNESS_MED, 1) inst.components.itemaffinity:AddAffinity(nil, "fishmeat", -TUNING.DAPPERNESS_MED_LARGE, 2) inst.components.itemaffinity:AddAffinity(nil, "spoiled_fish", -TUNING.DAPPERNESS_MED_LARGE, 2) First argument is the prefab that will give sanity bonus if it's in the inventory. "medal_red" goes here. Can be nil to use a tag instead. Second argument allows to supply a tag instead of a specific prefab, so you don't have to list each one. There are many types of fish, but they all have the same "fish" tag, so all of them will give a bonus. Can be nil to use a prefab instead. Third argument is the sanity bonus. Fourth argument is the priority. This component works so that the highest priority item is the only one giving a bonus. So, in this example having fish meat has a higher priority than having live fish, only the fish meat sanity bonus (debuff in this case) will be applied; you cannot cancel out the bonus by having equal amounts of dead and alive fish. If you look into "itemaffinity.lua" and "sanity.lua" components you can see how it works under the hood. But basically, the player's sanity component has a special variable for having one, and only one additional multiplier. You can set it with: inst.components.sanity.externalmodifiers:SetModifier(inst, 1) (assuming inst is a player prefab) The game doesn't mind overriding it, it is used in few places. You could design something with this if you HAVE to have the sanity boost be in item's code, and not player's. Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665221 Share on other sites More sharing options...
ArcAngela Posted September 16, 2023 Author Share Posted September 16, 2023 (edited) That doesn't seem to be quite what I'm looking for, I've used sanity mostly as a structure to add more stuff in the future. I'm planning to do 6 medals based on each gem, and they're supposed to give multiple buffs each, to any character that has them, and obviously I need to remove said buffs from them if they decide to drop the item. I got it working with this code but this is finnicky and very limited, having 2 medals on your inventory does nothing but dropping one removes all buffs, but the biggest limitation is that I can't exactly do things like picker.components.combat.damagemultiplier = +.15 because this would break several characters and their unique damage multipliers, so I need a method to be able to always just "add" to the picker/owner so I can subtract later. You can see I added sanity and winter insulation to demonstrate how I plan to give multiple buffs with 1 medal item, but setting winter insulation to 0 sounds very problematic if a character happens to have insulation of their own. local function OnDropped(inst) --this needs a check to see if the owner still has a red_medal in their inventory in order to remove sanity inst.owner.components.sanity.dapperness = 0 inst.owner.components.temperature.inherentinsulation = 0 inst.owner = nil end local function OnPickedUp(inst, picker) inst.owner = picker if picker and picker.components.sanity then picker.components.temperature.inherentinsulation = TUNING.INSULATION_MED picker.components.sanity.dapperness = TUNING.DAPPERNESS_MED end end Edited September 16, 2023 by ArcAngela Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665386 Share on other sites More sharing options...
Hamurlik Posted September 16, 2023 Share Posted September 16, 2023 Oh, I see. Now that I look more closely at the code I realize your initial way of doing it is better and simpler. One thing, you probably shouldn't override the dapperness variable like that. Currently there are 2 places where this variable is used: Maxwell's inherent sanity boost and WX-78's music module. This means when Maxwell picks up the red amulet, his inherent sanity boost of TUNING.DAPPERNESS_LARGE gets overwritten by TUNING.DAPPERNESS_MED, and when he drops it, overwritten to 0. You can fix this by adding or subtracting on what is already there, rather than just overwriting it. local function OnDropped(inst) inst.owner.components.sanity.dapperness = inst.owner.components.sanity.dapperness - TUNING.DAPPERNESS_MED end local function OnPickedUp(inst, picker) picker.components.sanity.dapperness = picker.components.sanity.dapperness + TUNING.DAPPERNESS_MED end Same applies for temperature.inherentinsulation as Wes has negative TUNING.INSULATION_TINY, meaning it too will get overwritten. Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665390 Share on other sites More sharing options...
ArcAngela Posted September 16, 2023 Author Share Posted September 16, 2023 (edited) 5 minutes ago, Hamurlik said: Oh, I see. Now that I look more closely at the code I realize your initial way of doing it is better and simpler. One thing, you probably shouldn't override the dapperness variable like that. Currently there are 2 places where this variable is used: Maxwell's inherent sanity boost and WX-78's music module. This means when Maxwell picks up the red amulet, his inherent sanity boost of TUNING.DAPPERNESS_LARGE gets overwritten by TUNING.DAPPERNESS_MED, and when he drops it, overwritten to 0. You can fix this by adding or subtracting on what is already there, rather than just overwriting it. local function OnDropped(inst) inst.owner.components.sanity.dapperness = inst.owner.components.sanity.dapperness - TUNING.DAPPERNESS_MED end local function OnPickedUp(inst, picker) picker.components.sanity.dapperness = picker.components.sanity.dapperness + TUNING.DAPPERNESS_MED end Same applies for temperature.inherentinsulation as Wes has negative TUNING.INSULATION_TINY, meaning it too will get overwritten. Would this work for basically everything? summer insulation, extra move speed, extra damage multipliers, etc? I can only see this not working when it involves components and tags... cause I'd have to add a component (example: efficientworker) and then I presume I need to also remove the component when the person drops the item, correct? Example: fastbuilder from Winona, how can I prevent a character who already has fastbuilder to not have their tag removed when they drop the medal if I want the medal to give fastbuilder tag? Edited September 16, 2023 by ArcAngela Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665393 Share on other sites More sharing options...
Hamurlik Posted September 16, 2023 Share Posted September 16, 2023 Quote Example: fastbuilder from Winona, how can I prevent a character who already has fastbuilder to not have their tag removed when they drop the medal if I want the medal to give fastbuilder tag? You could store whether the player had the tag before they picked the amulet up. local hadFastBuilder = false local function OnDropped(inst) if not hadFastBuilder then inst.owner:RemoveTag("fastbuilder") end end local function OnPickedUp(inst, picker) hadFastBuilder = inst.owner:HasTag("fastbuilder") if not hadFastBuilder then inst.owner:AddTag("fastbuilder") end end A component equivalence for this would be: local hadEfficientUser = false local function OnDropped(inst) if not hadEfficientUser then inst.owner:RemoveComponent("efficientuser") end end local function OnPickedUp(inst, picker) hadEfficientUser = inst.owner.components.efficientuser and true or false if not hadEfficientUser then inst.owner:AddComponent("efficientuser") end end Quote Would this work for basically everything? summer insulation, extra move speed, extra damage multipliers, etc? For stuff that uses a variable, yes. inherentinsulation in temperature or dapperness in sanity use a simple variable. They would work like that. A quirk about this, while dapperness in code is always added together to not overwrite, inherentinsulation is overwritten. See, the only 2 places where this variable is used on character prefabs is on Wes and Wolfgang's mightiness component. Wes inherently has negative insulation, so he gets cold easier (and he also has negative summer insulation, so it doesn't mean it's better in summer). And mightiness component gives some winter insulation when Wolfgang is in mighty form. But since Wes will never have the mightiness component, the devs don't mind overwriting it. Then again the WX-78 music module technically won't ever overwrite dapperness because only Maxwell has that variable ever used. ...But anyway, ignoring this inconsistency, you should use the safer option of adding together most of the time, as updates might change this in the future. Speed uses a different system. You can see how it works in detail at "scripts\components\locomotor.lua" But basically, you use functions and supply them with a key instead. inst.components.locomotor:SetExternalSpeedMultiplier(inst, "speedmultiplier_key", 5) First argument is the player. Second argument is a key; speed is calculated from multiple sources, this allows you to add another. Third argument is the value. When you don't need it anymore, you can remove it so: inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "speedmultiplier_key") Using this will make sure you won't overwrite anything. Damage modifiers also use a different system. To add a modifier: inst.components.combat.externaldamagemultipliers:SetModifier(inst, 1.5, "key") First argument is the player. Second argument is the value. Third argument is the key. One quirk about this, Wolfgang's mightiness component overwrites this whenever he changes form. Idk why. There is definitely a way to fix this but I won't look into it right now. 1 Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665397 Share on other sites More sharing options...
ArcAngela Posted September 16, 2023 Author Share Posted September 16, 2023 Thank you so much, this is very helpful! for clarity, "speedmultiplier_key" and "key" in this case can be anything, just to make sure it doesn't collide with existing code in the game, right? Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665398 Share on other sites More sharing options...
Hamurlik Posted September 16, 2023 Share Posted September 16, 2023 10 minutes ago, ArcAngela said: for clarity, "speedmultiplier_key" and "key" in this case can be anything, just to make sure it doesn't collide with existing code in the game, right? Yep, any string. Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665399 Share on other sites More sharing options...
ArcAngela Posted September 16, 2023 Author Share Posted September 16, 2023 While putting this code to practice I found a very silly behavior, you can keep your tags if you pick up more than 1 medal, meaning you always have the "hadTagBefore" But more importantly, any way I can make Medals not stack to prevent both the "hadTagBefore" issue and the exponential amount of buffs as shown by Wolfgang? Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665405 Share on other sites More sharing options...
ArcAngela Posted September 17, 2023 Author Share Posted September 17, 2023 2am update, with the help of my friend he managed to make the medals not stack buffs, but this broke tags completely, in the file below I add the tag expertchef to test this, but when dropping the item it never removes the tag despite removing the extra damage. medal_red.lua Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665435 Share on other sites More sharing options...
ArcAngela Posted September 19, 2023 Author Share Posted September 19, 2023 My friend has figured it out and fixed the code, it now works perfectly! a character who had Tags will keep their tags, a character who didn't will have them removed. The solution was kind of very much in our faces, first we check if they didn't have expertchef, which makes us add expertchef and a completely new tag, this is the tag that differentiates the player, so when they drop the item, we check for that made-up tag before removing both. This makes sure they always lose expertchef, and makes sure characters who already had expertchef don't. local function OnDropped(inst) local owner = inst.owner inst.owner = nil if owner.components.inventory:HasItemWithTag("medal_red", 1) then --Still have one, do nothing return end if owner:HasTag("medal_expertchef") then owner:RemoveTag("medal_expertchef") owner:RemoveTag("expertchef") end owner:RemoveTag("navyrecruit") --owner.components.sanity.dapperness = picker.components.sanity.dapperness - TUNING.DAPPERNESS_MED owner.components.temperature.inherentinsulation = owner.components.temperature.inherentinsulation - TUNING.INSULATION_MED owner.components.combat.externaldamagemultipliers:SetModifier("medal_red", 1) owner.components.health.absorb = owner.components.health.absorb - 0.5 end local function OnPickedUp(inst, picker) if picker == nil then --is this even possible? return end inst.owner = picker if inst.owner.components.inventory:HasItemWithTag("medal_red", 1) then --Already have one, do nothing return end if not inst.owner:HasTag("expertchef") then inst.owner:AddTag("medal_expertchef") inst.owner:AddTag("expertchef") end if picker.components.sanity then inst.owner:AddTag("navyrecruit") --so Whiskey doesn't lose sanity near them --picker.components.sanity.dapperness = picker.components.sanity.dapperness + TUNING.DAPPERNESS_MED picker.components.temperature.inherentinsulation = picker.components.temperature.inherentinsulation + TUNING.INSULATION_MED picker.components.combat.externaldamagemultipliers:SetModifier("medal_red", 1.25) picker.components.health.absorb = picker.components.health.absorb + 0.5 end end This isn't exactly a "fix-all" because I think mods have a cap of only being allowed to add 30 tags, so obviously 1 tag for every component or existing tag is gonna heavily limit someone's options, not mine tho! That was a field trip, now we know how to make inventory items that do special things without the need of being equipped/unequipped. Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665657 Share on other sites More sharing options...
Hamurlik Posted September 19, 2023 Share Posted September 19, 2023 Glad to hear that! I have a concern however, does it work when using it with backpacks? Try putting a medal into a backpack, and then dropping that backpack. Will OnDropped trigger, or will player still have the tag? You could just forbid putting the item in backpacks in the first place. local function fn() -- . . . inst.components.inventoryitem.canonlygoinpocket = true -- . . . end Link to comment https://forums.kleientertainment.com/forums/topic/150964-solved-how-to-make-an-item-give-sanity-by-just-being-on-your-inventory/#findComment-1665661 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