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

ENT.Model 			= "models/arachnid.mdl";
ENT.HealthAmt 		= 400;
ENT.Alerted 		= false;
ENT.Damage 			= 35;
ENT.MeleeAttacking 	= false;

ENT.alert 			= "warrior/warrior_idle2.wav";

ENT.idleSounds		= {

	"warrior/warrior_idle2.wav",
	"warrior/warrior_idle2.wav",
	"warrior/warrior_idle.wav",
	"warrior/warrior_hiss3.wav"
	
}

ENT.attackSounds	= {

	"warrior/warrior_hiss1.wav",
	"warrior/warrior_hiss2.wav",
	"warrior/warrior_hiss4.wav"
	
};

ENT.missSounds 		= {

	"warrior/claw_miss1.wav",
	"warrior/claw_miss2.wav"
	
};

ENT.hurtSounds 		= {

	"warrior/warrior_hurt.wav",
	"warrior/warrior_hurt2.wav",
	"warrior/warrior_hurt.wav"

};

ENT.dieSounds		= {

	"warrior/warrior_hurt.wav",
	"warrior/warrior_hurt2.wav"

};

ENT.dead 			= false;

function ENT:Initialize()

   self:SetModel( self.Model );
   self:SetHullType( HULL_MEDIUM_TALL );
   self:SetHullSizeNormal();
   self:SetSolid( SOLID_BBOX );
   self:SetMoveType( MOVETYPE_STEP );
   self:CapabilitiesAdd( CAP_MOVE_GROUND | CAP_SQUAD | CAP_MOVE_JUMP );
   self:SetMaxYawSpeed( 5000 );
   self:SetHealth( self.HealthAmt );
   self:Fire( "setsquad", "Bugs", 0 );
   
end

