_OpenScript("jbmenu.lua")
_OpenScript("noxspells.lua")
_OpenScript("gamemodes/noxctf/init/luaexplosion.lua")

function eventPlayerChangeTeam(name, userid, new_team, old_team)
	_EntSetName(userid, TeamString(new_team))
end

function onGravGunPickup(player, entity)
	return false
end

function explode(str, seperator, limit)
	local t={}
	local lim=limit or -1
	local reps=0
	local ll=0

	while true do
		local l=string.find(str,seperator,ll+1,true)
		if l~=nil then
			table.insert(t,string.sub(str,ll,l-1))
			ll=l+1
			reps=reps+1
		else
			table.insert(t,string.sub(str,ll))
			reps=reps+1
			break
		end
        if (reps>=lim and lim~=-1) or reps > 4000 then
			table.insert(t,string.sub(str,ll))
			break
		end
	end
	return t
end

function OverDrive()
	_PrintMessageAll(4, "OverDrive")
	for i=1, _MaxPlayers() do
		if IsPlayerOnline(i) then
			_SWEPRunString(_PlayerGetActiveWeapon(i), "OverDrive=true")
			_PlayerSetHealth(i, 1250)
			_EntSetMaxHealth(i, 1250)
		end
	end
end

function StartDragoonTransSequence(userid)
	_PlayerLockInPlace(userid, true)
	_PlayerDisableAttack(userid, true)
	_EntEmitSoundEx(userid, "ambient/energy/whiteflash.wav", 1.0, 1.5)
	AddTimer(0.75, 5, _EntEmitSound, userid, "ambient/energy/zap"..math.random(5,9)..".wav")
	local ent = _EntCreate("env_sprite")
	if ent > 0 then
		_EntSetKeyValue(ent, "model", "sprites/splodesprite.spr")
		_EntSetKeyValue(ent, "rendermode", "5")
		_EntSetKeyValue(ent, "scale", "0.8")
		_EntSetKeyValue(ent, "spawnflags", "1")
		_EntSetPos(ent, _EntGetPos(userid))
		_EntSpawn(ent)
		_EntFire(ent, "showsprite", "", 1)
		_EntFire(ent, "setscale", "0.8", 1.25)
		_EntFire(ent, "setscale", "1.25", 1.5)
		_EntFire(ent, "setscale", "1.55", 1.75)
		_EntFire(ent, "setscale", "2.8", 1.0)
		_EntFire(ent, "setscale", "1.85", 2.5)
		_EntFire(ent, "setscale", "1.25", 3.0)
		_EntFire(ent, "setscale", "0.5", 4.25)
		_EntFire(ent, "hidesprite", "", 5.25)
		_EntFire(ent, "kill", "", 5.5)
	end

	_util.ScreenShake(_EntGetPos(userid), math.random(15,35), 160.0, 3.0, 140)
	AddTimer(5.0, 1, EndDragoonTransSequence, userid)
end

function EndDragoonTransSequence(userid)
	_PlayerLockInPlace(userid, false)
	_PlayerDisableAttack(userid, false)
	_EntEmitSoundEx(userid, "weapons/rpg/rocketfire1.wav", 1.0, 0.8)
	_EntEmitSoundEx(userid, "ambient/explosions/explode_6.wav", 1.0, 1.1)
	_EntSetVelocity(userid, vector3(0,0,0))
end

function GetPlayerDamageScale(hitgroup)
	if hitgroup == HITGROUP_HEAD then
		return 3.0
	end
	return 1.0
end

_ServerCommand("sk_zombie_health 400\n")
_ServerCommand("sk_zombie_dmg_both_slash 50\n")
_ServerCommand("sk_zombie_dmg_one_slash 35\n")

function GiveDefaultItems(userid)
	if _PlayerInfo(userid, "team") == TEAM_SPECTATOR then return end
	_PlayerGiveItem(userid, "weapon_physcannon")
	for i=1, table.getn(Classes[players[userid].Class].SWEPs) do
		_PlayerGiveSWEP(userid, Classes[players[userid].Class].SWEPs[i])
	end
end

function EnergyGrenade(prop, userid)
	AddTimer(2.5, 1, EnergyGrenadeExplode, prop, userid)
end

function EnergyGrenadeExplode(prop, userid)
	local ents = _EntitiesFindInSphere(_EntGetPos(prop), 250)
	for i=1, table.getn(ents) do
		if Vehicles[ents[i]] then
			_TraceAttack(ents[i], userid, userid, 310)
		elseif _EntGetType(ents[i]) == "prop_physics" then
			_TraceAttack(ents[i], userid, userid, 200)
		elseif IsPlayer(ents[i]) then
			_TraceAttack(ents[i], userid, userid, _EntGetMaxHealth(ents[i])*0.75 or 75)
		else
			_TraceAttack(ents[i], userid, userid, 75)
		end
	end
	local exp = _EntCreate("env_ar2explosion")
	if exp > 0 then
		_EntSetPos(exp, vecAdd(_EntGetPos(prop), vector3(0, 0, 50)))
		_EntSpawn(exp)
		_EntFire(exp, "explode", "", 0.1)
		_EntEmitSound(exp, "weapons/physcannon/energy_disintegrate5.wav")
		_EntEmitSound(exp, "weapons/mortar/mortar_explode1.wav")
	end
	_EntRemove(prop)
end

function SummonZombie(prop, userid)
	AddTimer(2.5, 1, DoSummonZombie, prop, userid)
end

