Changing the behavior of a player's armor

The default HL2 implementation of armor has it where a little armor protects your health a little, a lot of armor protects your health a lot. (ie: having just 10 armor and taking a bullet will leave you with some armor left but also remove health).

For my gamemode I want armor to totally protect the player until it is exhausted.

What is the best hook to override to accomplish this, and what are the broad strokes of the code I should have in it?

The HL2 armour system is extremely minimal and hardcoded. You’ll have to create your own armour system – whether you want it to work alongside HL2’s or replace it is up to you. Choosing to replace will require you to override GetArmor and SetArmor in the player metatable, and constantly check the original GetArmor to see if any entities/maps gave the player HL2 armour.

I’d personally go with

GM:EntityTakeDamage and simply check if the entity taking damage is a player, then check if the player has armor, then retrieve how much damage is being dealt, and subtract that from their armor, and if damage > armor, continue to subtract what extra damage is left.


hook.Add("EntityTakeDamage", "Real Armor", function(entity, info)
	if (entity:IsPlayer()) then
		local armor = entity:Armor()

		if (armor > 0) then
			local damage = info:GetDamage()

			entity:SetArmor(math.max(0, armor - damage))

			if (damage > armor) then
				entity:TakeDamage(math.abs(armor - damage), info:GetAttacker(), info:GetInflictor())
			end

			return true
		end
	end
end)

give that a try

Armor is deducted even if you scale the damage to 0 in EntityTakeDamage iirc.

i love this game

To be fair, Valve left the amour system extremely bare – it’s hardcoded to 100 max and doesn’t scale on internal damage modifications.

Are you sure about that?

From my testing it looks like setting the damage to 0 still takes 2-3 armor. Manually taking 25 armor results in the player losing 27, and manually taking 37.5 (25*1.5) results in them taking 40.

I think what I’ll do is always set the damage to 0 and return true to stop any of the original damage code from occurring (and manually handle the player’s health, too). Then, when the player’s health is <= 0, I’ll just return so that the original code takes over and makes the player keel over.

Am I overlooking any consequences from this?

By normal means – of course, you can just call SetArmor manually with whatever you want.

Works for me. Do you see anything wrong with my plan on overriding the EntityTakeDamage hook? (incidentally also the ScalePlayerDamage hook, so I can detect what parts are hit if they need to ignore armor)