Jump to content

[Solved] How to multiply damage the target takes?


Recommended Posts

Hello, I have a problem & I'd love some help from someone :)!

Here's the code!

Spoiler

inst:ListenForEvent("onattackother", function(inst, data)
local crit = math.random(1,1)
--local damage = data.target.damage * (1-inst.components.health.absorb)

	if crit == 1 then
		ShakeAllCameras(CAMERASHAKE.VERTICAL,.5, .05, .5, inst, .01)
		
		if data.target.components.health and not data.target.components.health:IsDead() then
			--data.target.components.combat:GetAttacked(inst, damage*2, nil)
			--data.target.components.health:DoDelta(-damage * 2)
		end
		 
		if not data.target:HasTag("veggie")
		and not data.target:HasTag("hive")
		and not data.target:HasTag("wall")
		and not data.target:HasTag("soundproof")
		and data.target.components.health and not data.target.components.health:IsDead()
		and not data.target.prefab == "dummytarget"
		and not data.target.sg:HasStateTag("hiding") then
			data.target.sg:GoToState("hit")
		end
	end
end)

 

What I'm trying to do is make my char have a critical hit attack were he deals double damage, I tried to do it but I keep getting crashes like "value damage nil" which I don't understand, so any help would be really great :D, have a good day/night!

Edited by SuperDavid
Link to comment
Share on other sites

I have no idea what to do, but here it is.

Spoiler

crash.jpeg

and the code that starts the crash

Spoiler

inst:ListenForEvent("onattackother", function(inst, data)
local crit = math.random(1,1)
local damage = data.target.damage * (1-data.target.components.health.absorb) -- Crash starts from this line.

	if crit == 1 then
		ShakeAllCameras(CAMERASHAKE.VERTICAL,.5, .05, .5, inst, .01)
		
		if data.target.components.health and not data.target.components.health:IsDead() then
			--data.target.components.combat:GetAttacked(inst, damage*2, nil)
			data.target.components.health:DoDelta(-damage * 2)
		end
		
	end
end)

 

& thanks for replying :)!

Edited by SuperDavid
Link to comment
Share on other sites

1 hour ago, Lumina said:

Why is the damage data.target.damage ? Maybe i'm wrong but shouldn't this be the attacker damage ? Sorry if i don't understand the code well.

Oh., I didn't see that xd..do you maybe know how I make it based off the attackers damage :)?

 

EDIT: If anyone knows how I can get the damage value being inflicted on the target that would really help me, since I'm going through combat.lua & have no idea what to use from there :wilson_facepalm:..

 

Edited by SuperDavid
Link to comment
Share on other sites

If I am not mistaken the onattackother event uses the data of {target, weapon, projectile, stimuli}

  • Target is what is being attacked
  • Weapon is the thing smacking it
  • Projectile is if its a projectile hitting it
  • Stimuli is an element e.g. "electric"

weapon is also a component, maybe try data.weapon.components.weapon.damage

I'll do some testing when I have some time

Cheers

Link to comment
Share on other sites

i think you can take damage from data.weapon. Hope this is what you mean. :)

Spoiler

inst:ListenForEvent("onattackother", function(inst, data)
	local crit = math.random(1,1)
	local damage = data.weapon ~= nil and data.weapon.components.weapon.damage or inst.components.combat.defaultdamage
	damage = damage * (1-data.target.components.health.absorb)
	--Do some stuffs
end)

 

Link to comment
Share on other sites

46 minutes ago, Dear_J said:

i think you can take damage from data.weapon. Hope this is what you mean. :)

The problem is I think "data.weapon.components.damage" doesn't take into account the character's attack multiplier & only would double the weapon's attack value, I need something to multiply all the damage the target took by 2 :(.. but thanks for helping man :D

Link to comment
Share on other sites

hmm, in that case, i read the combat component, there is a function called CalcDamage(target, weapon, multiplier) that will calculate damage resulted by an attacker to target.

Spoiler

inst:ListenForEvent("onattackother", function(inst, data)
	local crit = math.random(1,1)
    local damage = inst.components.combat:CalcDamage(data.target, data.weapon)
	damage = damage * (1-data.target.components.health.absorb)
	--Do some stuffs
end)

 

for further more, you can read the function detail on data/scripts/components/combat.lua. :D

Link to comment
Share on other sites

I have this code snippet running in the modmain.lua or import it using modimport()

Spoiler

AddComponentPostInit("combat", function(Combat)-- place in modmain
	local OldCalcDamage = Combat.CalcDamage
	Combat.CalcDamage = function(self, target, weapon, ...)
		local old_damage = nil
		local crit = 0.5 --crit chance (e.g. this is 50%)
		local critdmg = 2 --crit damage (x2)
		if math.random() <= crit and target and self.inst.prefab == "wilson" then --change to your prefab
			if weapon then -- if its a weapon
				old_damage = weapon.components.weapon.damage
				weapon.components.weapon.damage = old_damage * critdmg
			else -- if we attack with something not using the weapon component
				old_damage = self.defaultdamage
				self.defaultdamage = old_damage * critdmg
			end
			-- visual effects and other stuff you can add
			local fx = SpawnPrefab("explode_small")
			local x, y, z = target.Transform:GetWorldPosition()
			fx.Transform:SetPosition(x, y, z)
		end
		local ret = OldCalcDamage(self, target, weapon, ...)-- returning crit damage
		if old_damage then-- reseting back to non crit damage
			if weapon then
				weapon.components.weapon.damage = old_damage
			else
				self.defaultdamage = old_damage
			end
		end
		return ret
	end
end)

