
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include( 'shared.lua' )

ENT.model = "models/buildables/teleporter_light.mdl"

ENT.health = 150
ENT.AutomaticFrameAdvance = true 

function ENT:SpawnFunction( ply, tr )
	if ( !tr.Hit or (ply.tp_exit and ValidEntity(ply.tp_exit)) ) then return end
	local SpawnPos = (tr.HitPos + tr.HitNormal * 16) -Vector( 0, 0, 17 )
	self.Spawn_angles = ply:GetAngles()
	self.Spawn_angles.pitch = 0
	self.Spawn_angles.roll = 0
	self.Spawn_angles.yaw = self.Spawn_angles.yaw + 180
	
	local ent = ents.Create( "obj_teleporter_exit" )
	ent:SetPos( SpawnPos )
	ent:SetAngles( self.Spawn_angles )
	ent.owner = ply
	ent:SetNetworkedEntity( "owner", ent.owner )
	ent.built = true
	ent.sb_spawn = true
	ent:SetModel( "models/buildables/teleporter.mdl" )
	ent.settingup = true
	ply:SetNetworkedEntity( "tp_exit", ent )
	ply.tp_exit = ent
	ent:Spawn()
	ent:Activate()
	
	return ent
end

function ENT:KeyValue( key, value )
	if( key == "TeamNum" ) then
		if value == "3" then
			self.team = 1
		else
			self.team = 2
		end
		self.built = true
		self.mapentity = true
		self.settingup = true
		self.sb_spawn = true
		self:SetModel( "models/buildables/teleporter.mdl" )
	end
	if( key == "health" ) then
		self.health = value
	end
	if( key == "spawnflags" ) then
		self.spawnflags = tonumber(value)
		self:CheckSpawnflags()
	end
end

function ENT:CheckSpawnflags()
	local spawnflags = { 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 }
	for k, v in pairs( spawnflags ) do
		if v <= self.spawnflags and !self.used then
			local value_a = v
			local value_b = self.spawnflags -v
			if table.HasValue( spawnflags, value_a ) then
				self:GetSpawnflag( value_a )
			end
			if self.spawnflags != v then
				if table.HasValue( spawnflags, value_b ) then
					self.used = true
					self:GetSpawnflag( value_b )
				else
					self.spawnflags = value_b
					self.used = false
					self:CheckSpawnflags()
				end
			else
				self.used = true
			end
		end
	end
end

function ENT:GetSpawnflag( value )
	local spawnflags = { 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 }
	if !table.HasValue( spawnflags, value ) then return false end
	if value == 2 then
		self.invulnerable = true
	end
	return true
end

function ENT:Initialize()
	if !self.sb_spawn then self:SetModel( self.model ) end
	self:SetMoveType( MOVETYPE_NONE )
	self:SetSolid( SOLID_BBOX )
	self:SetHealth(self.health)
	self:SetMaxHealth(self.health)
	self:SetCollisionBounds( Vector( -20, 22, 0 ), Vector( 20, -22, 12 ) )	
	
	self.idlesound = CreateSound( self, "weapons/teleporter_spin.wav" )
	if self.mapentity then self.idlesound:Play() end
	if !self.team then
		if self.owner and ValidEntity(self.owner) then
			self.team = self.owner:Team()
		else
			self.team = 0
		end
	end
	if self.team == 1 then
		self:SetSkin(1)
		self.teleporteffect = "blue"
	else
		self.teleporteffect = "red"
	end
	
	self.idle_effect = ents.Create( "info_particle_system" )
	self.idle_effect:SetKeyValue( "effect_name", "teleporter_" .. self.teleporteffect .. "_exit" )
	self.idle_effect:SetPos( self:GetPos() )
	self.idle_effect:SetParent( self )
	self.idle_effect:Spawn()
	self.idle_effect:Activate()
	self.idle_effect:Fire( "SetParentAttachment", "centre_attach", 0 )
	
	self.teleport_effect = ents.Create( "info_particle_system" )
	self.teleport_effect:SetKeyValue( "effect_name", "teleportedin_" .. self.teleporteffect )
	self.teleport_effect:SetPos( self:GetPos() )
	self.teleport_effect:SetParent( self )
	self.teleport_effect:Spawn()
	self.teleport_effect:Activate()
	self.teleport_effect:Fire( "SetParentAttachment", "centre_attach", 0 )

	self:SetUp()
	self:SetNetworkedInt( "health", self:Health() )
end

function ENT:SetUp()
	if self.built then self.setupdelay = 0; return end
	self:SetModel( "models/buildables/teleporter.mdl" )
	self:ResetSequence( self:LookupSequence( "build" ) )
	self:SetPlaybackRate( 0.5 )
	
	self.settingup = true
	self.setupdelay = CurTime() +self:SequenceDuration() *2
	self.totalseqduration = self:SequenceDuration() *2
end

