Jump to content

Recommended Posts

Helloooooo Klei forums! 

 

I've been enjoying DST a lot and I came across a mod called Tungsten mod by Mr.Gentleman and outseeker and I'm intrigued by their regeneration on tools (by attacking).

 

Their mod codes are shown below:

local function onattack(weapon, attacker, target)    if target ~= nil then        weapon.components.finiteuses:Use(-1.5)    endendlocal function fn(Sim)	local inst = CreateEntity()	local trans = inst.entity:AddTransform()	local anim = inst.entity:AddAnimState()    MakeInventoryPhysics(inst)        anim:SetBank("axe")    anim:SetBuild("tungsten_axe")    anim:PlayAnimation("idle")    	inst.entity:AddNetwork()	    if not TheWorld.ismastersim then        return inst    end    MakeHauntableLaunchAndSmash(inst)	    inst:AddTag("sharp")    inst:AddComponent("weapon")    inst.components.weapon:SetDamage(TUNING.TUNGSTEN_AXE_DAMAGE)    inst.components.weapon:SetAttackCallback(onattack)    -------        inst:AddComponent("finiteuses")    inst.components.finiteuses:SetMaxUses(TUNING.TUNGSTEN_AXE_USES)    inst.components.finiteuses:SetUses(TUNING.TUNGSTEN_AXE_USES)        inst.components.finiteuses:SetOnFinished( onfinished )

 

I replicated this to my own tools instead of their tungsten tools, however, I noticed that the durability can go over 100%. Is there a way to prevent this? Help is much appreciated!!

Thank you!!

Edited by Gigadroid
Link to comment
https://forums.kleientertainment.com/forums/topic/53421-help-regenerative-tools/
Share on other sites

LOL Damn it. I thought it was inst.components.finiteuses or something with inst. Ugh, okay thanks again DarkXero! You've been sooooo helpful all this while! :grin:

 

Hmmm, to make this more versatile and more compatible (not that there are any compatibility issues now), how would it be possible to create a formula that adds 1% even with Tweak Those Tools mod which modifiy your weapon.components.finiteuses.total and weapon.components.finiteuses.current as seen below:

 

			function TweakToolDurability(inst)                                                                                                                                                                        				if inst.components.finiteuses then                                                              					inst.components.finiteuses.total = (inst.components.finiteuses.total * TOOL_DURABILITY)       					inst.components.finiteuses.current = (inst.components.finiteuses.current * TOOL_DURABILITY)   				end                                                                                                                                                                                                     				if inst.components.fueled then                                                                  					inst.components.fueled.maxfuel = (inst.components.fueled.maxfuel * TOOL_DURABILITY)           					inst.components.fueled.currentfuel = (inst.components.fueled.currentfuel * TOOL_DURABILITY)   					inst.components.fueled.bonusmult = (inst.components.fueled.bonusmult * TOOL_DURABILITY)       				end                                                                                             			end 			AddPrefabPostInit("multitool_axe_pickaxe", TweakToolDurability)                                    
                        

THANK YOU!!

Edited by Gigadroid

However, will I have to put the function TweakToolDurability in the same file? Or may I do this onepercent thing in another file?

 

If for example I put this onattack function into the modmain of TweakToolDurability (to make use of the weapon.components.finiteuses.total) , how would I link the function to the axe_pickaxe prefab in the main game folder? Only the PrefabFiles {} in the beginning will do?

 

Also, how would one code a feature of lifesteal based on damage instead of a fixed amount like BatBat?

Edited by Gigadroid

You showed me a weapon that had initially

local function onattack(weapon, attacker, target)    if target ~= nil then        weapon.components.finiteuses:Use(-1.5)    endendinst.components.weapon:SetAttackCallback(onattack)

and you asked to make it not recover beyond 100%.

 

Thus, we get

local function onattack(weapon, attacker, target)	if target ~= nil then		if (weapon.components.finiteuses.current + 1.5) <= weapon.components.finiteuses.total then			weapon.components.finiteuses:Use(-1.5)		end	endendinst.components.weapon:SetAttackCallback(onattack)

 

And now, you asked for the weapon to recover 1%, and not 1.5 uses (which is only 1% of 150) so we get