function DoSummonZombie(prop, userid)
	local exp2 = _EntCreate("npc_zombie")
	if exp2 > 0 then
		_EntSetPos(exp2, vecAdd(_EntGetPos(prop), vector3(0, 0, 20)))
		_EntSpawn(exp2)
		_EntEmitSound(exp2, "ambient/creatures/town_zombie_call1.wav")
		local n = _PlayerInfo(userid, "team")
		_EntFire(exp2, "color", teams[n].color.r.." "..teams[n].color.g.." "..teams[n].color.b, 0)
		_EntFire(exp2, "sethealth", "250", 0)
	end
	_EntRemove(prop)
end

function Certified(userid, name)
	return string.find(players[userid].Certifications, name) ~= nil
end

function ConvertNet(str)
	if str == "UNKNOWN" or str == "STEAM_ID_PENDING" or str == "STEAM_ID_LAN" then return "admin"
	else
		return string.sub(str, 11)
	end
end

function vecAngAngle(v1)
	return vecMul(vecAdd(v1, vector3(1.0, 1.0, 1.0)), vector3(180,180,180))
end

function eventPlayerSpawn(userid)
	Gibbed[userid] = false
	_PlayerSetDrawViewModel(userid, true)
	_player.ShouldDropWeapon(userid, false)
	_EntSetMaxHealth(userid, Classes[players[userid].Class].Health)
	_PlayerSetHealth(userid, Classes[players[userid].Class].Health)
	_PlayerSetArmor(userid, Classes[players[userid].Class].Armor)
	_EntFire(userid, "color", TeamColor(_PlayerInfo(userid,"team")), 0)
	if Classes[players[userid].Class].Mana then
		_GModRect_Start("gmod/white")
		 _GModRect_SetPos(0.4, 0.95, 0.2, 0.1)
		 _GModRect_SetColor(0, 0, 0, 200)
		 _GModRect_SetTime(9999, 0, 0)
		_GModRect_Send(userid, 1800)
	else
		_GModRect_Hide(userid, 1800, 0, 0)
		_GModRect_Hide(userid, 1801, 0, 0)
	end
end

_GameSetTargetIDRules(TRGTID_TEAMONLY)


function TeamColor(num)
	if num ~= TEAM_SPECTATOR then
		return teams[num].color.r.." "..teams[num].color.g.." "..teams[num].color.b
	else
		return "255 255 255"
	end
end

function eventKeyPressed(userid, in_key)
	if players[userid].Invisible then
		if in_key == IN_ATTACK then
			local unin = false
			if Classes[players[userid].Class].Name == "mage" then
				unin = not _PlayerIsKeyDown(userid, IN_ATTACK2)
			else
				unin = true
			end
			if unin then
				players[userid].Invisible = false
				_EntEmitSound(userid, "nox/invisoff.wav")
				_GModRect_Hide(userid, 9109, 0)
				_EntFire(userid, "alpha", "255", 0)
				_PlayerSetDrawWorldModel(userid, true)
			end
		end
	end
end

function onTakeDamage(ent, inflictor, attacker, damage)
	if IsPlayer(ent) then
		if players[ent].Invisible then
			players[ent].Invisible = false
			_EntFire(ent, "alpha", "255", 0)
			_EntEmitSound(ent, "nox/invisoff.wav")
			_GModRect_Hide(ent, 9109, 0)
			_PlayerSetDrawWorldModel(ent, true)
		end
		if damage >= _PlayerInfo(ent, "health")+30 then
			if _PlayerInfo(ent, "armor") < 10 then
				if IsPlayer(attacker) then
					if _PlayerInfo(attacker, "team") ~= _PlayerInfo(ent, "team") or ent == attacker then
						Gib(ent)
					end
				else
					Gib(ent)
				end
			end
		end
	end
end

function math.frandom(minn, maxn)
	minn = minn * 100
	maxn = maxn * 100
	return math.random(minn, maxn)*0.01
end

function IsInRadius(a, b, dist)
	return math.abs(vecLength(vecSub(_EntGetPos(a),_EntGetPos(b)))) <= dist
end

function TeamString(intt)
	if intt == TEAM_RED then return "Red"
	elseif intt == TEAM_BLUE then return "Blue"
	elseif intt == TEAM_GREEN then return "Green"
	elseif intt == TEAM_YELLOW then return "Yellow"
	else return "Spectator" end
end

function eventPlayerActive(name, userid, steamid)
	_EntSetKeyValue(userid, "rendermode", "1")
end

function CanChangeClass(userid)
	return "yes"
end

function ClassMenu(userid, class)
	local canchange = CanChangeClass(userid)
	if canchange ~= "yes" then
		_PrintMessage(userid, 4, canchange)
		return
	end
	if players[userid].Class == class then
		_PrintMessage(userid, 4, "You are already a "..Classes[class].DisplayName.."!")
	elseif Certified(userid, Classes[class].Name) then
		players[userid].Class = class
		_PlayerRespawn(userid)
		_PrintMessage(userid, 4, "You are now a "..Classes[class].DisplayName.."!")
	elseif players[userid].money >= Classes[class].Value then
		players[userid].money = players[userid].money-Classes[class].Value
		players[userid].Class = class
		players[userid].Certifications = players[userid].Certifications.." "..Classes[class].Name
		SaveInfo(userid)
		_PlayerRespawn(userid)
		_PrintMessage(userid, 4, "You are now a certified "..Classes[class].DisplayName.."!")
		NDB.drawMoneyAmmount(userid)
	else
		_PrintMessage(userid, 4, "You don't have enough cash.")
	end
end

