AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile( "shared.lua" ) include('shared.lua') ENT.Alerted = false ENT.bleeds = 1 ENT.Grenades = 2 ENT.StartHealth = 45 ENT.PlayerFriendly = 0 ENT.AttackingMelee = false ENT.alert1 = "droid/attack1.wav" ENT.alert2 = "droid/attack2.wav" ENT.alert3 = "droid/roger.wav" ENT.idle1 = "droid/not_compute.wav" ENT.attack1 = "droid/attack1.wav" ENT.attack2 = "droid/attack2.wav" ENT.attack3 = "droid/cover.wav" ENT.die1 = "droid/die1.wav" ENT.die2 = "droid/die2.wav" ENT.seen_grenade = true ENT.TakingCover = false ENT.FindingLOS = false ENT.CanSeeEnemy = false ENT.TimeToTakeCover = 0 ENT.OutOfAmmo = false ENT.GotACloseOne = false ENT.dead = false function ENT:Initialize() if self:GetActiveWeapon() == nil then self:GetOwner():PrintMessage( HUD_PRINTNOTIFY, "This entity needs a weapon!" ) self:Give("weapon_smg1") end self:SetModel( "models/combine_starwar.mdl" ) self:SetHullType( HULL_HUMAN ) self:SetHullSizeNormal(); self:SetSolid( SOLID_BBOX ) self:SetMoveType( MOVETYPE_STEP ) self:CapabilitiesAdd( CAP_MOVE_GROUND | CAP_OPEN_DOORS | CAP_ANIMATEDFACE | CAP_SQUAD | CAP_USE_WEAPONS | CAP_DUCK | CAP_MOVE_SHOOT | CAP_TURN_HEAD | CAP_USE_SHOT_REGULATOR | CAP_AIM_GUN ) self:SetMaxYawSpeed( 5000 ) //self:Give("cse_mp5_fear") self.Friends = {""} self.Monsters = {"npc_antlion", "npc_antlion_worker", "npc_antlionguard", "npc_stalker", "monster_alien_controller", "monster_alien_grunt", "monster_alien_slave", "npc_headcrab", "npc_headcrab_black", "npc_headcrab_poison", "npc_headcrab_fast", "monster_babycrab", "monster_headcrab", "monster_bigmomma", "npc_hunter", "npc_rollermine", "npc_clawscanner", "npc_cscanner", "npc_manhack", "npc_fastzombie_torso", "npc_fastzombie", "npc_poisonzombie", "npc_zombie", "npc_zombie_torso", "npc_zombine", "monster_zombie", "npc_vortigaunt", "monster_bullchicken", "monster_gargantua", "monster_houndeye", "monster_ichthyosaur", "monster_archer", "monster_panthereye", "monster_snark", "monster_parasite","npc_xenomorph","npc_facehugger", "npc_st_insect", "npc_dan_zombie", "npc_raptor"} self.Scary_Things = { "npc_combinedropship", "npc_combinegunship", "npc_helicopter", "npc_strider", "npc_sniper" } //self:Give("cse_mp5_fear") //Sets the entity values self:SetHealth(self.StartHealth) self:SetEnemy(NULL) self:Fire("setsquad","Droids",0) end function ENT:OnTakeDamage(dmg) if (self.TakingCover == false) then self:SetSchedule(SCHED_SMALL_FLINCH) end //self:SpawnBlood(dmg) self:SetHealth(self:Health() - dmg:GetDamage()) if dmg:GetAttacker():GetClass() != self:GetClass() && math.random(1,25) == 1 then self:ResetEnemy() self:AddEntityRelationship( dmg:GetAttacker(), 1, 10 ) self:SetEnemy(dmg:GetAttacker()) self:CallForHelp() end if (self.TakingCover == false) || self.Alerted == false then self.TakingCover = true //print( "Take Cover, they shot me!" ); self:SetSchedule(SCHED_COMBAT_STAND ) end self.Alerted = true if self:Health() <= 0 && self.dead == false then //run on death self.dead = true; print("DIED!!!") self:KilledDan() end end function ENT:Think() local function setmeleefalse() self.MeleeAttacking = false end local function Attack_Melee() /* local entstoattack = ents.FindInSphere(self:GetPos() + self:GetForward()*75,74) if entstoattack != nil then self:EmitSound( "physics/body/body_medium_impact_hard"..math.random(1,6)..".wav", 400, 100) for _,v in pairs(entstoattack) do if ( (v:IsNPC() || ( v:IsPlayer() && v:Alive())) && (v != self) || (v:GetClass() == "prop_physics")) then v:TakeDamage( 4, self ) end end else self:EmitSound( "zombie/claw_miss1.wav", 400, 100) //add miss stuff here end timer.Create( "melee_done_timer" .. self.Entity:EntIndex( ), 0.25, 1, setmeleefalse ) */ end //print(self.TakingCover) if self:Health() > 0 then //print( "Think start" ); //Get all the npc's and other entities. local enttable = ents.FindByClass("npc_*") local monstertable = ents.FindByClass("monster_*") table.Add(monstertable,enttable)//merge //sort through each ent. for _, x in pairs(monstertable) do if (!ents) then print( "No Entities!" ); return end if (x:GetClass() != self:GetClass() && x:GetClass() != "npc_grenade_frag" && x:IsNPC()) then x:AddEntityRelationship( self, 1, 10 ) end end //print( "Think end" ); //self:AddRelationship("player D_HT 10") if self.TakingCover == false then self:GetBoomers()//grenades are top priority. if(math.random(1,20) == 1) then self:FindCloseEnemies()//get guys close to me end end //Hit them. if self:GetEnemy() != nil then if (self:GetEnemy():GetPos():Distance(self:GetPos()) < 70) then if self.MeleeAttacking == false then //self:SetSchedule( SCHED_MELEE_ATTACK1 ) timer.Create( "melee_attack_timer" .. self.Entity:EntIndex( ), 0.25, 1, Attack_Melee ) self.MeleeAttacking = true; end else self.MeleeAttacking = false end end end end function ENT:SelectSchedule() if self:Health() > 0 then //makes it never run out of ammo... :D self:GetActiveWeapon():SetClip1(45) local haslos = self:HasLOS() local distance = 0 local enemy_pos = 0 if self:GetEnemy() == nil then//no enemy self:FindEnemyDan() //print( "No Enemy!" ); self:SetSchedule(SCHED_IDLE_STAND)//patrol# self.TakingCover = false //play idle sounds every now and then local random_s = math.random(1,150) if random_s == 1 then self:StopSpeechSounds() self:EmitSound( self.idle1, 400, 100) end else //print( "Enemy!" ); //print(self:GetEnemy()) enemy_pos = self:GetEnemy():GetPos() distance = self:GetPos():Distance(enemy_pos) //distance = 4000 if distance > 4000 then//if too far away print( "Find him!" ); self:SetSchedule(SCHED_CHASE_ENEMY)//move to enemy elseif distance < 4000 && distance > 400 then//if in reasonable distance //if self:Health() < (self.StartHealth*0.25) then//if damaged > 75% and not in cover // self.TakingCover = true // print( "Take Cover, I'm hurt!" ); // self:SetSchedule(SCHED_COMBAT_STAND) //else self.TakingCover = false local randomsound = math.random(1,140) if randomsound == 1 then self:StopSpeechSounds() self:EmitSound( self.attack1, 400, 100) elseif randomsound == 2 then self:StopSpeechSounds() self:EmitSound( self.attack2, 400, 100) elseif randomsound == 3 then self:StopSpeechSounds() self:EmitSound( self.attack3, 400, 100) end //self:SetSchedule(SCHED_ESTABLISH_LINE_OF_FIRE)//move to enemy# if haslos && distance > 1000 then self:SetSchedule(SCHED_COMBAT_STAND) else //if math.random(1,2) == 1 then //self:SetSchedule(SCHED_ESTABLISH_LINE_OF_FIRE)//move to shoot enemy //else self:SetSchedule(SCHED_CHASE_ENEMY)//otherwise go to them. //end end if math.random(1,80) < 3 then print("Reloading") self:SetSchedule(SCHED_RELOAD) //give the ILLUSION of reloading. :D end //self:SetSchedule(SCHED_COMBAT_STAND) //end else//if too close if (haslos == true) then if self.TakingCover == false then //print( "Back away!!!!" ); self:SetSchedule(SCHED_COMBAT_STAND ) end else self.TakingCover = false self:SetSchedule(SCHED_CHASE_ENEMY)//move to shoot enemy end end end end end function ENT:FindEnemyDan() local MyNearbyTargets = ents.FindInCone(self:GetPos(),self:GetForward(),4000,45) //local ClosestDistance = 3000 if (!MyNearbyTargets) then print( "No Targets!" ); return end for k,v in pairs(MyNearbyTargets) do if v:Disposition(self) == 1 || v:IsPlayer() then //if (v:GetClass() == "npc_*" || v:GetClass() == "monster_*") && v:GetClass() != self:GetClass() then print(v:GetClass()) self:StopSpeechSounds() self:ResetEnemy() self:AddEntityRelationship( v, 1, 10 ) self:SetEnemy(v) local distance = self:GetPos():Distance(v:GetPos()) local randomsound = math.random(1,5) //self:SetSchedule(SCHED_ALERT_FACE) //alerted if self.Alerted == false then if randomsound == 1 then self:EmitSound( self.alert1, 400, 100) elseif randomsound == 2 then self:EmitSound( self.alert2, 400, 100) elseif randomsound == 3 then self:EmitSound( self.alert3, 400, 100) end end self.Alerted = true return end end //if ClosestDistance == 4000 then self:SetEnemy(NULL) //end end function ENT:StopSpeechSounds() self:StopSound(self.alert1) self:StopSound(self.alert2) self:StopSound(self.alert3) self:StopSound(self.idle1) self:StopSound(self.attack1) self:StopSound(self.attack2) self:StopSound(self.attack3) self:StopSound(self.alert1) self:StopSound(self.alert2) self:StopSound(self.alert3) end function ENT:StopHurtSounds() end function ENT:SpawnBlood(dmg) if (self.bleeds > 0) then local bloodeffect = ents.Create( "info_particle_system" ) bloodeffect:SetKeyValue( "effect_name", "blood_impact_red_01" ) bloodeffect:SetPos( dmg:GetDamagePosition() ) bloodeffect:Spawn() bloodeffect:Activate() bloodeffect:Fire( "Start", "", 0 ) bloodeffect:Fire( "Kill", "", 0.1 ) end end function ENT:GetBoomers() /* local nearbygrenades = ents.FindByClass("npc_grenade_frag") for k,v in pairs(nearbygrenades) do if self:GetPos():Distance(v:GetPos()) < 400 then self:StopSpeechSounds() self:ResetEnemy() self:AddEntityRelationship( v, 3, 10 ) //self:SetEnemy(v) self.seen_grenade = true self.TakingCover = true self:SetSchedule(SCHED_HIDE_AND_RELOAD) return end end */ end function ENT:KilledDan() /*I Took some of silverlan's code for ragdolling, cause I didn't want to recode it :P*/ //emit cry of death self:StopSpeechSounds() self:StopHurtSounds() local deathseed = math.random(1,11) if deathseed == 1 then self:EmitSound( self.die1, 500, 100) elseif deathseed == 2 then self:EmitSound( self.die2, 500, 100) end //create ragdoll local ragdoll = ents.Create( "prop_ragdoll" ) ragdoll:SetModel( self:GetModel() ) ragdoll:SetPos( self:GetPos() ) ragdoll:SetAngles( self:GetAngles() ) ragdoll:Spawn() ragdoll:SetSkin( self:GetSkin() ) ragdoll:SetColor( self:GetColor() ) ragdoll:SetMaterial( self:GetMaterial() ) //my code undo.ReplaceEntity(self,ragdoll) cleanup.ReplaceEntity(self,ragdoll) //ignight ragdoll if on fire. if self:IsOnFire() then ragdoll:Ignite( math.Rand( 8, 10 ), 0 ) end //position bones the same way. for i=1,128 do local bone = ragdoll:GetPhysicsObjectNum( i ) if ValidEntity( bone ) then local bonepos, boneang = self:GetBonePosition( ragdoll:TranslatePhysBoneToBone( i ) ) bone:SetPos( bonepos ) bone:SetAngle( boneang ) end end if( GetConVarNumber("ai_keepragdolls") == 0 ) then ragdoll:SetCollisionGroup( 1 )//COLLISION_GROUP_DEBRIS ) ragdoll:Fire( "FadeAndRemove", "", 7 ) end self:Remove() end function ENT:CallForHelp() end function ENT:ResetEnemy() end function ENT:FindCloseEnemies() local MyNearbyTargets = ents.FindInCone(self:GetPos(),self:GetForward(),300,45) //local ClosestDistance = 3000 if (!MyNearbyTargets) then print( "No Targets!" ); return end for k,v in pairs(MyNearbyTargets) do if v:Disposition(self) == 1 || v:IsPlayer() then print(v:GetClass()) self:StopSpeechSounds() self:ResetEnemy() self:AddEntityRelationship( v, 1, 10 ) self:SetEnemy(v) if (self.TakingCover == false) || self.Alerted == false then self.TakingCover = true self:SetSchedule(SCHED_BACK_AWAY_FROM_ENEMY) end local randomsound = math.random(1,90) self.Alerted = true return end end end function ENT:OnRemove() timer.Remove("melee_attack_timer" .. self.Entity:EntIndex( )) timer.Remove("melee_done_timer" .. self.Entity:EntIndex( )) end function ENT:HasLOS() if self:GetEnemy() != nil then //local shootpos = self:GetAimVector()*(self:GetPos():Distance(self:GetEnemy():GetPos())) + self:GetPos() //local shootpos = self:GetEnemy():GetPos() local tracedata = {} tracedata.start = self:GetPos() + Vector(0,0,64) tracedata.endpos = self:GetEnemy():GetPos() + Vector(0,0,64) tracedata.filter = self local trace = util.TraceLine(tracedata) if trace.HitWorld == false then print("returned true!") return true else return false end end print ("no enemy!") return false end