--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| 	Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]


AddCSLuaFile()

if CLIENT then
   local GetPTranslation = LANG.GetParamTranslation
   local hint_params = {usekey = Key("+use", "USE")}

   ENT.TargetIDHint = {
      name = "vis_name",
      hint = "vis_hint",
      fmt  = function(ent, txt) return GetPTranslation(txt, hint_params) end
   };

end

ENT.Type = "anim"
ENT.Base = "ttt_basegrenade_proj"
ENT.Model = Model("models/Items/battery.mdl")

ENT.RenderGroup = RENDERGROUP_BOTH

ENT.Range = 128
ENT.MaxScenesPerPulse = 3
ENT.SceneDuration = 10
ENT.PulseDelay    = 10

ENT.CanUseKey = true

function ENT:Initialize()
   self.BaseClass.Initialize(self)

   self:SetSolid(SOLID_VPHYSICS)

   if SERVER then
      self:SetMaxHealth(50)
      self:SetExplodeTime(CurTime() + 1)
   end

   self:SetHealth(50)
end

function ENT:GetNearbyCorpses()
   local pos = self:GetPos()

   local near = ents.FindInSphere(pos, self.Range)
   if not near then return end

   local near_corpses = {}

   local ent = nil
   for i=1, #near do
      ent = near[i]
      if IsValid(ent) and ent.player_ragdoll and ent.scene then
         table.insert(near_corpses, {ent=ent, dist=pos:LengthSqr()})
      end
   end

   return near_corpses
end

local zapsound = Sound("npc/assassin/ball_zap1.wav")
function ENT:OnTakeDamage(dmginfo)
   self:TakePhysicsDamage(dmginfo)

   self:SetHealth(self:Health() - dmginfo:GetDamage())
   if self:Health() < 0 then
      self:Remove()

      local effect = EffectData()
      effect:SetOrigin(self:GetPos())
      util.Effect("cball_explode", effect)
      sound.Play(zapsound, self:GetPos())
   end
end

local dummy_keys = {"victim", "killer"}
function ENT:ShowSceneForCorpse(corpse)
   local scene = corpse.scene
   local hit = scene.hit_trace
   local dur = self.SceneDuration

   if hit then
      -- line showing bullet trajectory
      local e = EffectData()
      e:SetEntity(corpse)
      e:SetStart(hit.StartPos)
      e:SetOrigin(hit.HitPos)
      e:SetMagnitude(hit.HitBox)
      e:SetScale(dur)

      util.Effect("crimescene_shot", e)
   end

   if not scene then return end

   for _, dummy_key in ipairs(dummy_keys) do
      local dummy = scene[dummy_key]

      if dummy then
         -- Horrible sins committed here to get all the data we need over the
         -- wire, the pose parameters are going to be truncated etc. but
         -- everything sort of works out. If you know a better way to get this
         -- much data to an effect, let me know.
         local e = EffectData()
         e:SetEntity(corpse)
         e:SetOrigin(dummy.pos)
         e:SetAngles(dummy.ang)
         e:SetColor(dummy.sequence)
         e:SetScale(dummy.cycle)
         e:SetStart(Vector(dummy.aim_yaw, dummy.aim_pitch, dummy.move_yaw))
         e:SetRadius(dur)

         util.Effect("crimescene_dummy", e)
      end
   end
end

local scanloop = Sound("weapons/gauss/chargeloop.wav")
function ENT:StartScanSound()
   if not self.ScanSound then
      self.ScanSound = CreateSound(self, scanloop)
   end

   if not self.ScanSound:IsPlaying() then
      self.ScanSound:PlayEx(0.5, 100)
   end
end

function ENT:StopScanSound(force)
   if self.ScanSound and self.ScanSound:IsPlaying() then
      self.ScanSound:FadeOut(0.5)
   end

   if self.ScanSound and force then
      self.ScanSound:Stop()
   end
end


if CLIENT then
   local glow = Material("sprites/blueglow2")
   function ENT:DrawTranslucent()
      render.SetMaterial(glow)

      render.DrawSprite(self:LocalToWorld(self:OBBCenter()), 32, 32, COLOR_WHITE)
   end
end

function ENT:UseOverride(activator)
   if IsValid(activator) and activator:IsPlayer() then
      if activator:IsActiveDetective() and activator:CanCarryType(WEAPON_EQUIP) then
         self:StopScanSound(true)
         self:Remove()

         activator:Give("weapon_ttt_cse")
      else
         self:EmitSound("HL2Player.UseDeny")
      end
   end
end


function ENT:OnRemove()
   self:StopScanSound(true)
end

function ENT:Explode(tr)
   if SERVER then

      -- prevent starting effects when round is about to restart
      if GetRoundState() == ROUND_POST then return end

      self:SetCollisionGroup(COLLISION_GROUP_WEAPON)

      local corpses = self:GetNearbyCorpses()
      if #corpses > self.MaxScenesPerPulse then
         table.SortByMember(corpses, "dist", true)
      end

      local e = EffectData()
      e:SetOrigin(self:GetPos())
      e:SetRadius(128)
      e:SetMagnitude(0.5)
      e:SetScale(4)
      util.Effect("pulse_sphere", e)

      -- show scenes for nearest corpses
      for i=1, self.MaxScenesPerPulse do
         local corpse = corpses[i]
         if corpse and IsValid(corpse.ent) then
            self:ShowSceneForCorpse(corpse.ent)
         end
      end

      if #corpses > 0 then
         self:StartScanSound()
      else
         self:StopScanSound()
      end

      -- "schedule" next show pulse
      self:SetDetonateTimer(self.PulseDelay)

   end
end
