NPC.Name = "Zombie" NPC.Desc = "A fearsome monster!" NPC.Class = "Ambient" --Ambient, Agressive, Boss NPC.Model = "models/Zombie/Classic.mdl" NPC.Icon = Material("wintersurvival2/hud/ws1_icons/icon_rock") NPC.Social = "Solo" --Solo, Pack NPC.Stats = { ["Vitality"] = 100, ["Speed"] = 50, ["AwareDist"] = 1000, ["Accel"] = 100, ["Decel"] = 200, ["Step"] = 20, --Step height ["Hull"] = HULL_HUMAN } --Drops should be formated as [index]={["item name"], percent_drop} where percent_drop is a number from 0 to 100 NPC.Drops = { [0] = {"Meat",100},--Birds will drop at least 1 meat, and have a 50% chance of dropping 2 [1] = {"Meat",50}, [2] = {"Feather",50}, } --Some npc's like birds have diffent names for their idle sequences NPC.IdleSequences = { [0] = "Idle", } --Distance to be made aware of players --Attacks should be formated as [i]={function (return int dammage) canattack(ply) = function doattack(ply)} --NPC will do the most dammage possible per attack local checkmele = function(self, ply) if(ply:GetPos():Distance(self:GetPos()) < 100) then return 20 end return -1 end local domele = function(self, ply) self:StartActivity(ACT_MELEE_ATTACK1) --Antlion has 6 attack animations local attackanim = math.Round(math.Rand(1,6)) coroutine.wait(0.75) --If the player is still in front of us after the animation, they didn't dodge! apply dammage! if(ply:GetPos():Distance(self:GetPos()) < 100) then ply:TakeDamage(20) end --Finish up the animation coroutine.wait(0.25) end local checkrun = function(self, ply) return 0 end local dorun = function(self, ply) local navarea = navmesh.GetNavArea(self:GetPos(), 100) self.loco:SetDesiredSpeed( 50 ) if navarea:IsValid() then local moveop = {} moveop.tolerance = 50 moveop.repath = 2 moveop.lookahead = 3 moveop.draw = true self:StartActivity(ACT_WALK) self:MoveToPos(ply:GetPos(),moveop) else print("Could not find valid navmesh, suicideing to prevent server crash!") self:BecomeRagdoll(DamageInfo()) end end NPC.Attacks = { [1] = { --A mele attack [checkmele] = domele }, [2] = {--Move to the player [checkrun] = dorun }, } --Attack priority is a fucntion that takes a player, and returns an int describing it's prority to attack (higher = more important) NPC will always attack the player with the highest priority function NPC:AttackPriority(ply) local dist = ply:GetPos():Distance(self:GetPos()) return self.Stats["AwareDist"] - dist end --A function that takes a position and returns true if this is an acceptable place to spawn function NPC:SpawnLocations(pos) return true end --The entity that is this npc's current target, if it has one. Nil otherwise NPC.Target = nil --All enemies that this NPC is aware of NPC.AwareEnemies = {} --What to replace the ENT:BehaveAct with function NPC:Act() end --What to replace ENT:OnStuck with function NPC:Stuck() --If we're stuck, jump backwards end --What to replace ENT:RunBehaviour with --[[ function NPC:Behave() --[[ print("Going into antlion's custom behaviour") while ( true ) do --self:PlaySequenceAndWait( "Idle" ) --Main loop for ai --Update aware enemies local players = ents.FindByClass("Player") for k,v in pairs(players) do if(v:IsPigeon()) then continue end local dist = v:GetPos():Distance(self:GetPos()) if( dist < self.Stats["AwareDist"]) then table.insert(self.AwareEnemies,v) end end --Find the enemy with the highest priority local maxpriority = -1 local maxprioritytarget = nil for k,v in pairs(self.AwareEnemies) do local priority = self:AttackPriority(v) if(priority > maxpriority) then maxpriority = priority maxprioritytarget = v end end self.Target = maxprioritytarget --If we can't find anyone to attack, just stay idle if(self.Target == nil) then print("Couldn't find anyone to attack!") --Play an idle sequence local randanim = math.Round(math.Rand(0,#self.IdleSequences)) self:PlaySequenceAndWait( self.IdleSequences[randanim] ) self:StartActivity( ACT_IDLE ) else --We have a target to attack! print("We found something to attack!") --Find which attack will do the most dammage local maxdammage = -1 local maxdammagefunc = nil for k,v in pairs(self.Attacks) do local dammagefunc = nil local attackfunc = nil for i,j in pairs(v) do dammagefunc = i attackfunc = j end print("Using damagefunc:") print(dammagefunc) local dammage = dammagefunc(self, self.Target) print("dammage is ") print(dammage) if(dammage > maxdammage) then maxdammage = dammage maxdammagefunc = attackfunc end end --Do that attack if(maxdammagefunc) then maxdammagefunc(self, self.Target) else print("It looked like we could attack, but we can't!") end end --coroutine.yield() end coroutine.yield() end --]] --These are just here to tell the editors/develoeprs what functions are available.. dont un-comment them out, as this could affect all the items. /* function NPC:OnSpawn() end --If we need to do more than just reduce health on dammage function NPC:OnDammage(ammount) end --If we need to do more than just drop items on death function NPC:OnDeath() end --A particular spell was cast on this npc by player function NPC:OnSpell(spell, player) end function NPC:OnFindEnemy(enemy) end --Called when the npc is attacking anything with any attack function NPC:OnAttack(target) end */