function onShowSpare1(userid)
	local menu = JBMenu.CreateMenu(false, "Class Menu", "", "255 255 255", "255 255 255")
	JBMenu.AddChoice(menu, "Class Catalog", "Purchase certifications.", "0 255 0", BuyClasses, userid)
	JBMenu.AddChoice(menu, "Your Classes", "Certifications you have purchased.", "0 255 0", CurrentClasses, userid)
	JBLastExit[userid] = _CurTime()-1
	JBMenu.SendMenu(userid, menu)
end

function BuyClasses(userid)
	local menu = JBMenu.CreateMenu(false, "Buy Classes", "", "255 255 255", "255 255 255")
	for i=1, table.getn(Classes) do
		if not Certified(userid, Classes[i].Name) then
			if not Classes[i].Hidden then
				if Classes[i].Value > players[userid].money then
					--[[if Classes[i].Requires then
						local hasreq = true
						for _, val in Classes[i].Requires do
							if not Certified(userid, val) then
								hasreq = false
							end
						end
						if hasreq then
							JBMenu.AddChoice(menu, "($"..Classes[i].Value..") "..Classes[i].Level.." "..Classes[i].DisplayName, Classes[i].Desc, "255 0 0", ClassMenu, userid, i)
						end
					else]]if Certified(userid, Classes[i].Name) then
						JBMenu.AddChoice(menu, "($"..Classes[i].Value..") "..Classes[i].DisplayName, Classes[i].Desc, "255 0 0", ClassMenu, userid, i)
					end
				else
					--[[if Classes[i].Requires then
						local hasreq = true
						for _, val in Classes[i].Requires do
							if not Certified(userid, val) then
								hasreq = false
							end
						end
						if hasreq then
							JBMenu.AddChoice(menu, "($"..Classes[i].Value..") (LVL "..Classes[i].Level..") "..Classes[i].DisplayName, Classes[i].Desc, "255 0 0", ClassMenu, userid, i)
						end
					else]]
						JBMenu.AddChoice(menu, "($"..Classes[i].Value..") "..Classes[i].DisplayName, Classes[i].Desc, "0 255 0", ClassMenu, userid, i)
					--end
				end
			end
		end
	end
	JBMenu.AddChoice(menu, "", "<-- Back", "255 255 255", onShowSpare1, userid)
	JBLastExit[userid] = _CurTime()-1
	JBMenu.SendMenu(userid, menu)
end

function CurrentClasses(userid)
	local menu = JBMenu.CreateMenu(false, "Your Classes", "", "255 255 255", "255 255 255")
	for i=1, table.getn(Classes) do
		if Classes[i].Hidden then
			if Certified(userid, Classes[i].Name) then
				JBMenu.AddChoice(menu, "(HIDDEN) (LVL "..Classes[i].Level..") "..Classes[i].DisplayName, Classes[i].Desc, "255 255 0", ClassMenu, userid, i)
			end
		elseif Certified(userid, Classes[i].Name) then
			JBMenu.AddChoice(menu, "(CERTIFIED) (LVL "..Classes[i].Level..") "..Classes[i].DisplayName, Classes[i].Desc, "255 255 255", ClassMenu, userid, i)
		end
	end
	JBMenu.AddChoice(menu, "", "<-- Back", "255 255 255", onShowSpare1, userid)
	JBLastExit[userid] = _CurTime()-1
	JBMenu.SendMenu(userid, menu)
end

ArrowTimers = {}
_EntPrecacheModel( "models/mixerman3d/other/arrow.mdl" )
function CreateArrow(userid, arrowtype)
	if not _PlayerInfo(userid, "alive") or not _PlayerInfo(userid, "connected") then return end
	local Bolt = _EntCreate("prop_physics")
	if Bolt > 0 then
		_EntSetModel(Bolt, "models/mixerman3d/other/arrow.mdl")
		_EntSetPos(Bolt, vecAdd(_PlayerGetShootPos(userid), vecMul(_PlayerGetShootAng(userid),vector3(30,30,30))))
		_EntSetAng(Bolt, _PlayerGetShootAng(userid))
		_EntSetOwner(Bolt, userid)
		_EntSetKeyValue(Bolt, "minhealthdmg", "0.001")
		_EntSetKeyValue(Bolt, "physdamagescale", "57500")
		_EntSpawn(Bolt)
		_phys.ApplyForceCenter(Bolt, vecMul(_PlayerGetShootAng(userid), vector3(250000, 250000, 250000)))
		_EntEmitSound(Bolt, "weapons/crossbow/bolt_fly4.wav")
		--_EntitySetPhysicsAttacker(Bolt, userid)
		_EntFire(Bolt, "kill", "", 10)
		OutputEntity(Bolt, "onhealthchanged", "ArrowHit", 0)
		if arrowtype < 2 then
			_EntSetName(Bolt, "normal")
			AttatchTrail(Bolt, "255 0 0")
		elseif arrowtype < 3 then
			_EntFire(Bolt, "color", "255 25 0", 0)
			_EntSetName(Bolt, "explode")
			local firetrail = _EntCreate("env_fire_trail")
			if firetrail > 0 then
				_EntSetPos(firetrail, _EntGetPos(Bolt))
				_EntSetParent(firetrail, Bolt)
			end
		elseif arrowtype < 4 then
			_EntFire(Bolt, "color", "0 25 255", 0)
			_EntSetName(Bolt, "cold")
			AttatchTrail(Bolt, "0 50 255")
		elseif arrowtype < 5 then
			_EntSetMaterial(Bolt, "gmod/shiny")
			_EntSetName(Bolt, "rope")
			AttatchTrail(Bolt, "255 255 255")
		end
	end
end

