~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/src/bot/bot.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// C++ Implementation: bot
 
3
//
 
4
// Description: 
 
5
//
 
6
// Contains code of the base bot class
 
7
//
 
8
// Author:  Rick <rickhelmus@gmail.com>
 
9
//
 
10
//
 
11
//
 
12
 
 
13
#include "pch.h"
 
14
#include "bot.h"
 
15
 
 
16
vector<botent *> bots;
 
17
 
 
18
extern int triggertime;
 
19
extern itemstat itemstats[];
 
20
extern ENetHost *clienthost;
 
21
 
 
22
const vec g_vecZero(0, 0, 0);
 
23
 
 
24
//Bot class begin
 
25
 
 
26
CBot::~CBot()
 
27
{
 
28
     // Delete all waypoints
 
29
     loopi(MAX_MAP_GRIDS)
 
30
     {
 
31
          loopj(MAX_MAP_GRIDS)
 
32
          {
 
33
               while (m_WaypointList[i][j].Empty() == false)
 
34
                    delete m_WaypointList[i][j].Pop();
 
35
          }
 
36
     }
 
37
}
 
38
 
 
39
void CBot::Spawn()
 
40
{
 
41
     // Init all bot variabeles
 
42
     spawnplayer(m_pMyEnt);
 
43
     
 
44
     m_pMyEnt->targetyaw = m_pMyEnt->targetpitch = 0.0f;
 
45
     m_pMyEnt->enemy = NULL;
 
46
     m_pMyEnt->maxspeed = 22.0f;
 
47
     m_pMyEnt->pBot = this;     
 
48
         
 
49
     m_eCurrentBotState = STATE_NORMAL;
 
50
     m_iShootDelay = m_iChangeWeaponDelay = 0;
 
51
     m_iCheckEnvDelay = 0;
 
52
     m_vPrevOrigin = g_vecZero;
 
53
     m_iStuckCheckDelay = lastmillis + 250;
 
54
     m_bStuck = false;
 
55
     m_iStuckTime = 0;
 
56
     m_iStrafeTime = m_iStrafeCheckDelay = 0;
 
57
     m_iMoveDir = DIR_NONE;
 
58
     
 
59
     m_pPrevEnemy = NULL;
 
60
     m_iCombatNavTime = 0;
 
61
     m_iSPMoveTime = 0;
 
62
     m_iEnemySearchDelay = 0;
 
63
     m_iSawEnemyTime = 0;
 
64
     m_bCombatJump = false;
 
65
     m_iCombatJumpDelay = 0;
 
66
     m_bShootAtFeet = (RandomLong(1, 100) <= m_pBotSkill->sShootAtFeetWithRLPercent);
 
67
     m_iHuntDelay = 0;
 
68
     m_vHuntLocation = m_vPrevHuntLocation = g_vecZero;
 
69
     m_pHuntTarget = NULL;
 
70
     m_fPrevHuntDist = 0.0f;
 
71
     m_iHuntLastTurnLessTime = m_iHuntPlayerUpdateTime = m_iHuntPauseTime = 0;
 
72
     m_iLookAroundDelay = m_iLookAroundTime = m_iLookAroundUpdateTime = 0;
 
73
     m_fLookAroundYaw = 0.0f;
 
74
     m_bLookLeft = false;
 
75
        
 
76
     m_iLastJumpPad = 0;
 
77
     m_pTargetEnt = NULL;
 
78
     while(!m_UnreachableEnts.Empty()) delete m_UnreachableEnts.Pop();
 
79
     m_iCheckTeleporterDelay = m_iCheckJumppadsDelay = 0;
 
80
     m_iCheckEntsDelay = 0;
 
81
     m_iCheckTriggersDelay = 0;
 
82
     m_iLookForWaypointTime = 0;
 
83
        
 
84
     m_iAimDelay = 0;
 
85
     m_fYawToTurn = m_fPitchToTurn = 0.0f;
 
86
     
 
87
     m_vGoal = m_vWaterGoal = g_vecZero;
 
88
     
 
89
     ResetWaypointVars();
 
90
}
 
91
 
 
92
void CBot::Think()
 
