Jump to content

How do I make the character take more damage in general?


Recommended Posts

Basically what I'm asking is; what is the line of code for a character taking more damage in general? The mod I'm making has the character a little strong, but I want to balance it out with some kind of disadvantage, like being more fragile. I swear I've searched for hours on the internet what is the code, but I couldn't find anything and even if I did, it wouldn't work or it would crash my game. I couldn't even figure it out myself either. So this is kinda the only option I have left.  Also, where do I put it in the .lua file? I'll attach the file below.

taran.lua

Link to comment
Share on other sites

There doesn't appear to be any actual code in the game as far as the health component goes that would increase damage taken directly, unfortunately there's only absorption which exclusively decreases it. One option would be simply listening for the healthdelta event and dealing extra damage to yourself with health:DoDelta() which is a tad bit hacky but would get the job done

There's also the possibility of hooking into the DoDelta function itself and modifying the damage amount there before its applies, but I'm not sure this would actually be a better idea over just applying more damage after. Both options can work, though

Both options would go in your character's prefab. For the first, you'd put the ListenForEvent in master_postinit and a function where your other local functions are (below the onload function or around your OnEat function), for hooking it'd be the same but instead you'd do a DoTaskInTime in master_postinit that calls the function

Link to comment
Share on other sites

14 hours ago, Merkyrrie said:

There doesn't appear to be any actual code in the game as far as the health component goes that would increase damage taken directly, unfortunately there's only absorption which exclusively decreases it. One option would be simply listening for the healthdelta event and dealing extra damage to yourself with health:DoDelta() which is a tad bit hacky but would get the job done

There's also the possibility of hooking into the DoDelta function itself and modifying the damage amount there before its applies, but I'm not sure this would actually be a better idea over just applying more damage after. Both options can work, though

Both options would go in your character's prefab. For the first, you'd put the ListenForEvent in master_postinit and a function where your other local functions are (below the onload function or around your OnEat function), for hooking it'd be the same but instead you'd do a DoTaskInTime in master_postinit that calls the function

I don't understand most of that as I am very new to coding, but now I know that there isn't a code for what I'm looking for. However I have to ask, is there a code for a single mob? Like instead of that code applying to every single thing that deals damage, could I instead just write several lines of code individually for each mob? For example, a function for pigs, then another one for tallbirds, etc etc. It would definitely be very time consuming to type all of that, but I don't care. I will do it anyways, if that code does exist. I know that there is one for the damage taken from fire, but I don't know the one for mobs. So, is it possible? Could I just do that instead? If so, what is the code?

Link to comment
Share on other sites

8 hours ago, zonydragon said:

I don't understand most of that as I am very new to coding, but now I know that there isn't a code for what I'm looking for. However I have to ask, is there a code for a single mob? Like instead of that code applying to every single thing that deals damage, could I instead just write several lines of code individually for each mob? For example, a function for pigs, then another one for tallbirds, etc etc. It would definitely be very time consuming to type all of that, but I don't care. I will do it anyways, if that code does exist. I know that there is one for the damage taken from fire, but I don't know the one for mobs. So, is it possible? Could I just do that instead? If so, what is the code?

There isn't really anything on a case by case basis for mobs either, the game doesn't have anything that increases damage instead of reduces it that I know of so its not really built into the code to do that at all. There also isn't anything that'd let you change a mob's damage for a specific player either. I do think my suggestions above would be wildly easier than going mob by mob though, and if you wanted to limit the damage increase to only mobs attacking you, you could use the listen event for being attacked instead.

Its not too complicated to setup a simple function for increasing damage with either of the two options I listed before, though. The second one could cause problems in the future but the first only has the drawback of applying damage a second time to yourself which in certain scenarios could seem funky but would more or less be unnoticeable.

EDIT : Also as a simple explanation for some of this, the game sends data to whatever is connected to where its being pushed and wants it (I.E. every component on your character has access to pushed events towards your character) and anything that wants this data can use a ListenForEvent to receive it. In the option I wrote above, you'd be listening for the "healthdelta" event Pushed from DoDelta whenever your character is hurt. With the second option what I mean is more complicated but in simple terms its just rewriting the DoDelta function to add our own code before we let it do its thing

With the first option you can just do something like this (if you want it for all damage, rather than mob attacks. I can rewrite if thats the case) :