_EntPrecacheModel("models/props_wasteland/rockcliff01c.mdl")
function ArrowFreeze(userid)
	AddTimer(3, 1, ArrowUnfreeze, userid)
	_PlayerFreeze(userid, true)
	_EntSetMaterial(userid, "gmod/shiny")
	local ent = _EntCreate("prop_dynamic_override")
	if ent > 0 then
		_EntSetModel(ent, "models/props_wasteland/rockcliff01c.mdl")
		_EntSetKeyValue(ent, "solid", "0")
		_EntSetKeyValue(ent, "rendermode", "1")
		_EntSetPos(ent, vecAdd(_EntGetPos(userid), vector3(0,0,128)))
		_EntSpawn(ent)
		_EntSetParent(ent, userid)
		_EntSetMaterial(ent, "models/props_combine/stasisshield_sheet")
		_EntFire(ent, "alpha", "220", 0)
		_EntFire(ent, "alpha", "210", 2)
		_EntFire(ent, "alpha", "190", 2.1)
		_EntFire(ent, "alpha", "180", 2.2)
		_EntFire(ent, "alpha", "170", 2.3)
		_EntFire(ent, "alpha", "140", 2.4)
		_EntFire(ent, "alpha", "120", 2.5)
		_EntFire(ent, "alpha", "100", 2.6)
		_EntFire(ent, "alpha", "80", 2.7)
		_EntFire(ent, "alpha", "60", 2.8)
		_EntFire(ent, "alpha", "50", 2.9)
		_EntFire(ent, "kill", "", 3.0)
	end
end

function ArrowUnfreeze(userid)
	_PlayerFreeze(userid, false)
	_EntSetMaterial(userid, "")
end

function CreateDynamicDuplicate(prop, parent)
	local ent = _EntCreate("prop_dynamic_override")
	if ent > 0 then
		_EntSetModel(ent, _EntGetModel(prop))
		_EntSetPos(ent, _EntGetPos(prop))
		_EntSetAng(ent, _EntGetAng(prop))
		_EntSpawn(ent)
		_EntFire(ent, "kill", "", 4)
		if parent then
			_EntSetParent(ent, parent)
			_EntEmitSound(ent, "weapons/crossbow/hitbod"..math.random(1,2)..".wav")
		end
		return ent
	end
	return 0
end

function IsWorld(index)
	return index == 0 or string.find(_EntGetType(index), "func_") ~= nil
end

MakeFunction("ArrowHit")
function ArrowHit(Activator, Caller)
	local arrowtype = _EntGetName(Caller)
	local userid = _EntGetOwner(Caller)
	if arrowtype == "normal" then
		if IsWorld(Activator) then
			_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, Caller)
			if _TraceHitWorld() then
				local dup = CreateDynamicDuplicate(Caller)
				if dup > 0 then
					_EntSetPos(dup, _TraceEndPos())
					_EntEmitSound(dup, "physics/metal/sawblade_stick"..math.random(1,3)..".wav")
				end
				_EntRemove(Caller)
			end
		else
			_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, Caller)
			if _TraceHitWorld() then return end
			_TraceAttack(Activator, userid, userid, math.random(20, 32))
			if _EntGetType(Activator) == "player" then
				_EntEmitSound(Activator, "weapons/crossbow/hitbod"..math.random(1,2)..".wav")
				_EntEmitSoundEx(Activator, "player/pl_pain5.wav", 1.1, 1)
			end
			local dup = CreateDynamicDuplicate(Caller, Activator)
			--_EntSetPos(dup, _TraceEndPos())
			_EntFire(Caller, "kill", "", 0)
		end
	elseif arrowtype == "cold" then
		if IsWorld(Activator) then
			_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, Caller)
			if _TraceHitWorld() then
				local dup = CreateDynamicDuplicate(Caller)
				if dup > 0 then
					_EntSetPos(dup, _TraceEndPos())
					_EntFire(dup, "Color", "0 0 255", 0)
					_EntEmitSound(dup, "physics/metal/sawblade_stick"..math.random(1,3)..".wav")
				end
				_EntRemove(Caller)
			end
		else
			_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, Caller)
			if _TraceHitWorld() then return end
			if _EntGetType(Activator) == "player" then
				_EntEmitSound(Activator, "weapons/crossbow/hitbod"..math.random(1,2)..".wav")
				if _PlayerInfo(Activator,"team") ~= _PlayerInfo(userid,"team") then
					_EntEmitSoundEx(Activator, "ambient/creatures/town_muffled_cry1.wav", 1, 0.7)
					ArrowFreeze(Activator)
				end
			end
			local dup = CreateDynamicDuplicate(Caller, Activator)
			--_EntSetPos(dup, _TraceEndPos())
			_EntFire(dup, "Color", "0 0 255", 0)
			_EntFire(Caller, "kill", "", 0)
		end
	elseif arrowtype == "explode" then
		if not IsWorld(Activator) then
			_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, Caller)
			if _TraceHitWorld() then return end
			_EntEmitSound(Activator, "weapons/crossbow/hitbod"..math.random(1,2)..".wav")
		end
		ArrowExplode(Caller, userid)
	elseif arrowtype == "rope" then
		local ent = _EntCreate("prop_dynamic_override")
		if ent > 0 then
			_EntSetModel(ent, _EntGetModel(Caller))
			_EntSetPos(ent, _EntGetPos(Caller))
			_EntSetAng(ent, _EntGetAng(Caller))
			_EntSpawn(ent)
			_EntSetMaterial(ent, "gmod/shiny")
			_EntFire(ent, "kill", "", 5)
			_EntSetName(ent, "rope")
			if not IsWorld(Activator) then
				ArrowTimers[ent] = AddTimer(0.05, 98, DoHook, userid, ent)
				_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, {Caller, ent})
				_EntSetParent(ent, Activator)
				--_EntSetPos(ent, _TraceEndPos())
				_EntEmitSound(Activator, "weapons/crossbow/hitbod"..math.random(1,2)..".wav")
			else
				_TraceLine(_EntGetPos(Caller), _EntGetAng(Caller), 32, Caller)
				if _TraceDidHitSky() ~= 4 then
					ArrowTimers[ent] = AddTimer(0.05, 98, DoHook, userid, ent)
					_EntSetPos(ent, _TraceEndPos())
					_EntEmitSound(ent, "physics/metal/sawblade_stick"..math.random(1,3)..".wav")
				end
			end
		end
		_EntFire(Caller, "kill", "", 0)
	end