function ENT:Think()
    
	local function Attack_Melee_F()
	
		if( self:Health() < 0 ) then return end
		self.MeleeAttacking = false;
		self:SetSchedule( SCHED_CHASE_ENEMY );
		
	end
    
	local function Attack_Melee()
	
		if( self:Health() < 0 ) then return end
		
		local entstoattack = ents.FindInSphere( self:GetPos() + self:GetForward() * 75, 47 );
		local hit = false;	-- Sounds
		
		if( entstoattack ) then
			
			for _, v in pairs( entstoattack ) do
				
				if( v:IsPlayer() and v:Alive() ) then
				
					v:TakeDamage( self.Damage, self );
						
					local n = math.random( -1, 1 ) * self.Damage;
					v:ViewPunch( Angle( n, n, n ) );
					
					v:SetVelocity( self:GetForward() * 100 );
					hit = true;
					
				end
				
			end
			
		end
		
		if( hit == false ) then
			
			local missSnd = self.missSounds[ math.random( 1, #self.missSounds ) ];
			self:EmitSound( missSnd, 460, math.random( 80, 120 ) );
			
		else
			
			local attackSnd = self.attackSounds[ math.random( 1, #self.attackSounds ) ];
	      	self:EmitSound( attackSnd, 460, math.random( 80, 120 ) );
			
		end
		
		timer.Simple( 0.4, Attack_Melee_F );
		
	end
	
    if( GetConVarNumber( "ai_disabled" ) == 0 and self:GetNWInt( "Disabled" ) == 0 ) then
		
		for k, v in pairs( player.GetAll() ) do
			
			self:AddEntityRelationship( v, 1, 10 ); -- i HATES players
			
		end
		
		if( self:GetEnemy() ) then
			
			self:UpdateEnemyMemory( self:GetEnemy(), self:GetEnemy():GetPos() );
			
		end
		
		local randomsound = math.random( 1, 30 );	-- Idle sounds
		
		if( randomsound == 1 ) then
			
			local idleSound = self.idleSounds[ math.random( 1, #self.idleSounds ) ];
	      	self:EmitSound( idleSound, 460, math.random( 80, 120 ) );
			
		end
		
		self:FindCloseEnemies();
		
		if( self:GetEnemy() ) then -- Melee em!
		
			if( self:GetEnemy():GetPos():Distance( self:GetPos() ) < 100 ) then
			
				if( self.MeleeAttacking == false ) then
					
					if( self:GetEnemy():GetNWInt( "CloakOn" ) ~= 1 ) then
					
						self:SetSchedule( SCHED_MELEE_ATTACK1 );
						timer.Simple( 0.5, Attack_Melee );
						self.MeleeAttacking = true;
					
					end
					
				end
				
			end
				
		else -- No target - find a new one
		
			self:FindEnemy_D();
			self.MeleeAttacking = false;
			
		end
		
    end

end

function ENT:SelectSchedule()

	if( self:GetEnemy() ) then
	
		if( self:GetEnemy():GetPos():Distance( self:GetPos() ) > 5000 ) then
			
			self:SetEnemy( NULL );
			self:SetSchedule( SCHED_CHASE_ENEMY_FAILED );
			
		end
		
	end

	if( self.Alerted and self:GetEnemy() ) then
		
		self:UpdateEnemyMemory( self:GetEnemy(), self:GetEnemy():GetPos() );
		self:SetSchedule( SCHED_CHASE_ENEMY );
		
	else
		
		self:SetSchedule( SCHED_IDLE_WANDER );
		
	end
	
end

function ENT:OnTakeDamage( dmg )

	self:SpawnBlood( dmg );
	self:SetHealth( self:Health() - dmg:GetDamage() );
	
	if( math.random( 28 ) == 1 ) then
		
		local hurtSound = self.hurtSounds[ math.random( 1, #self.hurtSounds ) ];
		self:EmitSound( hurtSound );
		
	end
	
	if( self:Health() <= 0 and not self.dead ) then
	
		self.dead = true;	-- Bugfix
		self:Killed_D();
		
	end
	
end

function ENT:FilterPlayers( tab )
	
	local plytab = { };
	
	for k, v in pairs( tab ) do
		
		if( v:IsPlayer() and v:Alive() ) then
			
			table.insert( plytab, v );
			
		end
		
	end
	
	return plytab;
	
end

function ENT:FindEnemy_D()
	
	local ply = self:FindClosestPly( player.GetAll() );
	
	if( ply ) then
		
		self:SetEnemy( ply );
		self:UpdateEnemyMemory( ply, ply:GetPos() );
		
		local randomsound = math.random( 1, 2 );
		
		if( not self.Alerted ) then
		
			if( randomsound == 1 ) then
			
				self:EmitSound( self.alert, 460, math.random( 80, 120 ) );
				
			end
			
		end
		
		self.Alerted = true;
		return;
		
	end
	
end

function ENT:FindCloseEnemies()
	
	local MyNearbyTargets = self:FilterPlayers( ents.FindInSphere( self:GetPos(), 250 ) );
	if( not MyNearbyTargets ) then return end
	
	local ply = self:FindClosestPly( MyNearbyTargets );
	
	if( ply ) then
	
		self:SetEnemy( ply );
		self.Alerted = true;
		return;
		
	end
	
end

function ENT:FindClosestPly( enttab )
	
	local tab = enttab; -- table of players
	
	local len = 999999; -- max length - for sorting
	local pl = nil;
	
	for k, v in pairs( tab ) do
		
		local my = self:GetPos();
		local their = v:GetPos()
		
		local length = my:Distance( their );
		if( length < len ) then
			
			len = length;
			pl = v;
			
		end
		
	end
	
	return pl;
	
end

function ENT:SpawnBlood( dmg )

   	local bloodeffect = ents.Create( "info_particle_system" );
	bloodeffect:SetKeyValue( "effect_name", "blood_impact_yellow_01" );
    bloodeffect:SetPos( dmg:GetDamagePosition() );
	bloodeffect:Spawn();
	bloodeffect:Activate();
	bloodeffect:Fire( "Start", "", 0 );
	bloodeffect:Fire( "Kill", "", 0.1 );
   
end

function ENT:Killed_D()
	
	-- AIEEEE
	local dieSound = self.dieSounds[ math.random( 1, #self.dieSounds ) ];
	self:EmitSound( dieSound, 460, math.random( 80, 120 ) );
	
	local pos = self:GetPos();
	local ang = self:GetAngles();
	
	local ragdoll = ents.Create( "prop_ragdoll" );
		ragdoll:SetModel( self:GetModel() );
		ragdoll:SetPos( pos );
		ragdoll:SetAngles( ang );
		ragdoll:Spawn();
		ragdoll:SetCollisionGroup( COLLISION_GROUP_DEBRIS );
	
	self:Remove()
	
end