-- In your master_postinit function, shouldn't matter where as long as its in the function but I usually put it towards the end in case a component needs to be initalized first
inst:ListenForEvent("healthdelta", myDeltaFunction) -- function name can be anything as long as the name isn't in use in this lua file already


-- Then outside the master_postinit, either near your OnLoad or your OnEat function
local function myDeltaFunction(inst, data) -- data is the table of information given with the listen event, you can find all the variables in the PushEvent the DoDelta function pushes in the Health component
  if not inst.components.health or inst.components.health:IsDead() then -- checking first if your character somehow doesn't have the health component yet or they are in the process of dying, so we don't do anything in these cases
    return -- This simply ends the function early
  end
  -- For the rest of this, I'll simply have it make the damage you take be multipled by 1.5x, you can change it to whatever you need
  -- You can also do specific changes depending on what the source of the damage was with an if statement and data.cause or data.afflicter
  local amount = data.amount * .5 -- Getting half the original amount of damage since the original damage was already applied
  inst.components.health:DoDelta(math.ciel(amount)) -- DoDelta applies the damage, math.ciel rounds the number up to the nearest integer
	
end

I recommend the first option because its easier and less likely to cause problems later, but for hooking with the second option it would be like :

Spoiler
-- In master_postinit
inst:DoTaskInTime(1, updateDoDelta) -- We could just call updateDoDelta by itself, but we need to make sure everything else is loaded and ready before the function goes off


-- Outside master_postinit
local function updateDoDelta(inst)
  if not inst.components.health then -- Returning if this inst somehow doesn't have the health component
    return
  end
  local _DoDelta = inst.components.health.DoDelta -- Saving the old DoDelta function as a variable
  inst.components.health.DoDelta = function(inst, amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb) -- ReWriting DoDelta as our own function, which then returns the original DoDelta function with our new data. All the variables are from the DoDelta function
    -- I don't really do function hooking very often, I'm pretty sure there's a much better way to setting these variables for this but I don't have the 		time to go looking it up
    	-- You can also use the cause or afflicter variable here to write an if statement that changes the damage amount to something different depening on 		what caused the damage
    	amount = amount * 1.5 -- Increasing damage by 1.5x
		return _DoDelta(inst, amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)
	end
end

 

Finally, if you do just want it to only change damage when you're attacked :

Spoiler
-- In master_postinit
inst:ListenForEvent("attacked", OnAttacked) -- OnAttacked can still be whatever want it to be


-- Outside master_postinit
local function OnAttacked(inst, data) -- The data for this can be found in the PushEvent in the function in combat.lua
  if not inst.components.health or inst.components.health:IsDead()  or data.attacker == nil then -- Again returning if you're dying or do not have the 			health component, but also checking if there is no attacker somehow
    return
  end

  if data.attacker.prefab == "spider" then -- Can be removed, example of doing something specific for a specific enemy
    -- Your code here
  end
  
  local damage = data.damage * .5 -- Taking half the damage we already took to apply that to ourselves
  inst.components.health:DoDelta(damage)
end

 

I added a lot of comments in these to try and explain what's happening with each part, hopefully that helps. All of these options are fairly simple and very open to whatever you need them to be able to do, since they all have whatever caused the damage stored in a variable you can easily change the damage in a case by case basis through a series of if statements (or, if you want to you can use a table as it'd be far cleaner passed a certain amount of "options")

Edited by Merkyrrie
Link to comment
Share on other sites

12 hours ago, Merkyrrie said:

(if you want it for all damage, rather than mob attacks. I can rewrite if thats the case)

Sure.

 

12 hours ago, Merkyrrie said:

I added a lot of comments in these to try and explain what's happening with each part, hopefully that helps.

It really does, thank you! I really do appreciate it.

Link to comment
Share on other sites

54 minutes ago, zonydragon said:

You still there? I'd like the code for all damage, rather than just mob attacks if that's okay ^^

Oh, very sorry I could have wrote what I said much better

The first set of code was for all damage already, I was gonna rewrite it to be exclusive to mob attacks if that's what you needed but I ended up doing that anyway further into that reply and forgot to delete saying that.

First set of code covers all sources of damage, the second in spoilers does the same but modifies the base game's function instead, third in spoilers is specifically for damage from being attacked. If you want it to be for all sources the first set of code should be ready and good to use

Link to comment
Share on other sites

