Jump to content

Character modding- need help


Recommended Posts

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

Screenshot (396).png

Link to comment
Share on other sites

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 by Ultroman
missing parenthesis
Link to comment
Share on other sites

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. 

Screenshot (404).png

Link to comment
Share on other sites

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

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

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

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

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 by sanok15
Link to comment
Share on other sites

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

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

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

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 by sanok15
Link to comment
Share on other sites

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

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

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...