function ENT:SpeedUp()
	timer.Destroy( tostring(self) .. "_speeduptimer" )
	self:SetPlaybackRate( 1 )
	local buildtime = (self:SequenceDuration() *2 -(self.setupdelay -CurTime())) /2
	self.setupdelay = CurTime() +(self:SequenceDuration() -buildtime)
	self.totalseqduration = self:SequenceDuration()
	self.speedup = true
	
	local function SpeedDown()
		if !self or !ValidEntity(self) or self.built then return end
		self:SetPlaybackRate( 0.5 )
		local buildtime = (self:SequenceDuration() -(self.setupdelay -CurTime())) *2
		self.setupdelay = CurTime() +(self:SequenceDuration() *2 -buildtime)
		self.totalseqduration = self:SequenceDuration() *2
		self.speedup = false
	end
	timer.Create( tostring(self) .. "_speeduptimer", 1, 1, SpeedDown )
end

function ENT:Sap()
	self.sapper:SetParent( self )
	self.sapper:Fire( "SetParentAttachment", "build_point_0", 0 )
	self.sapper:SetModel( "models/buildables/sapper_teleporter.mdl" )
	
	self.sapped = true
	self:SetNetworkedBool("sapped", true)
	
	if self.owner and ValidEntity( self.owner ) and self.owner:Health() > 0 then
		self.owner:EmitSound( "vo/engineer_autoattackedbyspy01.wav", 100, 100 )
	end
	
	self.idlesound:Stop()
	
	self:SetNetworkedInt( "health", self:Health() )
end

function ENT:Ready()
	self.idle_effect:Fire( "Start", "", 0 )
	self:SetBodygroup( 1,1 )
end

function ENT:Think()
	self:NextThink( CurTime() +0.1 )
	if self.recharge and self.recharge < 100 and !timer.IsTimer("RechargeTimer" .. self:EntIndex()) then
		timer.Create( "RechargeTimer" .. self:EntIndex(), 0.05, 0, function()
		if self and ValidEntity(self) then
			self.recharge = self.recharge +1;
			self:SetNetworkedInt( "recharge", self.recharge )
			if self.recharge == 40 then self.spinup = true end;
			if self.recharge == 100 then timer.Destroy( "RechargeTimer" .. self:EntIndex() ) end;
		else
			timer.Destroy( "RechargeTimer" .. self:EntIndex() )
		end
		end)
	elseif self.recharge == 100 then
		self:EmitSound( "weapons/teleporter_ready.wav", 100, 100 )
		self.recharge = false
		self.rechargedelay = nil
	end

	if self.speeddelay and CurTime() > self.speeddelay then
		if !self.spinup then
			if self.playbackrate > 0 then
				self.speeddelay = CurTime() +0.3
				self:SetPlaybackRate( self.playbackrate )
				self.idlesound:ChangePitch( 100 -self.pitchrate )
				if tostring(self.playbackrate) == "0.1" then self.idlesound:FadeOut( 1.8 ) end
				self.playbackrate = self.playbackrate -0.05
				self.pitchrate = self.pitchrate +6
				if tostring(self.playbackrate) == "0.45" then self:SetBodygroup( 1,0 ) end
			else
				self.pitchrate = nil
				self.playbackrate = nil
				self.speeddelay = nil
			end
		else
			if self.playbackrate < 0.6 then
				self.speeddelay = CurTime() +0.3
				self:SetPlaybackRate( self.playbackrate )
				self.idlesound:ChangePitch( 100 -self.pitchrate )
				if tostring(self.playbackrate) == "0.1" then self.idlesound:FadeOut( 1.8 ) end
				self.playbackrate = self.playbackrate +0.05
				self.pitchrate = self.pitchrate -6
				if tostring(self.playbackrate) == "0.5" then self:SetBodygroup( 1,1 ) end
			else
				self.spinup = nil
				self.pitchrate = nil
				self.playbackrate = nil
				self.speeddelay = nil
			end
		end
	end

	if self.setupdelay then
		if CurTime() > self.setupdelay then
			self:SetModel( self.model )
			self.setupdelay = nil
			self.settingup = false
			self:ResetSequence( self:LookupSequence( "running" ) )
			self:SetPlaybackRate( 0 )
			self.built = true
			self:SetNetworkedBool("building", false)
			if self:Health() >= 145 then self:SetHealth(150);self:SetNetworkedInt("health",150) end
		else
			self:SetHealth(((self.totalseqduration -(self.setupdelay -CurTime())) /self.totalseqduration) *self.health)
			self:SetNetworkedInt("health", self:Health())
		end
	end
	
	if !self.built then return true end
	if !self.gotentrance and ((self.owner and self.owner.tp_entrance and self.owner.tp_entrance.built and !self.owner.tp_entrance.sapped) or (self.tp_entrance and !self.tp_entrance.sapped)) then
		if !self.tp_entrance then
			self.tp_entrance = self.owner.tp_entrance
		end
		self.gotentrance = true
		self:SetNetworkedBool( "gotentrance", true )
		self:EmitSound( "weapons/teleporter_ready.wav", 100, 100 )
		self.idlesound:Play()
		self:ResetSequence( self:LookupSequence( "running" ) )
		self:SetPlaybackRate( 0.6 )
		self:Ready()
	end

	if self.gotentrance and ( !ValidEntity( self.tp_entrance ) or self.tp_entrance:Health() <= 0 or self.tp_entrance.sapped or self.sapped ) then
		self.gotentrance = false
		self:SetNetworkedBool( "gotentrance", false )
		self.playbackrate = 0.5
		self.pitchrate = 6
		self.speeddelay = CurTime() +0.3
		self.idle_effect:Fire( "Stop", "", 0 )
	end

	if self.tele_target and self.tele_target.teleport_effect and ValidEntity( self.tele_target.teleport_effect ) then
		if !ValidEntity(self.tele_target) or self.tele_target:Health() < 0 then
			target.teleport_effect:Remove()
			self.tele_target = nil
		end
	end
	return true
