sanok15 Posted September 3, 2019 Share Posted September 3, 2019 Hello, I started yesterday with modding dst (my first time). I really don't have any idea what I am doing, so maybe you guys could help me . So I want to make a new character with sanity recovery like maxwell, just a little bit weaker. Maybe +2/min. The character should also have the ability to trade sanity into health, so if the character got damage, sanity will decrease every second by 1 and health will increase by 1 until health equals maxhealth. Furthermore the character should be unable to wear armor. I tried yesterday multiple hours to implement this, but in most cases just nohting happens ingame. I did the sanity revovery like shown the picture and it works (don't know why but it works somehow XD). I tried to find an documentation about the mod API, because I don't know any commands, but I dont find any... Maybe you can help me (If you write some code, please use comments or explain it, I want to understand how it works and learn from it.) Thank you, Sanok15 Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 (edited) UPDATE: I've edited the code in this poat to be correct, after we went through a bit of debugging to figure out that I was an idiot. Instead of an image, posting the whole file as an attachment or using the code-text block is preferable, so we can copy/paste your code and try it out. Anyway, using custom_rate_fn for the first feature (constant sanity increase per second) is a good idea. I'm guessing that part works. For the part about trading sanity for health, I'd go with a task-based approach. Put this in your character's master_postinit. inst:DoPeriodicTask(1.0, function(inst) if inst.components.health.currenthealth <= inst.components.health:GetMaxWithPenalty() - 1 and inst.components.sanity.current > 1 then inst.components.health:DoDelta(1, true) inst.components.sanity:DoDelta(-1, true) end end) For not being able to wear armor at all, you can do this. Note that this particular way is very simplistic and makes your character unable to wear ANYTHING in their BODY equipslot. local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY then return end oldEquip(self, item, old_to_active) end You can insert your own checks instead of the simple BODY check. I have some code that can e.g. search a custom list of prefabs you don't want to be able to equip, if you want to be able to wear e.g. a raincoat but just not the armors giving defense bonuses. Edited September 3, 2019 by Ultroman missing parenthesis Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 22 minutes ago, Ultroman said: Instead of an image, posting the whole file as an attachment or using the code-text block is preferable, so we can copy/paste your code and try it out. Anyway, using custom_rate_fn for the first feature (constant sanity increase per second) is a good idea. I'm guessing that part works. For the part about trading sanity for health, I'd go with a task-based approach. Put this in your character's master_postinit. inst:DoTaskInTime(1.0, function(inst) if inst.components.health.currenthealth <= inst.components.health:GetMaxHealthWithPenalty() - 1 and inst.components.sanity.current > 1 then inst.components.health:DoDelta(1, true) inst.components.sanity:DoDelta(-1, true) end end For not being able to wear armor at all, you can do this. Note that this particular way is very simplistic and makes your character unable to wear ANYTHING in their BODY equipslot. local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY then return end oldEquip(self, item, old_to_active) end You can insert your own checks instead of the simple BODY check. I have some code that can e.g. search a custom list of prefabs you don't want to be able to equip, if you want to be able to wear e.g. a raincoat but just not the armors giving defense bonuses. Thank you When I was trying the "sanity health trade" part, I got an error (see picture, your code starts in line 72). Thought I have to put a second ")" in the first line, but it didn't work. Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 Fixed in my first post. Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 4 hours ago, Ultroman said: Fixed in my first post. There is still a problem. The game crashes while entering the world. Maybe because there is no value for healthWithPenalty at the beginning? Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 Oops, it's GetMaxWithPenalty() Fixed in the code in my first post. Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 6 minutes ago, Ultroman said: Oops, it's GetMaxWithPenalty() Fixed in the code in my first post. Ok nice thanks, the part with the armor works for me. If I try to craft one, it disappears. So for the part with the sanity-health trade: the error is gone, but nothing happens if i loose health. Thank you for your help so far Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 Oooh...it's not good that it disappears when you craft an armor...it should just throw it on the ground or in your inventory...maybe we need to hook in somewhere else. 3 minutes ago, sanok15 said: So for the part with the sanity-health trade: the error is gone, but nothing happens if i loose health. Are you sure? The "true" part of the DoDelta makes it do it silently, instead of making the sound and pulse every time. You can try putting "false" instead to make it more obvious. I just find it annoying. Are you sure you put the code in the right place? Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 3 minutes ago, Ultroman said: Oooh...it's not good that it disappears when you craft an armor...it should just throw it on the ground or in your inventory...maybe we need to hook in somewhere else. Are you sure? The "true" part of the DoDelta makes it do it silently, instead of making the sound and pulse every time. You can try putting "false" instead to make it more obvious. I just find it annoying. Are you sure you put the code in the right place? I put it in master_postinit. I tried it again with "false", but nothing happend. There also was no sound. Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 Debugging time! Put this in instead, go play and get damage (just type c_sethealth(0.5) in the console) and see what it writes in your log. inst:DoTaskInTime(1.0, function(inst) print("------------------------------------------------------") if inst.components.health.currenthealth <= inst.components.health:GetMaxWithPenalty() - 1 and inst.components.sanity.current > 1 then print("Trading sanity for health!") inst.components.health:DoDelta(1, true) inst.components.sanity:DoDelta(-1, true) else print("CANNOT trade sanity for health!") print("Current health: "..inst.components.health.currenthealth) print("Max health with penalty - 1: "..(inst.components.health:GetMaxWithPenalty() - 1)) print("Current sanity: "..inst.components.sanity.current) end end Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 (edited) 36 minutes ago, Ultroman said: Debugging time! Put this in instead, go play and get damage (just type c_sethealth(0.5) in the console) and see what it writes in your log. inst:DoTaskInTime(1.0, function(inst) print("------------------------------------------------------") if inst.components.health.currenthealth <= inst.components.health:GetMaxWithPenalty() - 1 and inst.components.sanity.current > 1 then print("Trading sanity for health!") inst.components.health:DoDelta(1, true) inst.components.sanity:DoDelta(-1, true) else print("CANNOT trade sanity for health!") print("Current health: "..inst.components.health.currenthealth) print("Max health with penalty - 1: "..(inst.components.health:GetMaxWithPenalty() - 1)) print("Current sanity: "..inst.components.sanity.current) end end where can I find my logs? I tried the armor crafting again. If I craft it, it will disappear in that moment, together with the materials. If I give me the armor as start item, I just can't use it. *found the logs* [00:00:49]: CANNOT trade sanity for health! [00:00:49]: Current health: 150 [00:00:49]: Max health with penalty - 1: 149 [00:00:49]: Current sanity: 175 36 minutes ago, Ultroman said: Debugging time! Put this in instead, go play and get damage (just type c_sethealth(0.5) in the console) and see what it writes in your log. inst:DoTaskInTime(1.0, function(inst) print("------------------------------------------------------") if inst.components.health.currenthealth <= inst.components.health:GetMaxWithPenalty() - 1 and inst.components.sanity.current > 1 then print("Trading sanity for health!") inst.components.health:DoDelta(1, true) inst.components.sanity:DoDelta(-1, true) else print("CANNOT trade sanity for health!") print("Current health: "..inst.components.health.currenthealth) print("Max health with penalty - 1: "..(inst.components.health:GetMaxWithPenalty() - 1)) print("Current sanity: "..inst.components.sanity.current) end end [NEWS] Ok, I tried it multiple times and if i create a new world and get damage, nothing will happen and in console will stand "CANNOT trade sanity for health!". If I load a existing world,where i dont have full life, I will heal 1 health after entering the world. Furthermore nothing happens. In this case I can find "Trading sanity for health" in the logs Edited September 3, 2019 by sanok15 Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 LoL!!! I messed up. I'm SO sorry! It's DoPeriodicTask, not DoTaskInTime. Fixed in the first post again. Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 6 minutes ago, Ultroman said: LoL!!! I messed up. I'm SO sorry! It's DoPeriodicTask, not DoTaskInTime. Fixed in the first post again. It works perfect now! XD Thank you What exactly is the different between DoPeriodicTask and DoTaskInTime? Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 DoTaskInTime calls a function after a given amount of time, while DoPeriodicTask calls a function instantly and then keeps calling it at a given interval. Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 6 minutes ago, Ultroman said: DoTaskInTime calls a function after a given amount of time, while DoPeriodicTask calls a function instantly and then keeps calling it at a given interval. Ok, thank you How do you know all the commands? I would also like to add other abilitys to the character but I can not find any instructions or explanations. How can I add custom Items, how can I get hot/cold resistance etc. Any tipps for me? Link to comment Share on other sites More sharing options...
Ultroman Posted September 3, 2019 Share Posted September 3, 2019 Read the newcomer post. It has "entry points" for a lot of things. Notably how to search the forums efficiently. We've done a LOT of things on here already, also custom items, custom items which only your character can craft, hot/cold resistance, auras etc. Link to comment Share on other sites More sharing options...
sanok15 Posted September 3, 2019 Author Share Posted September 3, 2019 9 minutes ago, Ultroman said: Read the newcomer post. It has "entry points" for a lot of things. Notably how to search the forums efficiently. We've done a LOT of things on here already, also custom items, custom items which only your character can craft, hot/cold resistance, auras etc. Perfect! I'll give it a try Link to comment Share on other sites More sharing options...
sanok15 Posted September 4, 2019 Author Share Posted September 4, 2019 (edited) 11 hours ago, Ultroman said: UPDATE: I've edited the code in this poat to be correct, after we went through a bit of debugging to figure out that I was an idiot. Instead of an image, posting the whole file as an attachment or using the code-text block is preferable, so we can copy/paste your code and try it out. Anyway, using custom_rate_fn for the first feature (constant sanity increase per second) is a good idea. I'm guessing that part works. For the part about trading sanity for health, I'd go with a task-based approach. Put this in your character's master_postinit. inst:DoPeriodicTask(1.0, function(inst) if inst.components.health.currenthealth <= inst.components.health:GetMaxWithPenalty() - 1 and inst.components.sanity.current > 1 then inst.components.health:DoDelta(1, true) inst.components.sanity:DoDelta(-1, true) end end) For not being able to wear armor at all, you can do this. Note that this particular way is very simplistic and makes your character unable to wear ANYTHING in their BODY equipslot. local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY then return end oldEquip(self, item, old_to_active) end You can insert your own checks instead of the simple BODY check. I have some code that can e.g. search a custom list of prefabs you don't want to be able to equip, if you want to be able to wear e.g. a raincoat but just not the armors giving defense bonuses. --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- I modified your version of the "no armor" code. With this code I'm unable to use any amor, but can equip any other items. Thanks for the inspiration @Ultroman local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armorwood" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armor_sanity" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armormarble" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armorsnurtleshell" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armorruins" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armordragonfly" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armorskeleton" then return --Item verschwindet einfach else if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.prefab == "armor_bramble" then return --Item verschwindet einfach end end end end end end end end oldEquip(self, item, old_to_active) end (If you try to craft any armor, the materials and the armor itself will disappear (I dont know why), armor lying on the ground can't picked up, armor in the inventory can't be equiped. Items like backpacks and for example raincoats can be used.) Edited September 4, 2019 by sanok15 Link to comment Share on other sites More sharing options...
Ultroman Posted September 4, 2019 Share Posted September 4, 2019 Yeah, but that's terrible nesting and A LOT of duplicate checks for the same thing. You should instead create a list of the prefabs you want it to block you from using, and check whether that list contains your prefab. -- A nice little function for checking whether an object is in a list. -- First parameter is your list, and the second parameter is the thing you're checking for. -- It returns true as soon as it finds the thing, or false if it doesn't find the thing. function contains(list, x) for _, v in pairs(list) do if v == x then return true end end return false end local unequippable_list = { "armorwood", "armor_sanity", "armormarble", "armorsnurtleshell", "armorruins", "armordragonfly", "armorskeleton", "armor_bramble", } local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and contains(unequippable_list, item.prefab) then return end oldEquip(self, item, old_to_active) end Alternatively, to also make your character unable to use ANY body armor, even custom ones from mods, you could simply refuse your character to wear any armor with the armor component on it. Like this: local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.components.armor then return end oldEquip(self, item, old_to_active) end Link to comment Share on other sites More sharing options...
sanok15 Posted September 5, 2019 Author Share Posted September 5, 2019 On 4.9.2019 at 5:52 PM, Ultroman said: Yeah, but that's terrible nesting and A LOT of duplicate checks for the same thing. You should instead create a list of the prefabs you want it to block you from using, and check whether that list contains your prefab. -- A nice little function for checking whether an object is in a list. -- First parameter is your list, and the second parameter is the thing you're checking for. -- It returns true as soon as it finds the thing, or false if it doesn't find the thing. function contains(list, x) for _, v in pairs(list) do if v == x then return true end end return false end local unequippable_list = { "armorwood", "armor_sanity", "armormarble", "armorsnurtleshell", "armorruins", "armordragonfly", "armorskeleton", "armor_bramble", } local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and contains(unequippable_list, item.prefab) then return end oldEquip(self, item, old_to_active) end Alternatively, to also make your character unable to use ANY body armor, even custom ones from mods, you could simply refuse your character to wear any armor with the armor component on it. Like this: local oldEquip = inst.components.inventory.Equip inst.components.inventory.Equip = function(self, item, old_to_active) if item ~= nil and item.components.equippable ~= nil and item.components.equippable.equipslot == EQUIPSLOTS.BODY and item.components.armor then return end oldEquip(self, item, old_to_active) end Thanks Link to comment 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