Jump to content

[Solved] Way to make a entity that isn't a player not take bonus damage from bosses?


Recommended Posts

Hello, I have a question if someone can help me that'd really be awesome :)!

So, basically I'm trying to make npc players & I noticed that they take huge amount of damage from bosses just like how other entities like pigmen do & I was wondering if there's a way I can prevent that?

I went through beequeen.lua which she deals 2x damage to entities that aren't players, but I couldn't really see anything like bonus damage or some special tag to exclude the bonus damage :?..so I'm kinda stuck:wilson_dorky:!

 

Any help would be very nice, & thanks for reading my problem! Have a great day/night :wilson_flower:!

 

 

Edited by SuperDavid
Link to comment
Share on other sites

It seems it's in this function in combat.lua, the "playermultiplier" for npc attacking player. Though, when I add tag "player" to my npc the game crashes..I think that tag is specifically reserved for players only.

That means I have to edit this to include my tag, but I don't know how to edit this function without copy-paste combat.lua for my mod which I think is bad way to do it :wilson_resigned:..

Spoiler

function Combat:CalcDamage(target, weapon, multiplier)
    if target:HasTag("alwaysblock") then
        return 0
    end

    local basedamage
    local basemultiplier = self.damagemultiplier
    local bonus = self.damagebonus --not affected by multipliers
    local playermultiplier = target ~= nil and target:HasTag("player")
    local pvpmultiplier = playermultiplier and self.inst:HasTag("player") and self.pvp_damagemod or 1

    --NOTE: playermultiplier is for damage towards players
    --      generally only applies for NPCs attacking players

    if weapon ~= nil then
        --No playermultiplier when using weapons
        basedamage = weapon.components.weapon.damage or 0
        playermultiplier = 1
    else
        basedamage = self.defaultdamage
        playermultiplier = playermultiplier and self.playerdamagepercent or 1

        if self.inst.components.rider ~= nil and self.inst.components.rider:IsRiding() then
            local mount = self.inst.components.rider:GetMount()
            if mount ~= nil and mount.components.combat ~= nil then
                basedamage = mount.components.combat.defaultdamage
                basemultiplier = mount.components.combat.damagemultiplier
                bonus = mount.components.combat.damagebonus
            end

            local saddle = self.inst.components.rider:GetSaddle()
            if saddle ~= nil and saddle.components.saddler ~= nil then
                basedamage = basedamage + saddle.components.saddler:GetBonusDamage()
            end
        end
    end

    return basedamage
        * (basemultiplier or 1)
        * (multiplier or 1)
        * playermultiplier
        * pvpmultiplier
        + (bonus or 0)
end

 

Edited by SuperDavid
Link to comment
Share on other sites

Maybe you could modify something else instead for your npc? Like the Combat:GetAttacked function. At some point there the damages are calculated, maybe you could check who is the attacker and if it's a boss apply a reduction factor on the damages taken.

There are several ways to do what you want to do, this is the first one which came to my mind, not saying it's the best.

Link to comment
Share on other sites

I tried code like this, but my npc still takes the 2x damage before healing back half of it to make it like player damage.

inst:ListenForEvent("attacked", function(inst, data)
	local damage = data.damage
	if data.attacker:HasTag("epic") then
		inst.components.health:DoDelta(data.damage * .5)
	end
end)

do you maybe know a way the better way to do this :)?

And sorry for bothering you so much, thanks for all your help man :D!

Link to comment
Share on other sites

You could override the function I am mentioning directly instead of reacting to the event "attacked".

Try to read and understand each of the lines in

components/combat.lua

function Combat:GetAttacked

Could you post back which line deals with the damage the entity will receive?

Link to comment
Share on other sites

Give your NPC a unique tag. Then override the CalcDamage function in combat.lua the regular way you override functions ('m assuming you can do this, I haven't tested this) and add a check before calling the regular function that divides the damage by some value that cancels out the player multiplier if the mob has your NPCs unique tag.

If you can't replace the function *at all* then I'm not sure what to do off the top of my head.

 

EDIT: I've never edited a component but I'm guessing you'd use the normal trick where you copy the function and embed it into a new function
 

oldCombatcalc = component.whateverfunction
component.whateverfunction = function(arguments)
	--Do the division
	oldCombatCalc(arguments)
end

AddComponentPostInit(whatever)

I've never used AddComponentPostInit so if this isn't how it would work for components then you'll have to look into that I guess.

nvm, check second post

Edited by code4240
Link to comment
Share on other sites

Okay, I actually did it in game and this works.

I made a really fast custom char with the tag "superspecial" and then did this in modmain:

local function OverrideCombat(comp)
	local OldCombat = comp.CalcDamage
	comp.CalcDamage = function(self, target, weapon, multiplier)
		if target:HasTag("superspecial") then	
			multiplier = 0 -- replace this part with the necessary number / calculation
		end
		return OldCombat(self, target, weapon, multiplier)
	end
end

AddComponentPostInit("combat", OverrideCombat)

This made my character immune to damage.

You'd replace the 0 with whatever you'd need to in order to cancel out the playermult.

EDIT: I'm guessing you'd want to set multiplier to be equal to self.playerdamagepercent, as implied by this line:

playermultiplier = playermultiplier and self.playerdamagepercent or 1

-which sets playermult to playerdamagepercent if it's true.
However, I don't have a custom NPC to add this code to so I can't actually test this.

Edited by code4240
Link to comment
Share on other sites

Thank you @code4240 your code works great, it halves the damage my entity take :D!! Thanks you because I'm not good at editing components or whatever this is xD..

If maybe you just know one thing is that do you know how I can make this code only work in halving damage from things with "epic" tag?

Spoiler

local function OverrideCombat(comp)
	local OldCombat = comp.CalcDamage
	comp.CalcDamage = function(self, target, weapon, multiplier)
		if target.prefab == "tieravil" then	
			multiplier = .5
		end
		return OldCombat(self, target, weapon, multiplier)
	end
end

AddComponentPostInit("combat", OverrideCombat)

 

since I think only epic entities deal 2x damage to non-players, & thanks a lot your help :D!!

Link to comment
Share on other sites

Actually, my answer was wrong. It just occurred to me that multiplier stacks with playermultiplier so changing it would give inaccurate results if it was supposed to be not 1. So actually what you'll want to do is multiply the result of the old function by the value instead of changing the multiplier.

Also, don't use 0.5, use playerdamagepercent. Changing this value is how mobs do different damage to players. I haven't looked but I'm assuming if you look at the files for the bosses such as deerclops you'll see them setting that value to 0.5 (probably using the setter function in combat.lua, though I'm too lazy to go look)
which would mean that if the mob would do half damage to players then playerdamagepercent would be 0.5 like you want. Or any other value the mob might do to players.

Link to comment
Share on other sites

Quote

Thanks you because I'm not good at editing components or whatever this is xD..

You'll wanna study the general technique I used because it's pretty important to modding pretty much anything in the game that isn't brand new content. Luckily it's pretty simple since prefabs and components actually aren't all that different. Basically there are a lot of "AddXPostInit" functions, like AddPrefabPostInit, AddComponentPostInit, AddBrainPostInit, etc. They all pretty much do the same thing, which is modify a prefab/component/etc. that you specify by tacking whatever function you write onto the end of the init function for that thing.

Basically, you could pretend that whatever function you gave it (in our case we passed the OverrideCombat function we wrote) just got stuck inside the prefab on the very last line of the init, right before it returns at the end, and you have to figure out how you would modify the rest of  the file only using that one function there.

As for the part where you actually change the calc, we basically save a copy the function the component was using for calc to a variable, and then replace the calc in the component with a new function we wrote that calls the copy of the old function inside it to ensure the original code still gets called. This is the standard practice for replacing functions in Don't Starve because it allows mods to be compatible; if multiple mods modify the same function this way, it has a sort of nesting doll effect where each one wraps around the other and they all still get called. As opposed to just overriding the function entirely or the whole file, in which case any other modifications that had been made to that function / file before the new one got loaded would be wiped out.

Prefabs are changed the same way, and prefabs can actually modify their individual copies of a component. So for example, you could go into the bearger file via AddPrefabPostInit and modify its copy of the combat component by setting the calc function to multiply the damage by 5,000 if it was your NPC. In this case, only the bearger would do 5,000x damage to your NPC and everyone else would be the same because only the copy of the combat component that belongs to the bearger gets modified, while when using AddComponentPostInit you'd be modifying the base file for the combat component and all the prefabs that later used combat would start out with those changes.

This also applies to brains but those are a whole other can of worms in terms of how the code you're modifying is actually structured tbh.

Link to comment
Share on other sites

Sorry, but I don't think I understood much of what you said :confused:

I replace .5 with "playerdamagepercent" at multiplier? It seems to do no damage halving at all now..sorry I couldn't really understand what to do.

Though, I don't wanna waste your time since this seems really complicated & stuff so I'm just gonna put a .5 health absorb on my followers, but thanks for your help man :D!

Link to comment
Share on other sites

Quote

Though, I don't wanna waste your time since this seems really complicated & stuff so I'm just gonna put a .5 health absorb on my followers, but thanks for your help man :D!

Oh no, this is actually pretty simple to me lol. The reason I wasn't more thorough is because I had to work last night. I realized my error in my first code while I was in the middle of my shift lol. And when I issued my correction was right before I went to bed so I didn't test anything.

Anyway, I'm awake and not at work now so allow me to clarify on what I meant:

local function OverrideCombat(comp)
	local OldCombat = comp.CalcDamage
	comp.CalcDamage = function(self, target, weapon, multiplier)
		local dmg = OldCombat(self, target, weapon, multiplier)
		if target:HasTag("superspecial") then
        		print("------")
			print(dmg)
			if self.playerdamagepercent ~= nil then 
				dmg = dmg * self.playerdamagepercent
				print(dmg)
				print(self.playerdamagepercent) -- print the modifier to see what you're multiplying by
			else 
				print("1") -- If the value is nil then it's not multiplied
			end
		end
		return dmg
	end
end

I tested this and it works.

Spoiler

wZYKjHp.png

4kJpCcc.png

(You'll want to remove or comment the prints at some point)

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