AddCSLuaFile()

if SERVER then
	util.AddNetworkString("DarkRP_ConfiscateEntity")
end

if CLIENT then
	SWEP.PrintName = "Stun Stick"
	SWEP.Slot = 0
	SWEP.SlotPos = 5
	SWEP.RenderGroup = RENDERGROUP_BOTH

	killicon.AddAlias("stunstick", "weapon_stunstick")
	CreateMaterial("mg_darkrp/stunstick_beam", "UnlitGeneric", {
		["$basetexture"] = "sprites/lgtning",
		["$additive"] = 1
	})
end

DEFINE_BASECLASS("stick_base")

SWEP.Instructions = "Left click to discipline\nRight click to kill\nHold reload to threaten"
SWEP.IsDarkRPStunstick = true

SWEP.Spawnable = true
SWEP.Category = "DarkRP (Utility)"

SWEP.StickColor = Color(0, 0, 255)

SWEP.Hit = {
	Sound("weapons/stunstick/stunstick_impact1.wav"),
	Sound("weapons/stunstick/stunstick_impact2.wav")
}

SWEP.FleshHit = {
	Sound("weapons/stunstick/stunstick_fleshhit1.wav"),
	Sound("weapons/stunstick/stunstick_fleshhit2.wav")
}

function SWEP:Initialize()
	BaseClass.Initialize(self)
end

function SWEP:SetupDataTables()
	BaseClass.SetupDataTables(self)
	self:NetworkVar("Float", 6, "LastReload")
end

function SWEP:Think()
	BaseClass.Think(self)
	if SERVER and self.WaitingForAttackEffect and self:GetSeqIdleTime() != 0 and CurTime() >= self:GetSeqIdleTime() - 0.35 then
		self.WaitingForAttackEffect = false
		local owner = self:GetOwner()
		local effectData = EffectData()
		effectData:SetOrigin(owner:GetShootPos() + (owner:EyeAngles():Forward() * 45))
		effectData:SetNormal(owner:EyeAngles():Forward())
		util.Effect("StunstickImpact", effectData, true)
	end
end

function SWEP:DoFlash(ply)
	if !IsValid(ply) or !ply:IsPlayer() then return end
	ply:ScreenFade(SCREENFADE.IN, color_white, 1.2, 0)
end

local stunstickMaterial = Material("effects/stunstick")
local stunstickBeam	 = Material("!mg_darkrp/stunstick_beam")
function SWEP:PostDrawViewModel(vm)
	if !IsValid(vm) then return end
	if vm:GetSequenceActivity(vm:GetSequence()) == ACT_VM_HITCENTER or self:GetLastReload() >= CurTime() - 0.1 then
		local attachment = vm:GetAttachment(1)
		if !attachment then return end
		local pos = attachment.Pos
		cam.Start3D(EyePos(), EyeAngles())
			render.SetMaterial(stunstickMaterial)
			render.DrawSprite(pos, 12, 12, Color(180, 180, 180))
			for i = 1, 3 do
				local randVec = VectorRand() * 3
				local offset = (attachment.Ang:Forward() * randVec.x) + (attachment.Ang:Right() * randVec.y) + (attachment.Ang:Up() * randVec.z)
				render.SetMaterial(stunstickBeam)
				render.DrawBeam(pos, pos + offset, 3.25 - i, 1, 1.25, Color(180, 180, 180))
				pos = pos + offset
			end
		cam.End3D()
	end
end

local light_glow02_add = Material("sprites/light_glow02_add")
function SWEP:DrawWorldModelTranslucent()
	local owner = self:GetOwner()
	if IsValid(owner) then
		if self:GetHoldType() != "normal" or self:GetLastReload() >= CurTime() - 0.1 then
			local bone = owner:LookupBone("ValveBiped.Bip01_R_Hand")
			if !bone then self:DrawModel() return end
			local bonePos, boneAng = owner:GetBonePosition(bone)
			if bonePos then
				local pos = bonePos + (boneAng:Up() * -16) + (boneAng:Right() * 3) + (boneAng:Forward() * 6.5)
				render.SetMaterial(light_glow02_add)
				render.DrawSprite(pos, 32, 32, color_white)
			end
		end
	end
	self:DrawModel()
end

local entMeta = FindMetaTable("Entity")
function SWEP:DoAttack(dmg)
	if CLIENT then return end
	local owner = self:GetOwner()
	owner:LagCompensation(true)
	local trace = util.QuickTrace(owner:EyePos(), owner:GetAimVector() * 90, {owner})
	owner:LagCompensation(false)
	local ent = trace.Entity
	if IsValid(ent) and ent.onStunStickUsed then
		ent:onStunStickUsed(owner)
		return
	elseif IsValid(ent) and ent:GetClass() == "func_breakable_surf" then
		ent:Fire("Shatter", util.TypeToString(ent:GetPos()))
		owner:EmitSound(self.Hit[math.random(#self.Hit)])
		return
	end
	self.WaitingForAttackEffect = true
	local ent = owner:getEyeSightHitEntity(
		self.stickRange,
		15,
		fn.FAnd{
			fp{fn.Neq, owner},
			fc{IsValid, entMeta.GetPhysicsObject},
			entMeta.IsSolid
		}
	)
	if !IsValid(ent) then return end
	if ent:IsPlayer() and !ent:Alive() then return end
	if !ent:isDoor() then
		ent:SetVelocity((ent:GetPos() - owner:GetPos()) * 7)
	end
	if ent:IsPlayer() or ent:IsNPC() or ent:IsVehicle() then
		self:DoFlash(ent)
		owner:EmitSound(self.FleshHit[math.random(#self.FleshHit)])
	else
		owner:EmitSound(self.Hit[math.random(#self.Hit)])
		if MG_SeizeReward and MG_SeizeReward.BeginSeizeEntity(owner, ent, dmg) then return end
		if IsValid(ent) then
			local phys = ent:GetPhysicsObject()
			if IsValid(phys) then
				phys:ApplyForceOffset(owner:GetAimVector() * 80 * phys:GetMass(), trace.HitPos)
			end
		end
	end
	if IsValid(ent) and dmg > 0 then
		SuppressHostEvents(NULL)
		ent:TakeDamage(dmg, owner, self)
		SuppressHostEvents(owner)
	end
end

function SWEP:PrimaryAttack()
	BaseClass.PrimaryAttack(self)
	self:SetNextSecondaryFire(self:GetNextPrimaryFire())
	self:DoAttack(0)
end

function SWEP:SecondaryAttack()
	BaseClass.PrimaryAttack(self)
	self:SetNextSecondaryFire(self:GetNextPrimaryFire())
	self:DoAttack(10)
end

function SWEP:Reload()
	self:SetHoldType("melee")
	self:SetHoldTypeChangeTime(CurTime() + 0.1)
	if self:GetLastReload() + 0.1 > CurTime() then self:SetLastReload(CurTime()) return end
	self:SetLastReload(CurTime())
	self:EmitSound("weapons/stunstick/spark"..math.random(1, 3)..".wav")
end