end

function DoHook(userid, prop)
	if _EntGetType(prop) ~= "prop_dynamic" or not _PlayerInfo(userid, "alive") then HaltTimer(ArrowTimers[prop]) ArrowTimers[prop] = nil return end
	if _PlayerIsKeyDown(userid, IN_ATTACK2) then
		_EntSetVelocity(userid, vecAdd(_EntGetVelocity(userid), vecMul(vecNormalize(vecSub(_EntGetPos(prop), _EntGetPos(userid))),vector3(75,75,75))))
	end
	_EffectInit()
	 _EffectSetEnt(userid)
	 _EffectSetOrigin(_EntGetPos(prop))
	 _EffectSetStart(_PlayerGetShootPos(userid))
	 _EffectSetScale(4)
	 _EffectSetMagnitude(1)
	 _EffectSetRadius(70)
	_EffectDispatch("FadingLineTeam")
end

function ArrowExplode(prop, userid)
	local ents = _EntitiesFindInSphere(_EntGetPos(prop), 165)
	for i=1, table.getn(ents) do
		if _phys.HasPhysics(ents[i]) and ents[i] ~= prop then
			_TraceAttack(ents[i], userid, userid, (90-(math.abs(vecLength(vecSub(_EntGetPos(prop),_EntGetPos(ents[i])))))*0.4)*0.65)
		end
	end
	local exp = _EntCreate("env_explosion")
	if exp > 0 then
		_EntSetKeyValue(exp, "spawnflags", "17")
		_EntSetPos(exp, _EntGetPos(prop))
		_EntSpawn(exp)
		_EntFire(exp, "explode", "", 0)
		_EntFire(exp, "kill", "", 0.1)
	end
	_util.ScreenShake(_EntGetPos(prop), math.random(15,35), 160.0, 1.15, 140)
	if _EntGetType(prop) == "prop_physics" then
		_EntRemove(prop)
	end
end

function DamagelessExplosion(targ, tim)
	local ent = _EntCreate("env_explosion")
	if ent > 0 then
		_EntSetPos(ent, _EntGetPos(targ))
		_EntSetKeyValue(ent, "spawnflags", "65")
		_EntSpawn(ent)
		_EntFire(ent, "explode", "", tim)
		_EntFire(ent, "kill", "", tim+0.05)
	end
end

function explode(str, seperator, limit)
	local t={}
	local lim=limit or -1
	local reps=0
	local ll=0

	while true do
		local l=string.find(str,seperator,ll+1,true)
		if l~=nil then
			table.insert(t,string.sub(str,ll,l-1))
			ll=l+1
			reps=reps+1
		else
			table.insert(t,string.sub(str,ll))
			reps=reps+1
			break
		end
        if (reps>=lim and lim~=-1) or reps > 4000 then
			table.insert(t,string.sub(str,ll))
			break
		end
	end
	return t
end

function FlagHit(Activator, Caller, Num)
	-- Obsolete, but can prevent console errors.
end

TorsoModels = {}
TorsoModels[1] = "models/Zombie/Classic_torso.mdl"
TorsoModels[2] = "models/Humans/Charple03.mdl"
_EntPrecacheModel("models/Zombie/Classic_torso.mdl")
_EntPrecacheModel("models/Humans/Charple03.mdl")

LegModels = {}
LegModels[1] = "models/Zombie/Classic_legs.mdl"
LegModels[2] = "models/Gibs/Fast_Zombie_Legs.mdl"
_EntPrecacheModel("models/Zombie/Classic_legs.mdl")
_EntPrecacheModel("models/Gibs/Fast_Zombie_Legs.mdl")

GibModels = {}
GibModels[1]="models/Gibs/Antlion_gib_medium_1.mdl"
GibModels[2]="models/Gibs/Antlion_gib_small_1.mdl"
GibModels[3]="models/Gibs/Antlion_gib_medium_2.mdl"
GibModels[4]="models/Gibs/Antlion_gib_medium_3.mdl"
GibModels[5]="models/Gibs/Antlion_gib_small_1.mdl"
GibModels[6]="models/Gibs/Antlion_gib_small_2.mdl"

_EntPrecacheModel("models/Gibs/Antlion_gib_medium_1.mdl")
_EntPrecacheModel("models/Gibs/Antlion_gib_small_1.mdl")
_EntPrecacheModel("models/Gibs/Antlion_gib_medium_2.mdl")
_EntPrecacheModel("models/Gibs/Antlion_gib_medium_3.mdl")
_EntPrecacheModel("models/Gibs/Antlion_gib_small_1.mdl")
_EntPrecacheModel("models/Gibs/Antlion_gib_small_2.mdl")
_EntPrecacheModel("models/gibs/HGIBS.mdl")
_EntPrecacheModel("models/gibs/HGIBS_rib.mdl")
_EntPrecacheModel("models/gibs/HGIBS_rib.mdl")
_EntPrecacheModel("models/gibs/HGIBS_rib.mdl")
_EntPrecacheModel("models/gibs/HGIBS_scapula.mdl")
_EntPrecacheModel("models/gibs/HGIBS_spine.mdl")