local function onattack(weapon, attacker, target)	if target ~= nil then		local onepercent = weapon.components.finiteuses.total / 100		if (weapon.components.finiteuses.current + onepercent) <= weapon.components.finiteuses.total then			weapon.components.finiteuses:Use(-onepercent)		end	endendinst.components.weapon:SetAttackCallback(onattack)

 

To apply this to the "multitool_axe_pickaxe" prefab via the TweakToolDurability(inst) function, it will look like this

local function onattack(weapon, attacker, target)	if target ~= nil then		local onepercent = weapon.components.finiteuses.total / 100		if (weapon.components.finiteuses.current + onepercent) <= weapon.components.finiteuses.total then			weapon.components.finiteuses:Use(-onepercent)		end	endendfunction TweakToolDurability(inst)    	inst.components.weapon:SetAttackCallback(onattack)                                                          																							 	if inst.components.finiteuses then                                                              		inst.components.finiteuses.total = (inst.components.finiteuses.total * TOOL_DURABILITY)       		inst.components.finiteuses.current = (inst.components.finiteuses.current * TOOL_DURABILITY)	end																								 	if inst.components.fueled then                                                                  		inst.components.fueled.maxfuel = (inst.components.fueled.maxfuel * TOOL_DURABILITY)           		inst.components.fueled.currentfuel = (inst.components.fueled.currentfuel * TOOL_DURABILITY)   		inst.components.fueled.bonusmult = (inst.components.fueled.bonusmult * TOOL_DURABILITY)       	end                                                                                            endAddPrefabPostInit("multitool_axe_pickaxe", TweakToolDurability)

 

And the batbat has

local function onattack(inst, owner, target)    if owner.components.health and owner.components.health:GetPercent() < 1 and not target:HasTag("wall") then        owner.components.health:DoDelta(TUNING.BATBAT_DRAIN,false,"batbat")        owner.components.sanity:DoDelta(-TUNING.BATBAT_DRAIN * 0.5)    endend

all you need to do is copy that into your onattack function and replace tuning.batbat_drain (a constant value) into weapon.components.weapon.damage to base it off the damage of the weapon. To base it off the damage dealt by the player (affected by multipliers), you will have to use the onhitotherfn of the combat component.

1. For the durability gain perk, is it possible to separate TweakToolDurability lua and onattack lua onto different files while onattack will still call the modified weapon.component.finiteuses.total? Because in this case, any tools that use TweakToolDurability will gain the perk. Long way to do it would be to have a TweakToolDurability and TweakToolDurability2 to separate the functions for different tools but I'm wondering if there's a better and smarter way to do this.

 

2. For lifesteal, I tried attacker.components.combat.onhitotherfn as the value but that sounded silly of me. HAHAHAA

How would I code to get the value of the final damage dealt?

 

THANK YOU DarkXero

Edited by Gigadroid

Well yes, you can have

local function GiveOnePercentOnAttack(weapon, attacker, target)    if target then        local onepercent = weapon.components.finiteuses.total / 100        if (weapon.components.finiteuses.current + onepercent) <= weapon.components.finiteuses.total then            weapon.components.finiteuses:Use(-onepercent)        end    endendlocal function GiveUsesOnAttack(inst)	if inst.components.weapon and inst.components.finiteuses then		local old = inst.components.weapon.onattack		inst.components.weapon.onattack = function(weapon, attacker, target)			GiveOnePercentOnAttack(weapon, attacker, target)			if old then				old(weapon, attacker, target)			end		end	endendAddPrefabPostInit("prefabname", GiveUsesOnAttack)

to keep it separate in the modmain.

 

Do you want lifesteal based on the weapon the player holds, on the damage the player deals, the damage the weapon can cause, or all of the above?

In that case you want to put inside your character's prefab:

inst.components.combat.onhitotherfn = function(attacker, victim, damage, stimuli)	attacker.components.health:DoDelta(0.15 * damage)end

so that all weapons, and the different damages, count towards healing.

Hmm......is there a way to only affect one weapon? If final damage dealt is not possible, then what other forms of damage is possible? Pure weapon damage?

 

So if I put the code above into Mod1/modmain.lua, it will use weapon.components.finiteuses.total from Mod2/modmain.lua?

 

