1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
ENT.Base = "base_nextbot"
--ART stuff
ENT.Drops = nil
ENT.OnDammage = nil
ENT.Speed = 0
ENT.Model = nil
ENT.Behave = nil
ENT.Act = nil
ENT.AutomaticFrameAdvance = true
--[[---------------------------------------------------------
Name: OnRemove
Desc: Called just before entity is deleted
---------------------------------------------------------]]
function ENT:OnRemove()
end
function ENT:DefaultBehaviour()
print("In default behavior")
self.lastrun = CurTime()
--Set some stuff up for navigation
local path = Path( "Follow" )
path:SetMinLookAheadDistance( self.lookahead or 300 )
path:SetGoalTolerance( self.goaltolarance or 100)
path:Draw()
local delta = CurTime() - self.lastrun
self:AI(delta)
while (true) do
--print("Inside defaultbehaviour's while")
--Sets all the values needed for the rest of this function to do it's thing
--Main loop for ai
--print("Going into behavior for " .. self.Name)
--Update aware enemies
delta = CurTime() - self.lastrun
--print("delta was", delta)
if delta > 0.1 then
--print('Running ai')
self:AI(delta)
self.lastrun = CurTime()
end
if self.TargetPos ~= nil then
if ( !path:IsValid() ) then print("Path wasn't valid!") end
if ( path:GetAge() > 0.1 ) then -- Since we are following the player we have to constantly repath
path:Compute( self, self.TargetPos ) -- Compute the path towards the enemy's position again
path:Update( self ) -- This function moves the bot along the path
end
if ( true ) then path:Draw() end
-- If we're stuck then call the HandleStuck function and abandon
if ( self.loco:IsStuck() ) then
--self:HandleStuck()
--return "stuck"
end
--return "ok"
end
coroutine.yield()
end
coroutine.yield()
end
function ENT:AI(num)
--print("Inside ai")
local players = player.GetAll()
for k, v in pairs(players) do
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 == nil) then
--print("Nill priority hit after ")
--PrintTable(self)
end
if (priority > maxpriority) then
maxpriority = priority
maxprioritytarget = v
end
end
self.Target = maxprioritytarget
--print("My target is",self.Target)
--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(1, #self.IdleSequences))
print("Playing sequence",self.IdleSequences[randanim])
self:PlaySequenceAndWait(self.IdleSequences[randanim])
self:StartActivity(ACT_IDLE)
print("Acting idle")
--If there's noone within 4000 units, just remove ourselves to save server resources
local closest = 5000
for k, v in pairs(player.GetAll()) do
local thisdist = self:GetPos():Distance(v:GetPos())
if (thisdist < closest) then
closest = thisdist
end
end
if (closest > 4000) then
--print("Closes player is " .. closest .. " removeing self...")
self:BecomeRagdoll(DamageInfo())
end
else
--We have a target 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
local dammage = dammagefunc(self, self.Target)
if (dammage > maxdammage) then
maxdammage = dammage
maxdammagefunc = attackfunc
end
end
--Do that attack
if (maxdammagefunc) then
maxdammagefunc(self, self.Target)
end
end
--[[
print("Before running, behavethread was", self.BehaveThread)
local ok, message = coroutine.resume( self.BehaveThread )
if not ok then
self.BehaveThread = nil
Msg( self, "error: ", message, "\n" );
end
]]
if (self.Act) then
self:Act(num)
else
print("NPC spawned without an Act function, this might be an error!")
end
end
function ENT:RunBehaviour()
print("Running behavior")
if (self.Behave) then
print("Doing self.behave")
self:Behave()
else
print("Doing default behavior")
self:DefaultBehaviour()
end
end
|