Gibbed = {}
for i=1, _MaxPlayers() do
	Gibbed[i] = false
end

function Gib(killed)
	if Gibbed[killed] then return end
	Gibbed[killed] = true
	_TraceLine(_EntGetPos(killed), vector3(0,0,-1), 100, killed)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
	end
	local velocity = vecLength(_EntGetVelocity(killed)) + 30
	Gibbed[killed] = true
	local ent = _EntCreate("env_shooter")
	if ent > 0 then
		_EntSetPos(ent, _EntGetPos(killed))
		_EntSetKeyValue(ent, "m_iGibs", "1")
		_EntSetKeyValue(ent, "m_flVelocity", velocity)
		_EntSetKeyValue(ent, "shootmodel", LegModels[math.random(1,2)])
		_EntSetKeyValue(ent, "m_flVariance", "5.0")
		_EntSetKeyValue(ent, "simulation", "2")
		_EntSpawn(ent)
		_EntFire(ent, "shoot", "", 0)
		_EntFire(ent, "kill", "", 1)
	end
	local ent = _EntCreate("env_shooter")
	if ent > 0 then
		_EntSetPos(ent, _EntGetPos(killed))
		_EntSetKeyValue(ent, "m_iGibs", "1")
		_EntSetKeyValue(ent, "m_flVelocity", velocity)
		_EntSetKeyValue(ent, "shootmodel", TorsoModels[math.random(1,2)])
		_EntSetKeyValue(ent, "m_flVariance", "5.0")
		_EntSetKeyValue(ent, "simulation", "2")
		_EntSpawn(ent)
		_EntFire(ent, "shoot", "", 0)
		_EntFire(ent, "kill", "", 1)
	end
	_EffectInit()
	_EffectSetOrigin(_EntGetPos(killed))
	_EffectSetScale(8)
	_EffectSetFlags(9)
	_EffectDispatch("bloodspray")
	_EffectDispatch("bloodspray")
	_EffectDispatch("bloodspray")
	local gibstospawn = {}
	for i=1, 3 do
		 gibstospawn[table.getn(gibstospawn)+1] = GibModels[math.random(1, table.getn(GibModels))]
	end
	for i in gibstospawn do
		local gib = _EntCreate("prop_physics")
		if gib > 0 then
			_EntSetModel(gib, gibstospawn[i])
			_EntSetKeyValue(gib, "spawnflags", "4")
			_EntSetPos(gib, vecAdd(_EntGetPos(killed), vector3(math.random(-10,10),math.random(-10,10),math.random(10,30))))
			_EntSetAngAngle(gib, vector3(math.random(0,359), math.random(0,359), math.random(0,359)))
			_EntSetKeyValue(gib, "physdamagescale", "1500")
			_EntSpawn(gib)
			_EntFire(gib, "AddOutput", "onhealthchanged GibHitWall,RunScript,,0,3", 0)
			_phys.ApplyForceCenter(gib, vecAdd(vecMul(_EntGetVelocity(killed), 12), vector3(math.random(-2000, 2000), math.random(-2000, 2000), math.random(0, 2000))))
			_phys.ApplyTorqueCenter(gib, vector3(math.random(-10500, 10500), math.random(-10500, 10500), math.random(-3000, 13000)))
			_EntFire(gib, "kill", "", 7.5)
			local trail = _EntCreate("env_smoketrail")
			if trail > 0 then
				_EntSetPos(trail, _EntGetPos(gib))
				_EntSetKeyValue(trail, "spawnrate", "22")
				_EntSetKeyValue(trail, "lifetime", "1.2")
				_EntSetKeyValue(trail, "startcolor", "255 0 0")
				_EntSetKeyValue(trail, "endcolor", "255 0 0")
				_EntSetKeyValue(trail, "minspeed", "0")
				_EntSetKeyValue(trail, "maxspeed", "0")
				_EntSetKeyValue(trail, "startsize", "6")
				_EntSetKeyValue(trail, "endsize", "9")
				_EntSetKeyValue(trail, "spawnradius", "2")
				_EntSetKeyValue(trail, "firesprite", "sprites/redglow3.spr")
				_EntSetKeyValue(trail, "smokesprite", "sprites/redglow3.spr")
				_EntSpawn(trail)
				_EntSetParent(trail, gib)
				_EntFire(trail, "kill", "", 4.0)
			end
		end
	end
	_EntEmitSoundEx(killed, "physics/flesh/flesh_bloody_break.wav", 1.0, 0.75)
	AddTimer(0.1, 1, _PlayerSilentKill, killed, 1.5, true)
end