Also, I wish to understand why is GiveUsesOnAttack needed at all. Why not just input inst.components.weapon.onattack anywhere in GiveOnePercent? How does it work actually?

local function GiveUsesOnAttack(inst)    if inst.components.weapon and inst.components.finiteuses then        local old = inst.components.weapon.onattack        inst.components.weapon.onattack = function(weapon, attacker, target)            GiveOnePercentOnAttack(weapon, attacker, target)            if old then                old(weapon, attacker, target)            end        end    endend

More specifically, could you explain the part of:

        local old = inst.components.weapon.onattack        inst.components.weapon.onattack = function(weapon, attacker, target)            GiveOnePercentOnAttack(weapon, attacker, target)            if old then                old(weapon, attacker, target) 

1. Why do you need to local old? 

2. How does setting up inst.components.weapon.onattack = function(weapon, attacker, targer) work?

3. if old then 
        old(weapon, attacker, target)       
is the same as
if inst.components.weapon.onattack = GiveOnePercentOnAttack(weapon, attacker, target) then
         GiveOnePercentOnAttack(weapon, attacker, target)?

Edited by Gigadroid

You either can get the weapon or the damage from the events/functions that can be used. Unless you decide to write a bit more.

Like:

AddComponentPostInit("combat", function(self)	local old = self.CalcDamage	function self:CalcDamage(targ, weapon, mult)		local damage = old(self, targ, weapon, mult)		if weapon and weapon.prefab == "myweapon" then			self.inst.components.health:DoDelta(0.15 * damage)		end		return damage	endend)

Now to the questions.

 

GiveUsesOnAttack is not really needed. But then again, no extra functions are really needed. I can write

AddPrefabPostInit("prefabname", function(inst)    if inst.components.weapon and inst.components.finiteuses then        local old = inst.components.weapon.onattack        inst.components.weapon.onattack = function(weapon, attacker, target)			if target then				local onepercent = weapon.components.finiteuses.total / 100				if (weapon.components.finiteuses.current + onepercent) <= weapon.components.finiteuses.total then					weapon.components.finiteuses:Use(-onepercent)				end			end            if old then                old(weapon, attacker, target)            end        end    endend)

and it's the same. I wrote the functions like that to structure the code.

 

The local old is creating a variable that stores an onattack function, if one exists, else it stores nil. Imagine you try to apply your onattack to a weapon that already has one: you will overwrite it. So what you want to do is to save the old function, then write yours containing that, and execute it along with your code.

 

Setting up that, works like that. You have inst, you access its components via inst.components, you pick the component you want via inst.components.weapon. What you get by this is a class, the class that gets returned in weapon.lua. That class contains the parameter onattack, that is either nil, or a function that gets executed when something is attacked. SetAttackCallback is a function that assigns the function you pass to the onattack parameter.

 

No, they are not the same.

Interesting. Thank you very much DarkXero for teaching me these things. I attempted to apply it below and got hunger drain working! 

Code:

local function hungerdrain(inst, owner, target)	local halfpercenthunger = owner.components.hunger.max*0.01*0.5    if owner.components.hunger and owner.components.hunger:GetPercent() < 1 and not target:HasTag("wall") then        owner.components.hunger:DoDelta(halfpercenthunger)    endendlocal function hungeronattack(inst)	if inst.components.weapon and inst.components.finiteuses then		local attack = inst.components.weapon.onattack		inst.components.weapon.onattack = function(inst, owner, target)			hungerdrain(inst, owner, target)			if attack then				attack(inst, owner, target)			end		end	endendAddPrefabPostInit("tentaclespike", hungeronattack)

Do let me know if anything can be improved.

 

Also, I noticed that the multitool doesn't restore 1% on EVERY hit. On every 4th or 5th hit, it doesn't restore 1%. Could the 1% be a decimal value that is causing this? Or is it still not implemented properly? 

 

Am I supposed to insert this:

-- Added Tools Durability Regenerationlocal function GiveOnePercentOnAttack(weapon, attacker, target)    if target then        local onepercent = weapon.components.finiteuses.total / 100        if (weapon.components.finiteuses.current + onepercent) <= weapon.components.finiteuses.total then            weapon.components.finiteuses:Use(-onepercent)        end    endend local function GiveUsesOnAttack(inst)    if inst.components.weapon and inst.components.finiteuses then        local old = inst.components.weapon.onattack        inst.components.weapon.onattack = function(weapon, attacker, target)            GiveOnePercentOnAttack(weapon, attacker, target)            if old then                old(weapon, attacker, target)            end        end    endend--Enter list of tools belowAddPrefabPostInit("multitool_axe_pickaxe", GiveUsesOnAttack) 

into this:

	-- Tools	--------	if TOOL_DURABILITY ~= "Default" then		if TOOL_DURABILITY == "Infinite" then  			-- Remove the durability for all tools.			function RemoveToolDurability(inst)    				-- Set the 'finiteuses.Use' function to a blank function.				if inst.components.finiteuses then					inst.components.finiteuses.Use = function () end 				end						-- Set the 'fueled.StartConsuming' function to a blank function.				if inst.components.fueled then					inst.components.fueled.StartConsuming = function () end				end			end      			-- Load all tool prefabs, and call the 'RemoveToolDurability' function for each.			AddPrefabPostInit("axe", RemoveToolDurability)			AddPrefabPostInit("goldenaxe", RemoveToolDurability)			AddPrefabPostInit("hammer", RemoveToolDurability)			AddPrefabPostInit("shovel", RemoveToolDurability)			AddPrefabPostInit("goldenshovel", RemoveToolDurability)			AddPrefabPostInit("pitchfork", RemoveToolDurability)			AddPrefabPostInit("pickaxe", RemoveToolDurability)			AddPrefabPostInit("goldenpickaxe", RemoveToolDurability)			AddPrefabPostInit("multitool_axe_pickaxe", RemoveToolDurability)			AddPrefabPostInit("bugnet", RemoveToolDurability)			AddPrefabPostInit("fishingrod", RemoveToolDurability)			AddPrefabPostInit("umbrella", RemoveToolDurability)			AddPrefabPostInit("panflute", RemoveToolDurability)			AddPrefabPostInit("horn", RemoveToolDurability)			AddPrefabPostInit("sewing_kit", RemoveToolDurability) -- Add option to tweak separately?        			AddPrefabPostInit("heatrock", RemoveToolDurability) -- Add option to tweak separately?              		else                                                                                                			-- Tweak the durability of all tools.                                                             			function TweakToolDurability(inst)                                                                                                                                                                        				if inst.components.finiteuses then                                                              					inst.components.finiteuses.total = (inst.components.finiteuses.total * TOOL_DURABILITY)       					inst.components.finiteuses.current = (inst.components.finiteuses.current * TOOL_DURABILITY)   				end                                                                                                                                                                                                     				if inst.components.fueled then                                                                  					inst.components.fueled.maxfuel = (inst.components.fueled.maxfuel * TOOL_DURABILITY)           					inst.components.fueled.currentfuel = (inst.components.fueled.currentfuel * TOOL_DURABILITY)   					inst.components.fueled.bonusmult = (inst.components.fueled.bonusmult * TOOL_DURABILITY)       				end                                                                                             			end                                                                                                                                                                                                       			-- Load all tool prefabs, and call the 'TweakToolDurability' function for each.                   			AddPrefabPostInit("axe", TweakToolDurability)                                                     			AddPrefabPostInit("goldenaxe", TweakToolDurability)                                               			AddPrefabPostInit("hammer", TweakToolDurability)                                                  			AddPrefabPostInit("shovel", TweakToolDurability)                                                  			AddPrefabPostInit("goldenshovel", TweakToolDurability)                                            			AddPrefabPostInit("pitchfork", TweakToolDurability)                                               			AddPrefabPostInit("pickaxe", TweakToolDurability)                                              			AddPrefabPostInit("goldenpickaxe", TweakToolDurability)                                           			AddPrefabPostInit("multitool_axe_pickaxe", TweakToolDurability)                                   			AddPrefabPostInit("bugnet", TweakToolDurability)                                                  			AddPrefabPostInit("fishingrod", TweakToolDurability)                                              			AddPrefabPostInit("umbrella", TweakToolDurability)                                                			AddPrefabPostInit("panflute", TweakToolDurability)                                                			AddPrefabPostInit("horn", TweakToolDurability)                                                    			AddPrefabPostInit("sewing_kit", TweakToolDurability) -- Add option to tweak separately?                                               			AddPrefabPostInit("heatrock", TweakToolDurability) -- Add option to tweak separately?                                                                           		end	end      

 

