summaryrefslogtreecommitdiff
path: root/lua/entities/npc_huntable/shared.lua
blob: e42c100d04734a664bc784e6e360f8cb28b33466 (plain)
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