93
{
 
94
     if (intermission)
 
95
          return;
 
96
             
 
97
     // Bot is dead?
 
98
     if (m_pMyEnt->state == CS_DEAD)
 
99
     {
 
100
          if(lastmillis-m_pMyEnt->lastaction<1200)
 
101
          {
 
102
               m_pMyEnt->move = 0;
 
103
               moveplayer(m_pMyEnt, 1, true);
 
104
          }
 
105
          else if (!m_arena && lastmillis-m_pMyEnt->lastaction>5000)
 
106
               Spawn();
 
107
     
 
108
          SendBotInfo();
 
109
          return;
 
110
     }
 
111
     
 
112
     CheckItemPickup();
 
113
 
 
114
     TLinkedList<unreachable_ent_s*>::node_s *p = m_UnreachableEnts.GetFirst(), *tmp;
 
115
     while(p)
 
116
     {
 
117
          if ((lastmillis - p->Entry->time) > 3500)
 
118
          {
 
119
               tmp = p;
 
120
               p = p->next;
 
121
               delete tmp->Entry;               
 
122
               m_UnreachableEnts.DeleteNode(tmp);
 
123
               continue;
 
124
          }
 
125
          p = p->next;
 
126
     }
 
127
 
 
128
     if (!BotManager.IdleBots())
 
129
     {
 
130
          MainAI();
 
131
     }
 
132
     else
 
133
     {
 
134
          ResetMoveSpeed();
 
135
     }    
 
136
     
 
137
     // Aim to ideal yaw and pitch
 
138
     AimToIdeal();
 
139
     
 
140
     // Store current location, to see if the bot is stuck
 
141
     m_vPrevOrigin = m_pMyEnt->o;
 
142
     
 
143
     // Don't check for stuck if the bot doesn't want to move
 
144
     if (!m_pMyEnt->move && !m_pMyEnt->strafe)
 
145
          m_iStuckCheckDelay = max(m_iStuckCheckDelay, lastmillis+100.0f);
 
146
          
 
147
     // Move the bot
 
148
     moveplayer(m_pMyEnt, 1, true);
 
149
     
 
150
     // Update bot info on all clients
 
151
     SendBotInfo();
 
152
}
 
153
 
 
154
void CBot::AimToVec(const vec &o)
 
155
{
 
156
     m_pMyEnt->targetpitch = atan2(o.z-m_pMyEnt->o.z, GetDistance(o))*180/PI;
 
157
     m_pMyEnt->targetyaw = -(float)atan2(o.x - m_pMyEnt->o.x, o.y -
 
158
                                         m_pMyEnt->o.y)/PI*180+180;
 
159
}
 
160
 
 
161
void CBot::AimToIdeal()
 
162
{
 
163
     if (m_iAimDelay > lastmillis)
 
164
          return;
 
165
 
 
166
     float MaxXSpeed = RandomFloat(m_pBotSkill->flMinAimXSpeed,
 
167
                                   m_pBotSkill->flMaxAimXSpeed);
 
168
     float MaxYSpeed = RandomFloat(m_pBotSkill->flMinAimYSpeed,
 
169
                                   m_pBotSkill->flMaxAimYSpeed);
 
170
     float XOffset = RandomFloat(m_pBotSkill->flMinAimXOffset,
 
171
                                 m_pBotSkill->flMaxAimXOffset);
 
172
     float YOffset = RandomFloat(m_pBotSkill->flMinAimYOffset,
 
173
                                 m_pBotSkill->flMaxAimYOffset);
 
174
     float RealXOffset, RealYOffset;
 
175
     float AimXSpeed = MaxXSpeed, AimYSpeed = MaxYSpeed;
 
176
     float XDiff = fabs(m_pMyEnt->targetpitch - m_pMyEnt->pitch);
 
177
     float YDiff = fabs(m_pMyEnt->targetyaw - m_pMyEnt->yaw);
 
178
 
 
179
     // How higher the diff, how higher the offsets and aim speed
 
180
          
 
181
     if (XOffset)
 
182
     {
 
183
          if (RandomLong(0, 1))
 
184
               RealXOffset = XDiff * (XOffset / 100.0f);
 
185
          else
 
186
               RealXOffset = -(XDiff * (XOffset / 100.0f));
 
187
     }
 
188
     else
 
189
          RealXOffset = 0.0f;
 
190
 
 
191
     if (YOffset)
 
192
     {
 
193
          if (RandomLong(0, 1))
 
194
               RealYOffset = YDiff * (YOffset / 100.0f);
 
195
          else
 
196
               RealYOffset = -(YDiff * (YOffset / 100.0f));
 
197
     }
 
198
     else
 
199
          RealYOffset = 0.0f;
 
200
 
 
201
          
 
202
     if (XDiff >= 1.0f)
 
203
          AimXSpeed = (AimXSpeed * (XDiff / 80.0f)) + (AimXSpeed * 0.25f);
 
204
     else
 
205
          AimXSpeed *= 0.01f;
 
206
 
 
207
     if (YDiff >= 1.0f)
 
208
          AimYSpeed = (AimYSpeed * (YDiff / 70.0f)) + (AimYSpeed * 0.25f);
 
209
     else
 
210
          AimYSpeed *= 0.015f;
 
211
 
 
212
     m_fPitchToTurn = fabs((m_pMyEnt->targetpitch + RealXOffset) - m_pMyEnt->pitch);
 
213
     m_fYawToTurn = fabs((m_pMyEnt->targetyaw + RealYOffset) - m_pMyEnt->yaw);
 
214
     
 
215
     float flIdealPitch = ChangeAngle(AimXSpeed, m_pMyEnt->targetpitch + RealXOffset, m_pMyEnt->pitch);
 
216
     float flIdealYaw = ChangeAngle(AimYSpeed, m_pMyEnt->targetyaw + RealYOffset, m_pMyEnt->yaw);
 
217
     
 
218
//     m_pMyEnt->pitch = WrapXAngle(m_pMyEnt->targetpitch); // Uncomment for instant aiming
 
219
//     m_pMyEnt->yaw = WrapYZAngle(m_pMyEnt->targetyaw);
 
220
                 
 
221
     m_pMyEnt->pitch = WrapXAngle(flIdealPitch);
 
222
     m_pMyEnt->yaw = WrapYZAngle(flIdealYaw);     
 
223
}     
 