end

function ENT:DamageLevel(dmglvl)
	if self.dmgparticle and self.dmgparticle.lvl == dmglvl then return false end
	if self.dmgparticle and self.dmgparticle.lvl > dmglvl then self.dmgparticle:Remove(); self.dmgparticle = nil; return false end
	if self.dmgparticle and ValidEntity(self.dmgparticle) then self.dmgparticle:Remove(); self.dmgparticle = nil end
	self.dmgparticle = ents.Create( "info_particle_system" )
	self.dmgparticle:SetKeyValue( "effect_name", "tpdamage_" .. dmglvl )
	self.dmgparticle:SetKeyValue( "start_active", "1" )
	self.dmgparticle:SetPos( self:GetPos() )
	self.dmgparticle:SetParent( self )
	self.dmgparticle:Spawn()
	self.dmgparticle:Activate()
	self.dmgparticle.lvl = dmglvl
	return true
end

function ENT:CheckDamageLevel()
	if self:Health() == self:GetMaxHealth() then self:DamageLevel(0); return end
	if self:Health() <= self:GetMaxHealth() -(self:GetMaxHealth() *0.25) and self:Health() > self:GetMaxHealth() -(self:GetMaxHealth() *0.5) then
		self:DamageLevel(1)
	elseif self:Health() <= self:GetMaxHealth() -(self:GetMaxHealth() *0.5) and self:Health() > self:GetMaxHealth() -(self:GetMaxHealth() *0.75) then
		self:DamageLevel(2)
	elseif self:Health() <= self:GetMaxHealth() -(self:GetMaxHealth() *0.75) and self:Health() > self:GetMaxHealth() -(self:GetMaxHealth() *0.85) then
		self:DamageLevel(3)
	elseif self:Health() <= self:GetMaxHealth() -(self:GetMaxHealth() *0.85) then
		self:DamageLevel(4)
	end
end

function ENT:OnTakeDamage( dmg )
	if self.invulnerable then return end
	local attacker = dmg:GetAttacker()
	if attacker and ValidEntity(attacker) and attacker:IsPlayer() and attacker:Team() == self.team and self.team != 1001 then return end
	if self.owner and self:Health() == 150 and self:Health() -dmg:GetDamage() > 0 then self.owner:ConCommand("playgamesound misc/hud_warning.wav"); timer.Simple(2, function() if self and ValidEntity(self) and self:Health() > 0 and self:Health() < 150 and self.owner and ValidEntity(self.owner) then self.owner:ConCommand("playgamesound misc/hud_warning.wav") end end ) end
	self:SetHealth(self:Health() - dmg:GetDamage())
	self:CheckDamageLevel()
	self:SetNetworkedInt( "health", self:Health() )
	if self:Health() <= 0 and !self.broken then
		self.broken = true
		self:Explode()
	end
end

function ENT:Explode()
	for i = 1,3 do
		local gib = ents.Create( "obj_gib" )
		gib:SetModel( "models/buildables/Gibs/teleporter_Gib" .. i .. ".mdl" )
		gib:SetPos( self:GetPos() )
		gib:SetAngles( self:GetAngles() )
		gib:Spawn()
		gib:Activate()
		gib:GetPhysicsObject():ApplyForceCenter( Vector(0,0,500) )
		gib:SetSkin(self:GetSkin())
	end

	self:EmitSound( "weapons/teleporter_explode.wav", 100, 100 )
	local explosion = ents.Create( "info_particle_system" )
	explosion:SetKeyValue( "effect_name", "ExplosionCore_buildings" )
	explosion:SetPos( self:GetPos() +self:OBBCenter() ) 
	explosion:SetAngles( self:GetAngles() )
	explosion:Spawn()
	explosion:Activate() 
	explosion:Fire( "Start", "", 0 )
	explosion:Fire( "Kill", "", 0.1 )
	self:Remove()
end

function ENT:OnRemove()
	if self.owner then self.owner.teleport_exit = nil end
	if ValidEntity( self.idle_effect ) then self.idle_effect:Remove() end
	if ValidEntity( self.teleport_effect ) then self.teleport_effect:Remove() end
	if self.dmgparticle and ValidEntity(self.dmgparticle) then self.dmgparticle:Remove() end
	
	if self.tp_entrance then self.tp_entrance.tp_exit = nil end
	if self.owner and ValidEntity(self.owner) then self.owner:SetNetworkedEntity( "tp_exit", NULL ) end
	
	self.idlesound:Stop()
end

