Not a trivial task. Below is what I've built up over the last few months to handle (ie, prevent) killing while in God Mode. There are lots of considerations including ranged weapons that don't inherit parent ownership properly, preventing prop damage etc. It's never really 100%, but below is close. I think this is completely self contained, but let me know if you run into problems.
* If user is in God Mode and attempts to damage / kill, he/she will receive a HUD notification that you cannot damage in God Mode. Damage will be dropped.
* Place in ../addons/thab_local/lua/ulib/modules/thab_god.lua
* (alternatively, ../addons/<anynameyouwant>/lua/ulib/modules/anynameyouwant.lua)
AddCSLuaFile()
if SERVER then
util.AddNetworkString( "GodCheckMsg" )
-- player-specific function. Is this redundant?
function THABHandleGodDamagePlayer(ent, att)
local dbg = false
local target = ent
local attacker = att
if dbg then
print( "------------------Inside THABHandleGodDamagePlayer-------------------" )
print( "target = ", target )
print( "attacker = ", attacker )
print( "attacker Parent = ", attacker:GetParent() )
print( "attacker Owner = ", attacker:GetOwner() )
print( "attacker CPPIGetOwner = ", attacker:CPPIGetOwner() )
end
local targetOwner = target
local attackerOwner = attacker
-- get the player attacker involved
if not attacker:IsPlayer() then
attackerOwner = attacker:CPPIGetOwner()
end
if dbg then
print( "(ply) ", attackerOwner, " is player attacking (ply) ", targetOwner )
end
if attackerOwner == nil then
-- we have a situation where the attacker is not determined. Likely a worldspawn, tank shell or thrown weapon. Let's just kill it for now.
local ignoreAttack = false
if attacker != nil then
if attacker:GetClass() == "m9k_thrown_knife" then ignoreAttack = true end -- unowned thrown knife. Kill it
if attacker:GetClass() == "ent_sky_daedricarrow" then ignoreAttack = true end -- unowned thrown knife. Kill it
end
if ignoreAttack then
if dbg then print("1 Player Attack was dropped due to undetermined attacker") end
print ("1 Player Attack by ", attackerOwner,":",attacker, " on ", targetOwner,":", target, " using ", inflictor," was ignored.")
return false
end
return -- we know attackerOwner is nil. Just return. We can't do anything else interesting.
end
if attackerOwner==targetOwner then return end -- ignore self inflicted damage
-- attackerOwner has godmode or is noclipped
if attackerOwner:IsPlayer() then
if attackerOwner:HasGodMode() then
net.Start( "GodCheckMsg" )
net.WriteString("god")
net.Send( attackerOwner )
if dbg then print("Player Attack was dropped due to attacker godmode") end
return false
end
if attackerOwner:GetMoveType() == MOVETYPE_NOCLIP and not attackerOwner:InVehicle() then
net.Start( "GodCheckMsg" )
net.WriteString("noclip")
net.Send( attackerOwner )
if dbg then print("Attack was dropped due to attacker noclip") end
return false
end
end
-- targetOwner has god mode. Remove the damage regardless of whether or not we have a defined owner.
if targetOwner:HasGodMode() then
if attackerOwner:IsPlayer() then
net.Start( "GodCheckMsg" )
net.WriteString("god2")
net.Send( attackerOwner )
if dbg then print("Player Attack was dropped due to target godmode") end
end
return false
end
end
hook.Add( "PlayerShouldTakeDamage", "THAB.PlayerShouldTakeDamage.GodMode", THABHandleGodDamagePlayer, -15 )
-- any entity, check for damage
function THABHandleGodDamage( ent, dmginfo )
local dbg = false
local target = ent
local inflictor = dmginfo:GetInflictor()
local attacker = dmginfo:GetAttacker()
if dbg then
print( "------------------Inside THABHandleGodDamage (EntityTakeDamage) -------------------" )
print( "target = ", target )
print( "dmginfo = ", dmginfo )
print( "attacker = ", attacker )
print( "attacker Parent = ", attacker:GetParent() )
print( "attacker Owner = ", attacker:GetOwner() )
print( "attacker CPPIGetOwner = ", attacker:CPPIGetOwner() )
print( "inflictor = ", inflictor )
end
local targetOwner = target
local attackerOwner = attacker
-- get the player victim involved (target or target's owner
if not target:IsPlayer() then
targetOwner = target:CPPIGetOwner()
end
-- get the player attacker involved
if not attacker:IsPlayer() then
attackerOwner = attacker:CPPIGetOwner()
end
if dbg then
print( "(ply) ", attackerOwner, " is attacking (ply) ", targetOwner )
end
if attackerOwner == nil then
-- we have a situation where the attacker is not determined. Likely a worldspawn, tank shell or thrown weapon. Let's just kill it for now.
local ignoreAttack = false
if attacker != nil and attacker:GetClass() != nil then
if attacker:GetClass() == "m9k_thrown_knife" then ignoreAttack = true end -- unowned thrown knife. Kill it
if attacker:GetClass() == "ent_sky_daedricarrow" then ignoreAttack = true end -- unowned thrown knife. Kill it
end
if ignoreAttack then
dmginfo:SetDamage(0);
if dbg then print("2 Attack was dropped due to undetermined attacker") end
print ("2 Attack by ", attackerOwner,":",attacker, " on ", targetOwner,":", target, " using ", inflictor," was dropped.")
return false
end
return -- we know attackerOwner is nil. Just return. We can't do anything else interesting.
end
if targetOwner == nil then return end
if attackerOwner==targetOwner then return end -- ignore self inflicted damage
-- attackerOwner has godmode or is noclipped
if attackerOwner:IsPlayer() then
if attackerOwner:HasGodMode() then
dmginfo:SetDamage(0);
net.Start( "GodCheckMsg" )
net.WriteString("god")
net.Send( attackerOwner )
if dbg then print("Attack was dropped due to attacker godmode") end
return false
end
if attackerOwner:GetMoveType() == MOVETYPE_NOCLIP and not attackerOwner:InVehicle() then
dmginfo:SetDamage(0);
net.Start( "GodCheckMsg" )
net.WriteString("noclip")
net.Send( attackerOwner )
if dbg then print("Attack was dropped due to attacker noclip") end
return false
end
end
-- targetOwner has god mode. Remove the damage regardless of whether or not we have a defined owner.
if !target:IsNPC() and targetOwner:IsPlayer() then
if targetOwner:HasGodMode() then
dmginfo:SetDamage(0);
if attackerOwner:IsPlayer() then
net.Start( "GodCheckMsg" )
net.WriteString("god2")
net.Send( attackerOwner )
if dbg then print("Attack was dropped due to target godmode") end
end
return false
end
end
end
hook.Add( "EntityTakeDamage", "THAB.EntityTakeDamage.GodMode", THABHandleGodDamage, -15)
else
function csayDrawThab( amsg)
color = Color( 255, 255, 40, 255 )
duration = 2
fade = 0.5
start = CurTime()
msg = amsg
hook.Add( "HUDPaint", "drawToScreen2", drawToScreen2 )
end
function drawToScreen2()
local alpha = 255
local dtime = CurTime() - start
if dtime > duration then -- Our time has come :'(
hook.Remove( "HUDPaint", "drawToScreen2" )
return
end
--if fade - dtime > 0 then -- beginning fade
-- alpha = (fade - dtime) / fade -- 0 to 1
-- alpha = 1 - alpha -- Reverse
-- alpha = alpha * 255
--end
--if duration - dtime < fade then -- ending fade
-- alpha = (duration - dtime) / fade -- 0 to 1
-- alpha = alpha * 255
--end
color.a = alpha
--draw.DrawText( msg, "CloseCaption_Bold", ScrW() * 0.5, ScrH() * 0.20, color, TEXT_ALIGN_CENTER )
draw.SimpleTextOutlined( msg, "CloseCaption_Bold", ScrW() * 0.5, ScrH() * 0.20, color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1, Color( 100, 100, 100, 200 ) )
end
net.Receive( "GodCheckMsg", function( len )
local msg = net.ReadString()
local txt = ""
if msg=="god" then
txt = "No damage. You're in god mode!"
elseif msg=="noclip" then
txt = "No damage. You're in noclip!"
elseif msg=="god2" then
txt = "No damage. Target is in god mode!"
end
csayDrawThab(txt)
end )
end