224
 
 
225
// Function code by Botman
 
226
float CBot::ChangeAngle(float speed, float ideal, float current)
 
227
{
 
228
     float current_180;  // current +/- 180 degrees
 
229
     float diff;
 
230
 
 
231
     // find the difference in the current and ideal angle
 
232
     diff = fabs(current - ideal);
 
233
    
 
234
     // speed that we can turn during this frame...
 
235
     speed = speed * (float(BotManager.m_iFrameTime)/1000.0f);
 
236
 
 
237
     // check if difference is less than the max degrees per turn
 
238
     if (diff < speed)
 
239
          speed = diff;  // just need to turn a little bit (less than max)
 
240
 
 
241
     // check if the bot is already facing the idealpitch direction...
 
242
     if (diff <= 1.0f)
 
243
          return ideal;
 
244
          
 
245
     if ((current >= 180) && (ideal >= 180))
 
246
     {
 
247
          if (current > ideal)
 
248
               current -= speed;
 
249
          else
 
250
               current += speed;
 
251
     }
 
252
     else if ((current >= 180) && (ideal < 180))
 
253
     {
 
254
          current_180 = current - 180;
 
255
 
 
256
          if (current_180 > ideal)
 
257
               current += speed;
 
258
          else
 
259
               current -= speed;
 
260
     }
 
261
     else if ((current < 180) && (ideal >= 180))
 
262
     {
 
263
          current_180 = current + 180;
 
264
          
 
265
          if (current_180 > ideal)
 
266
               current += speed;
 
267
          else
 
268
               current -= speed;
 
269
     }
 
270
     else  // (current < 180) && (ideal < 180)
 
271
     {
 
272
          if (current > ideal)
 
273
               current -= speed;
 
274
          else
 
275
               current += speed;
 
276
     }
 
277
 
 
278
 
 
279
     return current;     
 
280
}
 
281
 
 
282
void CBot::SendBotInfo()
 
283
{
 
284
     if(lastmillis-m_iLastBotUpdate<40) return;    // don't update faster than 25fps
 
285
     m_iLastBotUpdate = lastmillis;
 
286
}
 
287
 
 
288
float CBot::GetDistance(const vec &o)
 
289
{
 
290
     return o.dist(m_pMyEnt->o);
 
291
}
 
292
 
 
293
float CBot::GetDistance(const vec &v1, const vec &v2)
 
294
{
 
295
     return v2.dist(v1);
 
296
}
 
297
 
 
298
float CBot::GetDistance(entity *e)
 
299
{
 
300
     vec v(e->x, e->y, e->z);
 
301
     return v.dist(m_pMyEnt->o);
 
302
}
 
303
 
 
304
bool CBot::SelectGun(int Gun)
 
305
{
 
306
        if(m_pMyEnt->weaponsel->reloading) return false;
 
307
    if (m_pMyEnt->gunselect != Gun) playsound(S_GUNCHANGE, m_pMyEnt);
 
308
    m_pMyEnt->gunselect = Gun;
 
309
    return true;
 
310
}
 
311
 
 
312
bool CBot::IsVisible(entity *e, bool CheckPlayers)
 
