1 #include "g_local.h" 2 3 4 /* 5 ============================================================================== 6 7 PLAYER TRAIL 8 9 ============================================================================== 10 11 This is a circular list containing the a list of points of where 12 the player has been recently. It is used by monsters for pursuit. 13 14 .origin the spot 15 .owner forward link 16 .aiment backward link 17 */ 18 19 20 #define TRAIL_LENGTH 8 21 22 edict_t *trail[TRAIL_LENGTH]; 23 int trail_head; 24 qboolean trail_active = false; 25 26 #define NEXT(n) (((n) + 1) & (TRAIL_LENGTH - 1)) 27 #define PREV(n) (((n) - 1) & (TRAIL_LENGTH - 1)) 28 29 PlayerTrail_Init(void)30void PlayerTrail_Init (void) 31 { 32 int n; 33 34 if (deathmatch->value /* FIXME || coop */) 35 return; 36 37 for (n = 0; n < TRAIL_LENGTH; n++) 38 { 39 trail[n] = G_Spawn(); 40 trail[n]->classname = "player_trail"; 41 } 42 43 trail_head = 0; 44 trail_active = true; 45 } 46 47 PlayerTrail_Add(vec3_t spot)48void PlayerTrail_Add (vec3_t spot) 49 { 50 vec3_t temp; 51 52 if (!trail_active) 53 return; 54 55 VectorCopy (spot, trail[trail_head]->s.origin); 56 57 trail[trail_head]->timestamp = level.time; 58 59 VectorSubtract (spot, trail[PREV(trail_head)]->s.origin, temp); 60 trail[trail_head]->s.angles[1] = vectoyaw (temp); 61 62 trail_head = NEXT(trail_head); 63 } 64 65 PlayerTrail_New(vec3_t spot)66void PlayerTrail_New (vec3_t spot) 67 { 68 if (!trail_active) 69 return; 70 71 PlayerTrail_Init (); 72 PlayerTrail_Add (spot); 73 } 74 75 PlayerTrail_PickFirst(edict_t * self)76edict_t *PlayerTrail_PickFirst (edict_t *self) 77 { 78 int marker; 79 int n; 80 81 if (!trail_active) 82 return NULL; 83 84 for (marker = trail_head, n = TRAIL_LENGTH; n; n--) 85 { 86 if(trail[marker]->timestamp <= self->monsterinfo.trail_time) 87 marker = NEXT(marker); 88 else 89 break; 90 } 91 92 if (visible(self, trail[marker])) 93 { 94 return trail[marker]; 95 } 96 97 if (visible(self, trail[PREV(marker)])) 98 { 99 return trail[PREV(marker)]; 100 } 101 102 return trail[marker]; 103 } 104 PlayerTrail_PickNext(edict_t * self)105edict_t *PlayerTrail_PickNext (edict_t *self) 106 { 107 int marker; 108 int n; 109 110 if (!trail_active) 111 return NULL; 112 113 for (marker = trail_head, n = TRAIL_LENGTH; n; n--) 114 { 115 if(trail[marker]->timestamp <= self->monsterinfo.trail_time) 116 marker = NEXT(marker); 117 else 118 break; 119 } 120 121 return trail[marker]; 122 } 123 PlayerTrail_LastSpot(void)124edict_t *PlayerTrail_LastSpot (void) 125 { 126 return trail[PREV(trail_head)]; 127 } 128