diff --git a/lua/pac3/core/client/parts/damage_zone.lua b/lua/pac3/core/client/parts/damage_zone.lua index eab19fc12..0cc22bd3c 100644 --- a/lua/pac3/core/client/parts/damage_zone.lua +++ b/lua/pac3/core/client/parts/damage_zone.lua @@ -180,6 +180,8 @@ function PART:LaunchAuditAndEnforceSoftBan(amount, reason) return end local owner = self:GetPlayerOwner() + if not IsValid(owner) then return end + if owner ~= LocalPlayer() then return end owner.stop_hit_markers_admonishment_count = owner.stop_hit_markers_admonishment_count or 1 owner.stop_hit_markers_admonishment_message_up = false @@ -277,6 +279,8 @@ local function CleanupParts(group) end function PART:FindOrCreateFloatingPart(owner, ent, part_uid, id, parent_ent) + if not IsValid(owner) or not IsValid(ent) then return end + owner.hitmarker_partpool = owner.hitmarker_partpool or {} for spec_uid,tbl in pairs(owner.hitmarker_partpool) do if tbl.template_uid == part_uid then @@ -317,6 +321,8 @@ net.Receive("pac_send_ragdoll", function(len) end) local function TryAttachPartToAnEntity(self,group,parent_ent,marker_ent,killing) + if not IsValid(parent_ent) or not IsValid(marker_ent) then return end + local can_do_ragdolls = GetConVar("pac_sv_damage_zone_allow_ragdoll_hitparts"):GetBool() if killing and can_do_ragdolls then if isstring(killing) then @@ -353,17 +359,19 @@ local function TryAttachPartToAnEntity(self,group,parent_ent,marker_ent,killing) end group:SetOwnerName(parent_ent:EntIndex()) end - + else group:SetOwner(marker_ent) end end local function FreeSpotInStack(owner) + if not IsValid(owner) then return end + owner.hitparts = owner.hitparts or {} owner.hitparts_freespots = owner.hitparts_freespots or {} for i=1,50,1 do - if owner.hitparts_freespots[i] == nil then owner.hitparts_freespots[i] = false return i end + if owner.hitparts_freespots[i] == nil then owner.hitparts_freespots[i] = false return i end if owner.hitparts_freespots[i] ~= false then if owner.hitparts[i] then if not owner.hitparts[i].active then @@ -383,6 +391,8 @@ end ]] local function MatchInStack(owner, ent) + if not IsValid(owner) or not IsValid(ent) then return end + owner.hitparts = owner.hitparts or {} for i=1,50,1 do if owner.hitparts[i] then @@ -398,6 +408,8 @@ local function MatchInStack(owner, ent) end local function UIDMatchInStackForExistingPart(owner, ent, part_uid, ent_id) + if not IsValid(owner) or not IsValid(ent) then return end + owner.hitparts = owner.hitparts or {} for i=1,50,1 do if owner.hitparts[i] then @@ -424,6 +436,8 @@ end owner.hitparts[free] = {active, specimen_part, hitmarker_id, template_uid} ]] function PART:AddHitMarkerToStack(index, owner, ent, part_uid, ent_id, parent_ent, killing) + if not IsValid(owner) or not IsValid(ent) or not IsValid(parent_ent) then return end + --print("trying to add to stack:") --print("\t\t",owner, ent, part_uid, ent_id, parent_ent) owner.hitparts = owner.hitparts or {} @@ -441,12 +455,14 @@ function PART:AddHitMarkerToStack(index, owner, ent, part_uid, ent_id, parent_en owner.hitparts[index] = {active = true, specimen_part = returned_part, hitmarker_id = ent_id, template_uid = part_uid, csent = ent, parent_ent = parent_ent} TryAttachPartToAnEntity(self,existingpart,parent_ent,ent, killing) end - + return returned_part end local function RemoveHitMarker(owner, ent, uid, id) + if not IsValid(owner) or not IsValid(ent) then return end + owner.hitparts = owner.hitparts or {} local match = MatchInStack(owner, ent) @@ -475,7 +491,7 @@ end ]] function PART:AssignFloatingPartToEntity(index, part, owner, ent, parent_ent, template_uid, marker_id) - if not IsValid(part) then return false end + if not IsValid(part) or not IsValid(owner) or not IsValid(ent) or not IsValid(parent_ent) then return false end ent.pac_draw_distance = 0 @@ -496,13 +512,13 @@ function PART:AssignFloatingPartToEntity(index, part, owner, ent, parent_ent, te group:SetShowInEditor(false) TryAttachPartToAnEntity(self,group,parent_ent,ent) - - + + timer.Simple(0, function() group:SetHide(false) part2:SetHide(false) group:CallRecursive("Think") group:CallRecursive("CalcShowHide") end) - - + + --print(parent_ent, group:IsHidden(), part2:IsHidden()) - + owner.hitparts_freespots[index] = false --print(group, "assigned to " .. marker_id .. " / " .. parent_ent:EntIndex()) @@ -513,6 +529,8 @@ function PART:ClearHitMarkers() if IsValid(part) then part:GetRootOwner():Remove() end end local ply = self:GetPlayerOwner() + if not IsValid(ply) then return end --CMON CEDRIC. IT'S THIS EASY + if ply.hitparts then for i,v in pairs(ply.hitparts) do v.specimen_part:Remove() @@ -680,6 +698,10 @@ function PART:SendNetMessage() end function PART:OnShow() + if not IsValid(self) then return end + local owner = self:GetPlayerOwner() + if not IsValid(owner) then return end + self.remaining_DOT_count = self.DOTCount self.next_DOT = self.NoInitialDOT and CurTime() + self.DOTTime or CurTime() - 1 @@ -690,12 +712,15 @@ function PART:OnShow() self:PreviewHitbox() end self.stop_until = self.stop_until or 0 - if self.stop_until then self:GetPlayerOwner().stop_hit_markers_admonishment_message_up = nil end - if (self:GetPlayerOwner().stop_hit_markers_admonishment_message_up) or self.stop_until > CurTime() then return end + if self.stop_until then owner.stop_hit_markers_admonishment_message_up = nil end + if (owner.stop_hit_markers_admonishment_message_up) or self.stop_until > CurTime() then return end if self.DOTMethod == "RefreshZone" then return end --handle with Think - if self:GetRootPart():GetOwner() ~= self:GetPlayerOwner() then --dumb workaround for when it activates before it realizes it needs to be hidden first + local rootOwner = self:GetRootPart():GetOwner() + if not IsValid(rootOwner) then return end + + if rootOwner ~= owner then --dumb workaround for when it activates before it realizes it needs to be hidden first timer.Simple(0.01, function() --wait to check if needs to be hidden first if self:IsHidden() or self:IsDrawHidden() then return end if self.Preview then @@ -715,19 +740,22 @@ end local dmgzone_requesting_corpses = {} function PART:SetAttachPartsToTargetEntity(b) + local owner = self:GetPlayerOwner() + if not IsValid(owner) then return end + self.AttachPartsToTargetEntity = b - if pac.LocalPlayer ~= self:GetPlayerOwner() then return end + if pac.LocalPlayer ~= owner then return end if self.KillMarkerPart == nil then return end if b then net.Start("pac_request_ragdoll_sends") - net.WriteBool(true) + net.WriteBool(true) net.SendToServer() dmgzone_requesting_corpses[self] = true else dmgzone_requesting_corpses[self] = nil if table.Count(dmgzone_requesting_corpses) == 0 then net.Start("pac_request_ragdoll_sends") - net.WriteBool(false) + net.WriteBool(false) net.SendToServer() end end @@ -735,18 +763,22 @@ end --revertable to projectile part's version which wastes time creating new parts but has less issues function PART:LegacyAttachToEntity(part, ent) + if not IsValid(ent) then return false end if not part:IsValid() then return false end ent.pac_draw_distance = 0 local tbl = part:ToTable() - local group = pac.CreatePart("group", self:GetPlayerOwner()) + local ply = self:GetPlayerOwner() + if not IsValid(ply) then return end + + local group = pac.CreatePart("group", ply) table.insert(hitparts_dump, {self, group, ent}) self.force_cleanup_hitparts = CurTime() + math.max(self.HitMarkerLifetime, self.KillMarkerLifetime) group:SetShowInEditor(false) - local part_clone = pac.CreatePart(tbl.self.ClassName, self:GetPlayerOwner(), tbl, tostring(tbl)) + local part_clone = pac.CreatePart(tbl.self.ClassName, ply, tbl, tostring(tbl)) group:AddChild(part_clone) group:SetOwner(ent) @@ -797,6 +829,13 @@ net.Receive("pac_hit_results", function(len) local pos = self:GetWorldPosition() local owner = self:GetPlayerOwner() + if not IsValid(owner) then return end + + --START_BS_MOD + --Octo 3/32026 + --Purpose: Set off a client hook so we know what a damage zone did for crediting in the killcam. + hook.Run("BS_pacHitResults", owner, uid, self, pos, hit, kill, highest_dmg, do_ents_feedback, ents_hit, ents_kill) + --END_BS_MOD self.lag_risk = table.Count(ents_hit) > 15 @@ -880,7 +919,7 @@ net.Receive("pac_hit_results", function(len) end local free_spot = FreeSpotInStack(owner) - + if free_spot then if part:IsValid() then --self:AttachToEntity(part, ent, parent_ent, global_hitmarker_CSEnt_seed) --print("free spot should be " .. free_spot) @@ -1020,6 +1059,10 @@ function PART:PreviewHitbox() if not self.Preview then pac.RemoveHook(self.RenderingHook, "pace_draw_hitbox"..self.UniqueID) end if not IsValid(self) then pac.RemoveHook(self.RenderingHook, "pace_draw_hitbox"..self.UniqueID) end self:GetWorldPosition() + + local ply = self:GetPlayerOwner() + if not IsValid(ply) then return end + if self.HitboxMode == "Box" then local mins = Vector(-self.Radius, -self.Radius, -self.Length) local maxs = Vector(self.Radius, self.Radius, self.Length) @@ -1041,7 +1084,8 @@ function PART:PreviewHitbox() cam.PushModelMatrix( mat ) obj:Draw() cam.PopModelMatrix() - if LocalPlayer() == self:GetPlayerOwner() then + + if LocalPlayer() == ply then if self.Radius ~= 0 then local sides = self.Detail if self.Detail < 1 then sides = 1 end @@ -1116,7 +1160,7 @@ function PART:PreviewHitbox() cam.PushModelMatrix( mat ) obj:Draw() cam.PopModelMatrix() - if LocalPlayer() == self:GetPlayerOwner() then + if LocalPlayer() == ply then if self.Radius ~= 0 then local sides = self.Detail if self.Detail < 1 then sides = 1 end