function GibHitWall(hit, gib)
	_TraceLine(_EntGetPos(gib), vector3(0,0,-1), 32, gib)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
		_EffectInit()
		 _EffectSetOrigin(_EntGetPos(gib))
		 _EffectSetNormal(vector3(0,0,1))
		 _EffectSetScale(7)
		 _EffectSetFlags(9)
		_EffectDispatch("bloodspray")
		_EffectDispatch("bloodspray")
	end
	_TraceLine(_EntGetPos(gib), vector3(0,0,1), 32, gib)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
		_EffectInit()
		 _EffectSetOrigin(_EntGetPos(gib))
		 _EffectSetNormal(vector3(0,0,-1))
		 _EffectSetScale(7)
		 _EffectSetFlags(9)
		_EffectDispatch("bloodspray")
		_EffectDispatch("bloodspray")
	end
	_TraceLine(_EntGetPos(gib), vector3(1,0,0), 32, gib)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
		_EffectInit()
		 _EffectSetOrigin(_EntGetPos(gib))
		 _EffectSetNormal(vector3(-1,0,0))
		 _EffectSetScale(7)
		 _EffectSetFlags(9)
		_EffectDispatch("bloodspray")
		_EffectDispatch("bloodspray")
	end
	_TraceLine(_EntGetPos(gib), vector3(-1,0,0), 32, gib)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
		_EffectInit()
		 _EffectSetOrigin(_EntGetPos(gib))
		 _EffectSetNormal(vector3(1,0,0))
		 _EffectSetScale(7)
		 _EffectSetFlags(9)
		_EffectDispatch("bloodspray")
		_EffectDispatch("bloodspray")
	end
	_TraceLine(_EntGetPos(gib), vector3(0,1,0), 32, gib)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
		_EffectInit()
		 _EffectSetOrigin(_EntGetPos(gib))
		 _EffectSetNormal(vector3(0,-1,0))
		 _EffectSetScale(7)
		 _EffectSetFlags(9)
		_EffectDispatch("bloodspray")
		_EffectDispatch("bloodspray")
	end
	_TraceLine(_EntGetPos(gib), vector3(0,-1,0), 32, gib)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
		_EffectInit()
		 _EffectSetOrigin(_EntGetPos(gib))
		 _EffectSetNormal(vector3(0,1,0))
		 _EffectSetScale(7)
		 _EffectSetFlags(9)
		_EffectDispatch("bloodspray")
		_EffectDispatch("bloodspray")
	end
	_EntEmitSound(gib, "physics/flesh/flesh_bloody_impact_hard1.wav")
end
MakeFunction("GibHitWall")

function DoExplode(Owner)
	if not _PlayerInfo(Owner, "alive") then return end
	_EntEmitSoundEx(Owner, "ambient/explosions/explode_"..math.random(1,9)..".wav", 1.5, 0.9)
	_EntEmitSoundEx(Owner, "ambient/explosions/explode_"..math.random(1,9)..".wav", 1.0, 1.1)
	_util.ScreenShake(_EntGetPos(Owner), 50, 475, 3, 550)
	local ents = _EntitiesFindInSphere(_EntGetPos(Owner), 330)
	local damage = 0
	for i=1, table.getn(ents) do
		if _phys.HasPhysics(ents[i]) then
			if IsPlayer(ents[i]) then
				if _PlayerInfo(ents[i], "connected") then
					if _PlayerInfo(ents[i], "team") ~= _PlayerInfo(Owner, "team") then
						_EntSetVelocity(ents[i], vecAdd(vector3(math.random(-1000, 1000), math.random(-1000, 1000), math.random(500, 1500)), _EntGetVelocity(ents[i])))
					end
					damage = 355-(math.abs(vecLength(vecSub(_EntGetPos(Owner),_EntGetPos(ents[i])))))
					if damage >= _PlayerInfo(ents[i], "health") then damage = 2000 end
					_RunString("_TraceAttack("..ents[i]..", "..Owner..", "..Owner..", "..damage..")")
				end
			else
				damage = 355-(math.abs(vecLength(vecSub(_EntGetPos(Owner),_EntGetPos(ents[i])))))
				_RunString("_TraceAttack("..ents[i]..", "..Owner..", "..Owner..", "..damage..")")
			end
		end
	end
	local x = -90
	local y = -90
	local ent = 0
	for i=1, 3 do
		if x ~= 0 then
			ent = 0
			ent = _EntCreate("env_explosion")
			if ent > 0 then
				_EntSetPos(ent, vecAdd(vector3(x, 0, 0), _EntGetPos(Owner)))
				_EntSetKeyValue(ent, "spawnflags", "65")
				_EntSpawn(ent)
				_EntFire(ent, "explode", "", 0)
				_EntFire(ent, "kill", "", 0.15)
			end
		end
		x = x + 90
	end
	for ii=1, 3 do
		if y ~= 0 then
			ent = 0
			ent = _EntCreate("env_explosion")
			if ent > 0 then
				_EntSetPos(ent, vecAdd(vector3(0, y, 0), _EntGetPos(Owner)))
				_EntSetKeyValue(ent, "spawnflags", "65")
				_EntSpawn(ent)
				_EntFire(ent, "explode", "", 0)
				_EntFire(ent, "kill", "", 0.15)
			end
		end
		y = y + 90
	end
	Gib(Owner)
end

Cannons = {}
MiniCannons = {}
function JuggernautCannon(userid)
	_EntEmitSound(userid, "weapons/stinger_fire1.wav")
	_EntEmitSound(userid, "weapons/rpg/rocketfire1.wav")
	local i = table.getn(Cannons)+1
	Cannons[i] = {}
	Cannons[i].pos = _PlayerGetShootPos(userid)
	Cannons[i].ang = _PlayerGetShootAng(userid)
	Cannons[i].owner = userid
end

function JuggernautMiniCannon(userid)
	_EntEmitSound(userid, "weapons/stinger_fire1.wav")
	local i = table.getn(MiniCannons)+1
	MiniCannons[i] = {}
	MiniCannons[i].pos = _PlayerGetShootPos(userid)
	MiniCannons[i].ang = _PlayerGetShootAng(userid)
	MiniCannons[i].owner = userid
end