313
{
 
314
     vec v(e->x, e->y, e->z);
 
315
     return ::IsVisible(m_pMyEnt->o, v, (CheckPlayers) ? m_pMyEnt : NULL);
 
316
}
 
317
 
 
318
bool CBot::IsVisible(vec o, int Dir, float flDist, bool CheckPlayers, float *pEndDist)
 
319
{
 
320
     static vec angles, end, forward, right, up;
 
321
     static traceresult_s tr;
 
322
        
 
323
     end = o;
 
324
     angles = GetViewAngles();
 
325
     angles.x = 0;
 
326
          
 
327
     if (Dir & UP)
 
328
          angles.x = WrapXAngle(angles.x + 45.0f);
 
329
     else if (Dir & DOWN)
 
330
          angles.x = WrapXAngle(angles.x - 45.0f);
 
331
          
 
332
     if ((Dir & FORWARD) || (Dir & BACKWARD))
 
333
     {
 
334
          if (Dir & BACKWARD)
 
335
               angles.y = WrapYZAngle(angles.y + 180.0f);
 
336
          
 
337
          if (Dir & LEFT)
 
338
          {
 
339
               if (Dir & FORWARD)
 
340
                    angles.y = WrapYZAngle(angles.y - 45.0f);
 
341
               else
 
342
                    angles.y = WrapYZAngle(angles.y + 45.0f);
 
343
          }
 
344
          else if (Dir & RIGHT)
 
345
          {
 
346
               if (Dir & FORWARD)
 
347
                    angles.y = WrapYZAngle(angles.y + 45.0f);
 
348
               else
 
349
                    angles.y = WrapYZAngle(angles.y - 45.0f);
 
350
          }
 
351
     }
 
352
     else if (Dir & LEFT)
 
353
          angles.y = WrapYZAngle(angles.y - 90.0f);
 
354
     else if (Dir & RIGHT)
 
355
          angles.y = WrapYZAngle(angles.y + 90.0f);
 
356
     else if (Dir & UP)
 
357
          angles.x = WrapXAngle(angles.x + 90.0f);
 
358
     else if (Dir & DOWN)
 
359
          angles.x = WrapXAngle(angles.x - 90.0f);
 
360
               
 
361
     AnglesToVectors(angles, forward, right, up);
 
362
     
 
363
     forward.mul(flDist);
 
364
     end.add(forward);
 
365
         
 
366
     TraceLine(o, end, m_pMyEnt, CheckPlayers, &tr);
 
367
     
 
368
     if (pEndDist)
 
369
          *pEndDist = GetDistance(o, tr.end);
 
370
          
 
371
     return !tr.collided;
 
372
}
 
373
 
 
374
void CBot::SetMoveDir(int iMoveDir, bool add)
 
375
{
 
376
     if (iMoveDir & FORWARD)
 
377
          m_pMyEnt->move = 1;
 
378
     else if (m_iMoveDir & BACKWARD)
 
379
          m_pMyEnt->move = -1;
 
380
     else if (!add)
 
381
          m_pMyEnt->move = 0;
 
382
 
 
383
     if (iMoveDir & LEFT)
 
384
          m_pMyEnt->strafe = 1;
 
385
     else if (m_iMoveDir & RIGHT)
 
386
          m_pMyEnt->strafe = -1;
 
387
     else if (!add)
 
388
          m_pMyEnt->strafe = 0;
 
389
          
 
390
     if (iMoveDir & UP)
 
391
          m_pMyEnt->jumpnext = true;
 
392
}
 
393
 
 
394
// Used when switching to another task/state
 
395
void CBot::ResetCurrentTask()
 
396
{
 
397
     switch (m_eCurrentBotState)
 
398
     {
 
399
     case STATE_ENEMY:
 
400
          m_pMyEnt->enemy = NULL;
 
401
          m_pTargetEnt = NULL;
 
402
          m_iCombatNavTime = m_iMoveDir = 0;
 
403
          m_bCombatJump = false;
 
404
          m_vGoal = g_vecZero;
 
405
          break;
 
406
     case STATE_ENT:
 
407
          m_pTargetEnt = NULL;
 
408
          m_vGoal = g_vecZero;
 
409
          break;
 
410
     case STATE_SP:
 
411
          m_iSPMoveTime = m_iMoveDir = 0;
 
412
          m_pTargetEnt = NULL;
 
413
          m_vGoal = g_vecZero;
 
414
          break;
 
415
     case STATE_NORMAL:
 
416
          m_iStrafeTime = m_iMoveDir = 0;
 
417
          break;
 
418
     default:
 
419
          break;
 
420
     }
 
421
}
 
422
          
 
423
// Bot class end