/* * Author: Needles * https://steamcommunity.com/profiles/76561198026257137/ */ printl("*** HANDLER/FAKE_HEADSHOT"); local FakeHeadshotHandler = class extends ::Handler.BaseHandler { headshotVolume = null; blockingVolume = null; maxRayDistance = null; transformOverride = null; event_onHeadshot = null; constructor() { base.constructor(); headshotVolume = {origin = Vector(0.0, 0.0, 0.0), radius = 0.0}; blockingVolume = {origin = Vector(0.0, 0.0, 0.0), radius = 0.0, height = 0.0}; maxRayDistance = 512.0; transformOverride = null; event_onHeadshot = ::Events.Event(); } function DetermineHitscanCrit(params) { // The classic if (params.weapon.GetClassname() == "tf_weapon_sniperrifle_classic" && NetProps.GetPropFloat(params.weapon, "SniperRifleLocalData.m_flChargedDamage") == ::Const.SNIPER_CHARGE_MAX) return CRIT_TYPE.FULL; // Standard rifles if (params.weapon.GetClassname() == "tf_weapon_sniperrifle") { if (params.attacker.InCond(Constants.ETFCond.TF_COND_ZOOMED)) { if (params.idef == ITEM_DEFINITION_INDEX.SYDNEY_SLEEPER) return CRIT_TYPE.MINI; return CRIT_TYPE.FULL; } } // Ambassador if (params.idef == ITEM_DEFINITION_INDEX.AMBASSADOR) return CRIT_TYPE.FULL; return CRIT_TYPE.NONE; } function OnEvent_DamagePre(params) { if (params.const_entity != self) return; if (::Players.IsPlayerValid(params.attacker) == false) return; if (params.weapon == null || params.weapon.IsValid() == false) return; local crit = CRIT_TYPE.NONE; local start = null; local end = null; if (params.weapon.GetClassname() == "tf_weapon_compound_bow") { local trackedData = ::EntTracker.FindTrackedEntityData(params.inflictor); if (trackedData != null) { start = trackedData.start; local n = params.damage_force; n.Norm(); end = trackedData.start + n * maxRayDistance; ::Debug.Print(params.inflictor); crit = CRIT_TYPE.FULL; } } else { start = params.attacker.EyePosition(); local n = (params.damage_position - start); n.Norm(); end = params.damage_position + n * maxRayDistance; crit = DetermineHitscanCrit(params); } if (crit == CRIT_TYPE.NONE) return; local selfOrigin = self.GetOrigin(); local selfAngles = self.GetAbsAngles(); if (transformOverride != null) { selfOrigin = transformOverride.GetOrigin(); selfAngles = transformOverride.GetAbsAngles(); } local headshotOrigin = headshotVolume.origin; local blockingOrigin = blockingVolume.origin; local worldMatrix = ::MathN.BuildMatrix(selfOrigin, selfAngles, Vector(1.0, 1.0, 1.0)); headshotOrigin = MathN.MatrixTransformVector(worldMatrix, headshotOrigin); blockingOrigin = MathN.MatrixTransformVector(worldMatrix, blockingOrigin); local headshotIntersect = ::Collision.RaySphereIntersect(start, end, headshotOrigin, headshotVolume.radius); local blockingIntersect = ::Collision.RayCylinderIntersect(start, end, blockingOrigin, blockingVolume.radius, blockingVolume.height); if (headshotIntersect != null) { if (blockingIntersect == null) params.crit = crit; else if (headshotIntersect.t0 < blockingIntersect.t0) params.crit = crit; if (params.crit != CRIT_TYPE.NONE) { ::Debug.Print("*** FAKE_HEADSHOT_HANDLER - I got a headshot!"); event_onHeadshot.FireListeners({handler_fakeHeadshot = this, attacker = params.attacker}); } } } } ::Handler.RegisterHandler("fake_headshot", @() FakeHeadshotHandler());