17 hours ago, Merkyrrie said:

Oh, very sorry I could have wrote what I said much better

The first set of code was for all damage already, I was gonna rewrite it to be exclusive to mob attacks if that's what you needed but I ended up doing that anyway further into that reply and forgot to delete saying that.

First set of code covers all sources of damage, the second in spoilers does the same but modifies the base game's function instead, third in spoilers is specifically for damage from being attacked. If you want it to be for all sources the first set of code should be ready and good to use

Ohh okay, all good. The first set of code is what I actually needed, and I put it in the .lua file but now whenever I enter a server and choose my character, then go into the world, this yellowish-white screen just appears and stays there forever. It's supposed to appear for a moment and then fade out, but that's not happening and I can't figure out what I did wrong. But I'm guessing it's where I put your code in my .lua file? Like maybe I put it in the wrong place. If you're wondering what it looks like, I'll attach the file below. If you can't open it or something, then you can also open the spoilered text below.

Spoiler

 

 

image_2023-02-14_154434348.png

taran.lua

Link to comment
Share on other sites

The frozen yellowish screen is the game stuck trying to load the character and failing.

It looks like the myDeltaFunction ended up inside the onload function, which isn't where you want it to be. Just move one of the two 'end' on line 63/64 and put it below the end on line 52 so the onload function properly closes before the other function begins.

 

Link to comment
Share on other sites

16 hours ago, Merkyrrie said:

The frozen yellowish screen is the game stuck trying to load the character and failing.

It looks like the myDeltaFunction ended up inside the onload function, which isn't where you want it to be. Just move one of the two 'end' on line 63/64 and put it below the end on line 52 so the onload function properly closes before the other function begins.

 

That worked, the character loaded successfully. However, I summoned a spider and hit it so it will attack me. I kept in mind that they deal 20 damage, and my character has 200 health so if it doesn't work for some reason, I will have 180 damage from being hit once. And that's exactly what happened, I received 20 damage even though I should get a little more because of your code, but it was even stranger than that. As soon as I hit the spider and it hit me back, the game froze and I got a "You have lost connection to the server" message on the screen, it said something like that. So I had to leave the server immediately. What's wrong here? Did the code just not work or it was something that I did?

taran.lua

Link to comment
Share on other sites

10 hours ago, zonydragon said:

That worked, the character loaded successfully. However, I summoned a spider and hit it so it will attack me. I kept in mind that they deal 20 damage, and my character has 200 health so if it doesn't work for some reason, I will have 180 damage from being hit once. And that's exactly what happened, I received 20 damage even though I should get a little more because of your code, but it was even stranger than that. As soon as I hit the spider and it hit me back, the game froze and I got a "You have lost connection to the server" message on the screen, it said something like that. So I had to leave the server immediately. What's wrong here? Did the code just not work or it was something that I did?

taran.lua 5.37 kB · 0 downloads

Ok I actually just realized this is a bad way to go about doing this, it didn't cross my mind that doing a health:DoDelta after listening to a health:DoDelta event would probably cause it to loop through those infinitely. My bad. I'm not sure if that's the error you're receiving but its a problem nonetheless more than likely.

The other bit of code is probably the better option even if its a bit more complicated.

-- In master_postinit, where the listener is
inst:DoTaskInTime(1, updateDoDelta) -- We could just call updateDoDelta by itself, but we need to make sure everything else is loaded and ready before the function goes off


-- Outside master_postinit, where you put the myHealthDelta before
local function updateDoDelta(inst)
  if not inst.components.health then -- Returning if this inst somehow doesn't have the health component
    return
  end
  local _DoDelta = inst.components.health.DoDelta -- Saving the old DoDelta function as a variable
  inst.components.health.DoDelta = function(inst, amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb) -- ReWriting DoDelta as our own function, which then returns the original DoDelta function with our new data. All the variables are from the DoDelta function
    -- I don't really do function hooking very often, I'm pretty sure there's a much better way to setting these variables for this but I don't have the 		time to go looking it up
    	-- You can also use the cause or afflicter variable here to write an if statement that changes the damage amount to something different depening on 		what caused the damage
    	amount = amount * 1.5 -- Increasing damage by 1.5x
		return _DoDelta(inst, amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)
	end
end

 

Link to comment
Share on other sites

12 hours ago, Merkyrrie said:

Ok I actually just realized this is a bad way to go about doing this, it didn't cross my mind that doing a health:DoDelta after listening to a health:DoDelta event would probably cause it to loop through those infinitely. My bad. I'm not sure if that's the error you're receiving but its a problem nonetheless more than likely.

The other bit of code is probably the better option even if its a bit more complicated.

-- In master_postinit, where the listener is
inst:DoTaskInTime(1, updateDoDelta) -- We could just call updateDoDelta by itself, but we need to make sure everything else is loaded and ready before the function goes off


-- Outside master_postinit, where you put the myHealthDelta before
local function updateDoDelta(inst)
  if not inst.components.health then -- Returning if this inst somehow doesn't have the health component
    return
  end
  local _DoDelta = inst.components.health.DoDelta -- Saving the old DoDelta function as a variable
  inst.components.health.DoDelta = function(inst, amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb) -- ReWriting DoDelta as our own function, which then returns the original DoDelta function with our new data. All the variables are from the DoDelta function
    -- I don't really do function hooking very often, I'm pretty sure there's a much better way to setting these variables for this but I don't have the 		time to go looking it up
    	-- You can also use the cause or afflicter variable here to write an if statement that changes the damage amount to something different depening on 		what caused the damage
    	amount = amount * 1.5 -- Increasing damage by 1.5x
		return _DoDelta(inst, amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)
	end
end

 

Oh, this one worked! Thank you very much, I appreciate all you did. Thanks.

Link to comment
Share on other sites

For taking extra damage, including armor taking more damage, I suggest hooking Combat:GetAttacked
 

AddComponentPostInit("combat", function(self)
	local _GetAttacked = self.GetAttacked

	function self:GetAttacked(attacker, damage, weapon, stimuli, ...)
		if self.inst:HasTag("yourcharactertaghere") then
			damage = damage * 1.5
			return _GetAttacked(self, attacker, damage, weapon, stimuli, ...)
		else
        	return _GetAttacked(self, attacker, damage, weapon, stimuli, ...)
        end
    end)
end)

 

Link to comment
Share on other sites

1 hour ago, O_Atoba_Azul said:

For taking extra damage, including armor taking more damage, I suggest hooking Combat:GetAttacked
 

AddComponentPostInit("combat", function(self)
	local _GetAttacked = self.GetAttacked

	function self:GetAttacked(attacker, damage, weapon, stimuli, ...)
		if self.inst:HasTag("yourcharactertaghere") then
			damage = damage * 1.5
			return _GetAttacked(self, attacker, damage, weapon, stimuli, ...)
		else
        	return _GetAttacked(self, attacker, damage, weapon, stimuli, ...)
        end
    end)
end)

 

I replaced the code I already had with that one to test it out, but I got this message when trying to launch the server (Image below).

Maybe it's where I put it or something?

image_2023-02-17_164001286.png

taran.lua

Link to comment
Share on other sites

On 2/18/2023 at 12:34 AM, O_Atoba_Azul said:

Put that in modmain.lua.

Oh, whoops, there's also an extra ) that shouldn't be there.

I put it in modmain.lua and removed the extra ), the error is gone but now every time I try to enter my server with the mod it just says "Server is generating world" forever. It literally won't stop loading no matter how long I wait.

image_2023-02-19_172433775.png

modmain.lua

Link to comment
Share on other sites

AddComponentPostInit("combat", function(self)
	local _GetAttacked = self.GetAttacked

	function self:GetAttacked(attacker, damage, weapon, stimuli, ...)
        damage = self.inst:HasTag("yourcharactertaghere") and damage*1.5 or damage
        return _GetAttacked(self, attacker, damage, weapon, stimuli, ...)
    end
end)

change tag

i think this metod dont work with armor

Edited by kipper0k
Link to comment
Share on other sites

4 hours ago, kipper0k said:
AddComponentPostInit("combat", function(self)
	local _GetAttacked = self.GetAttacked

	function self:GetAttacked(attacker, damage, weapon, stimuli, ...)
        damage = self.inst:HasTag("yourcharactertaghere") and damage*1.5 or damage
        return _GetAttacked(self, attacker, damage, weapon, stimuli, ...)
    end
end)

change tag

i think this metod dont work with armor

What do I change it to? Like what is the tag, I don't really know what that is specifically.

Edited by zonydragon
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...