or does it not matter even if I put them at the very end of the whole modmain.lua?

I believe I tried changing 
local function GiveOnePercentOnAttack(weapon, attacker, target)
to
local function GiveOnePercentOnAttack(inst, attacker, target) (not only this line but also the others accordingly)

 

so that it is the same thing from TweakThoseTools but it still doesn't restore 1% every hit.

Edited by Gigadroid

It's because the weapon component consumes 1 use on use.

So we are actually consuming Use(-onepercent + 1).

local function GiveUsesOnAttack(inst)    if inst.components.weapon and inst.components.finiteuses then		inst.components.weapon.attackwear = 0        local old = inst.components.weapon.onattack        inst.components.weapon.onattack = function(weapon, attacker, target)            GiveOnePercentOnAttack(weapon, attacker, target)            if old then                old(weapon, attacker, target)            end        end    endend

Editing attackwear to 0 solves this.

 

Also, in this case, it only matters if you put the AddPrefabPostInit("multitool_axe_pickaxe", GiveUsesOnAttack) inside the IF that "removes durability", because then, if you load the config that allows extra durability, it won't run and you won't gain anything. So you have to put it either inside the ELSE, or anywhere in the modmain (except the IF).

Oh yup! I knew that! Yay! 

Oh I was wondering how would it be possible to make spiderhats repairable from sewing kits. I found out that they have their own fueltype of FUELTYPE.SPIDERHAT and I wish to change it to FUELTYPE.USAGE so that sewing kits can repair them. Is that the right way?

However, a problem I face is that I can't find spiderhat.lua and only found hats.lua. How would I make this modification using a new modmain.lua?

 

Also after you showed me attackwear above, isn't it much simpler to just use that instead of inst.components.finiteuses:Use()? By using attackwear, you can know the final increase in durability (maybe some tools have different attackwear so your Use(onepercent) could be way off). 

Edited by Gigadroid

All hats are in hats.lua. In hats.lua there are many prefab functions ran when the game loads the prefab file.

The spider hat is the result of MakeHat, with the parameters that make it use the spider related functions.

 

AddPrefabPostInit doesn't change a lua file.

It appends a function to a table of functions that get ran when a prefab is initialized in the game.

 

The spider hat prefab is spiderhat. So, in a modmain you would put

AddPrefabPostInit("spiderhat", function(inst)	inst.components.fueled.fueltype = GLOBAL.FUELTYPE.USAGEend)

By editing Use(), you make it so using the tool as a tool, and the tool as a weapon don't consume durability.

You don't want that, you just want to nullify the effects of Use() when attackwear is being passed.

Ahh I see. Why is there a need for "GLOBAL." and when is it needed?

 

"By editing Use(), you make it so using the tool as a tool, and the tool as a weapon don't consume durability.

You don't want that, you just want to nullify the effects of Use() when attackwear is being passed."

 

What I understood from that is:

Use() is whenever the tool is well.....used, whether attacking or chopping or mining. 

I don't want to replace Use() with attackwear because Use() will still decrease the durability? So I need both either way?

 

 

Edited by Gigadroid

Some constants, functions, values are variables with global scope: you can call them from anywhere. However, in the modmain you have a restricted environment. In order to reference them, you need to ask the GLOBAL table you get for the global scope variable you are looking for.

 

FUELTYPE is a constant in constants.lua.

 

attackwear doesn't replace Use().

This is the function called when you attack with an equipped prefab that has the weapon component:

function Weapon:OnAttack(attacker, target, projectile)    if self.onattack then        self.onattack(self.inst, attacker, target)    end        if self.inst.components.finiteuses then	    self.inst.components.finiteuses:Use(self.attackwear or 1)    endend

The onattack parameter function of the class gets called.

And if the weapon has the finiteuses component, it uses attackwear uses, or 1 use, if there is no attackwear.

If attackwear is 0, then you use 0 uses.

 

Use() is used whenever Use() is used, not just when performing an action (chopping, mining, etc.).

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
×
  • Create New...