function CannonsTick()
	MiniCannonsTick()
	for i in Cannons do
		_TraceLine(Cannons[i].pos, Cannons[i].ang, 99999, Cannons[i].owner)
		if not _TraceHit() then
			Cannons[i] = nil
		else
			_TraceLine(Cannons[i].pos, Cannons[i].ang, 180, Cannons[i].owner)
			if _TraceHit() then
				Cannons[i].pos = _TraceEndPos()
				local ents = _EntitiesFindInSphere(Cannons[i].pos, 275)
				for x=1, table.getn(ents) do
					if _phys.HasPhysics(ents[x]) then
						_TraceAttack(ents[x], Cannons[i].owner, Cannons[i].owner, (280 - Distance(Cannons[i].pos,_EntGetPos(ents[x]))) * 0.35, "antivehicle")
					end
				end
				NoDamageLuaExplosion(Cannons[i].pos)
				AR2Explosion(Cannons[i].pos)
				Cannons[i] = nil
			else
				local ents = _EntitiesFindInSphere(Cannons[i].pos, 140)
				for x in ents do
					if ents[x] ~= Cannons[i].owner and not Vehicles[ents[x]] then
						_TraceAttack(ents[x], Cannons[i].owner, Cannons[i].owner, (145-Distance(Cannons[i].pos, _EntGetPos(ents[i])))*0.2)
					end
				end
				local ent = _EntCreate("env_sprite")
				if ent > 0 then
					_EntSetKeyValue(ent, "model", "sprites/muzzleflash"..math.random(1,3)..".spr")
					_EntSetKeyValue(ent, "rendermode", "5")
					_EntSetKeyValue(ent, "scale", "1.0")
					_EntSetKeyValue(ent, "spawnflags", "1")
					_EntSetPos(ent, Cannons[i].pos)
					_EntSpawn(ent)
					_EntFire(ent, "showsprite", "", 0)
					_EntFire(ent, "setscale", "0.85", 0.25)
					_EntFire(ent, "setscale", "0.55", 0.5)
					_EntFire(ent, "setscale", "0.15", 0.75)
					_EntFire(ent, "hidesprite", "", 0.9)
					_EntFire(ent, "kill", "", 1.0)
					_EntEmitSoundEx(ent, "weapons/explode"..math.random(3,5)..".wav", 1, 1.45)
				end
				--Cannons[i].ang = vecAdd(Cannons[i].ang, vector3(math.frandom(-0.06, 0.06), math.frandom(-0.06, 0.06), math.frandom(-0.06, 0.06)))
				Cannons[i].pos = vecAdd(Cannons[i].pos, vecMul(Cannons[i].ang, vector3(175,175,175)))
				if Cannons[i].ang.z > -0.75 then
					Cannons[i].ang.z = Cannons[i].ang.z - 0.025
				end
			end
		end
	end
end
AddTimer(0.12, 0, CannonsTick)

function MiniCannonsTick()
	for i in MiniCannons do
		_TraceLine(MiniCannons[i].pos, MiniCannons[i].ang, 99999, MiniCannons[i].owner)
		if not _TraceHit() then
			MiniCannons[i] = nil
		else
			_TraceLine(MiniCannons[i].pos, MiniCannons[i].ang, 200, MiniCannons[i].owner)
			if _TraceHit() then
				MiniCannons[i].pos = _TraceEndPos()
				local ents = _EntitiesFindInSphere(MiniCannons[i].pos, 160)
				for x=1, table.getn(ents) do
					if _phys.HasPhysics(ents[x]) then
						_TraceAttack(ents[x], MiniCannons[i].owner, MiniCannons[i].owner, (165 - Distance(MiniCannons[i].pos,_EntGetPos(ents[x]))) * 0.23, "antivehicle")
					end
				end
				local exp = _EntCreate("env_explosion")
				if exp > 0 then
					_EntSetKeyValue(exp, "spawnflags", "17")
					_EntSetPos(exp, MiniCannons[i].pos)
					_EntSpawn(exp)
					_EntFire(exp, "explode", "", 0)
					_EntFire(exp, "kill", "", 0.1)
				end
				MiniCannons[i] = nil
			else
				local ent = _EntCreate("env_sprite")
				if ent > 0 then
					_EntSetKeyValue(ent, "model", "sprites/muzzleflash"..math.random(1,3)..".spr")
					_EntSetKeyValue(ent, "rendermode", "5")
					_EntSetKeyValue(ent, "scale", "0.32")
					_EntSetKeyValue(ent, "spawnflags", "1")
					_EntSetPos(ent, MiniCannons[i].pos)
					_EntSpawn(ent)
					_EntFire(ent, "showsprite", "", 0)
					_EntFire(ent, "setscale", "0.3", 0.25)
					_EntFire(ent, "setscale", "0.26", 0.5)
					_EntFire(ent, "setscale", "0.23", 0.75)
					_EntFire(ent, "hidesprite", "", 0.9)
					_EntFire(ent, "kill", "", 1.0)
					if math.random(1, 3) ~= 1 then
						_EntEmitSoundEx(ent, "weapons/explode"..math.random(3,5)..".wav", 1, 1.45)
					end
				end
				--MiniCannons[i].ang = vecAdd(MiniCannons[i].ang, vector3(math.frandom(-0.06, 0.06), math.frandom(-0.06, 0.06), math.frandom(-0.06, 0.06)))
				MiniCannons[i].pos = vecAdd(MiniCannons[i].pos, vecMul(MiniCannons[i].ang, vector3(195,195,195)))
				MiniCannons[i].ang = vecAdd(MiniCannons[i].ang, vector3(math.frandom(-0.03, 0.03), math.frandom(-0.03, 0.03), math.frandom(-0.03, 0.03)))
				MiniCannons[i].ang = vecNormalize(MiniCannons[i].ang)
			end
		end
	end
end