It's been commented

The problem is listenforevent happens after damage is already dealt, its too late to modify damage because its in the past.

To solve this we need to modify the combat component when you initiate the attack, before damage is calculated and overide the damage we would of done.

To prevent it from rapidly escalating we need to revert back to our previous damage.

This has been tested by me and works completely fine on my end, on caves enabled servers.

Cheers

Link to comment
Share on other sites

Your code's very great @IronHunter, thank you :D!! If I could just ask some questions from you then that'd really be great :)!

So, if I wanted to make my character not be able to do a critical hit when not holding a equippable, would I just get rid of the " * critdmg " at " self.defaultdamage = old_damage * critdmg "?

Spoiler

if weapon then -- if its a weapon
	old_damage = weapon.components.weapon.damage
	weapon.components.weapon.damage = old_damage * critdmg
else -- if we attack with something not using the weapon component
	old_damage = self.defaultdamage
	self.defaultdamage = old_damage * critdmg -- over here
end

 

 

My second thing question is if I want to edit the "crit" chance value how would I do that, can I just put it again to override it or do a hundred "elseif" to check for various things? Since I want my character's critical hit chance go up & down between different hunger values & different modes. Would doing something like this for example work or is there a better way?

Spoiler

AddComponentPostInit("combat", function(Combat)-- place in modmain
	local OldCalcDamage = Combat.CalcDamage
	Combat.CalcDamage = function(self, target, weapon, ...)
		local old_damage = nil
		
		if self.inst.crit_1 == true then
		local crit = 0.1
		elseif self.inst.crit_2 == true then
		local crit = 0.2
		elseif self.inst.crit_3 == true then
		local crit = 0.3
		elseif self.inst.crit_4 == true then
		local crit = 0.4
		elseif self.inst.crit_5 == true then
		local crit = 0.5
		elseif self.inst.crit_6 == true then
		local crit = 0.6
		elseif self.inst.crit_7 == true then
		local crit = 0.7
		elseif self.inst.crit_8 == true then
		local crit = 0.8
		elseif self.inst.crit_9 == true then
		local crit = 0.9
		elseif self.inst.crit_10 == true then
		local crit = 1
		end
		
		local critdmg = 2
		
		if math.random() <= crit and target and self.inst.prefab == "wilson" then --change to your prefab
			if weapon then -- if its a weapon
				old_damage = weapon.components.weapon.damage
				weapon.components.weapon.damage = old_damage * critdmg
			else -- if we attack with something not using the weapon component
				old_damage = self.defaultdamage
				self.defaultdamage = old_damage * critdmg
			end
			-- visual effects and other stuff you can add
			local fx = SpawnPrefab("explode_small")
			local x, y, z = target.Transform:GetWorldPosition()
			fx.Transform:SetPosition(x, y, z)
		end
		local ret = OldCalcDamage(self, target, weapon, ...)-- returning crit damage
		if old_damage then-- reseting back to non crit damage
			if weapon then
				weapon.components.weapon.damage = old_damage
			else
				self.defaultdamage = old_damage
			end
		end
		return ret
	end
end)

 

 Thanks for your help man, I really appreciate it :D!!

Edited by SuperDavid
Link to comment
Share on other sites

Ya just remove the default damage, stuff.

You could probably do something like check the self.inst.components.hunger:GetPercent() and do some of your characters code in there or you could just make one variable in your character's prefab like inst.crit chance in your characters postinit.

Then you could just check

local crit = 0
if self.inst.crit then
	local crit = self.inst.crit
end

Then your character can change that value at your leisure.

Seeing as this code is run in the modmain and only runs for your character's prefab

I would modify it to look something like

Spoiler

AddComponentPostInit("combat", function(Combat)-- place in modmain
	local OldCalcDamage = Combat.CalcDamage
	Combat.CalcDamage = function(self, target, weapon, ...)
		local old_damage = nil
		if self.inst.prefab == "wilson" and self.inst.crit then
			local crit = self.inst.crit -- in postinit of your prefab make a variable called inst.crit you can then modify it at your leisure.
			local critdmg = 2 --crit damage (x2)
			if math.random() <= crit and target and weapon then --change to your prefab
				old_damage = weapon.components.weapon.damage
				weapon.components.weapon.damage = old_damage * critdmg
				-- visual effects and other stuff you can add
				local fx = SpawnPrefab("explode_small")
				local x, y, z = target.Transform:GetWorldPosition()
				fx.Transform:SetPosition(x, y, z)
			end
		end
		local ret = OldCalcDamage(self, target, weapon, ...)-- returning crit damage
		if old_damage and weapon then-- reseting back to non crit damage
			weapon.components.weapon.damage = old_damage
		end
		return ret
	end
end)

 

 

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