109 VectorSubtract(self->enemy->s.origin, self->s.origin, v);
111 if (self->s.angles[YAW] != self->ideal_yaw && self->monsterinfo.aiflags &
AI_TEMP_STAND_GROUND) {
113 self->monsterinfo.run(
self);
125 if (
level.
time > self->monsterinfo.pausetime) {
126 self->monsterinfo.walk(
self);
130 if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (
level.
time > self->monsterinfo.idle_time)) {
131 if (self->monsterinfo.idle_time) {
132 self->monsterinfo.idle(
self);
156 if ((self->monsterinfo.search) && (
level.
time > self->monsterinfo.idle_time)) {
157 if (self->monsterinfo.idle_time) {
158 self->monsterinfo.search(
self);
179 VectorSubtract(self->enemy->s.origin, self->s.origin, v);
250 VectorSubtract(self->s.origin,
other->s.origin, v);
251 len = VectorLength(v);
274 VectorCopy(self->s.origin, spot1);
275 spot1[2] +=
self->viewheight;
276 VectorCopy(
other->s.origin, spot2);
277 spot2[2] +=
other->viewheight;
280 if (trace.fraction == 1.0)
300 VectorSubtract(
other->s.origin, self->s.origin, vec);
302 dot = DotProduct(vec,
forward);
316 self->goalentity =
self->enemy;
318 self->monsterinfo.stand(
self);
320 self->monsterinfo.run(
self);
321 VectorSubtract(self->enemy->s.origin, self->s.origin, vec);
331 if (self->enemy->client) {
339 VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting);
340 self->monsterinfo.trail_time =
level.
time;
342 if (!self->combattarget) {
347 self->goalentity =
self->movetarget =
G_PickTarget(self->combattarget);
348 if (!self->movetarget) {
349 self->goalentity =
self->movetarget =
self->enemy;
351 gi.dprintf(
"%s at %s, combattarget %s not found\n", self->classname,
vtos(self->s.origin), self->combattarget);
356 self->combattarget = NULL;
360 self->movetarget->targetname = NULL;
361 self->monsterinfo.pausetime = 0;
364 self->monsterinfo.run(
self);
392 if (self->goalentity && self->goalentity->inuse && self->goalentity->classname) {
393 if (strcmp(self->goalentity->classname,
"target_actor") == 0)
415 if (client->enemy == self->enemy) {
434 if (client == self->enemy)
437 if (client->client) {
440 }
else if (client->svflags & SVF_MONSTER) {
445 }
else if (heardit) {
452 r =
range(
self, client);
460 if (client->light_level <= 5)
477 self->enemy = client;
479 if (strcmp(self->enemy->classname,
"player_noise") != 0) {
482 if (!self->enemy->client) {
483 self->enemy =
self->enemy->enemy;
484 if (!self->enemy->client) {
493 if (self->spawnflags & 1) {
497 if (!
gi.inPHS(self->s.origin, client->s.origin))
501 VectorSubtract(client->s.origin, self->s.origin, temp);
503 if (VectorLength(temp) > 1000) {
508 if (client->areanum != self->areanum)
509 if (!
gi.AreasConnected(self->areanum, client->areanum))
517 self->enemy = client;
525 if (!(self->monsterinfo.aiflags &
AI_SOUND_TARGET) && (self->monsterinfo.sight))
526 self->monsterinfo.sight(
self, self->enemy);
544 delta = anglemod(self->s.angles[YAW] - self->ideal_yaw);
545 if (delta > 45 && delta < 315)
559 if (self->enemy->health > 0) {
561 VectorCopy(self->s.origin, spot1);
562 spot1[2] +=
self->viewheight;
563 VectorCopy(self->enemy->s.origin, spot2);
564 spot2[2] +=
self->enemy->viewheight;
566 tr =
gi.trace(spot1, NULL, NULL, spot2,
self, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_WINDOW);
569 if (tr.ent != self->enemy)
576 if (
skill->value == 0 && (rand() & 3))
578 if (self->monsterinfo.melee)
579 self->monsterinfo.attack_state =
AS_MELEE;
586 if (!self->monsterinfo.attack)
589 if (
level.
time < self->monsterinfo.attack_finished)
607 if (
skill->value == 0)
609 else if (
skill->value >= 2)
618 if (self->flags &
FL_FLY) {
642 self->monsterinfo.melee(
self);
661 self->monsterinfo.attack(
self);
681 if (self->monsterinfo.lefty)
686 if (
M_walkmove(
self, self->ideal_yaw + ofs, distance))
689 self->monsterinfo.lefty = 1 -
self->monsterinfo.lefty;
690 M_walkmove(
self, self->ideal_yaw - ofs, distance);
708 if (self->goalentity) {
713 if ((
level.
time - self->enemy->teleport_time) > 5.0) {
714 if (self->goalentity == self->enemy) {
715 if (self->movetarget)
716 self->goalentity =
self->movetarget;
718 self->goalentity = NULL;
734 if ((!self->enemy) || (!
self->enemy->inuse)) {
736 }
else if (self->monsterinfo.aiflags &
AI_MEDIC) {
737 if (self->enemy->health > 0) {
739 self->monsterinfo.aiflags &= ~
AI_MEDIC;
742 if (self->monsterinfo.aiflags &
AI_BRUTAL) {
743 if (self->enemy->health <= -80)
746 if (self->enemy->health <= 0)
754 if (self->oldenemy && self->oldenemy->health > 0) {
755 self->enemy =
self->oldenemy;
756 self->oldenemy = NULL;
759 if (self->movetarget) {
760 self->goalentity =
self->movetarget;
761 self->monsterinfo.walk(
self);
767 self->monsterinfo.pausetime =
level.
time + 100000000;
768 self->monsterinfo.stand(
self);
779 self->monsterinfo.search_time =
level.
time + 5;
780 VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting);
791 VectorSubtract(self->enemy->s.origin, self->s.origin, temp);
797 if (self->monsterinfo.attack_state ==
AS_MISSILE) {
801 if (self->monsterinfo.attack_state ==
AS_MELEE) {
810 return self->monsterinfo.checkattack(
self);
830 vec3_t v_forward, v_right;
831 float left, center,
right;
832 vec3_t left_target, right_target;
841 VectorSubtract(self->s.origin, self->enemy->s.origin, v);
842 if (VectorLength(v) < 64) {
844 self->monsterinfo.stand(
self);
857 if (self->monsterinfo.attack_state ==
AS_SLIDING) {
867 VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting);
868 self->monsterinfo.trail_time =
level.
time;
879 if ((self->monsterinfo.search_time) && (
level.
time > (self->monsterinfo.search_time + 20))) {
881 self->monsterinfo.search_time = 0;
886 save =
self->goalentity;
888 self->goalentity = tempgoal;
905 self->monsterinfo.search_time =
level.
time + 5;
911 VectorCopy(self->monsterinfo.saved_goal, self->monsterinfo.last_sighting);
921 VectorCopy(marker->s.origin, self->monsterinfo.last_sighting);
922 self->monsterinfo.trail_time = marker->timestamp;
923 self->s.angles[YAW] =
self->ideal_yaw = marker->s.angles[YAW];
931 VectorSubtract(self->s.origin, self->monsterinfo.last_sighting, v);
932 d1 = VectorLength(v);
938 VectorCopy(self->monsterinfo.last_sighting, self->goalentity->s.origin);
943 tr =
gi.trace(self->s.origin, self->mins, self->maxs, self->monsterinfo.last_sighting,
self, MASK_PLAYERSOLID);
944 if (tr.fraction < 1) {
945 VectorSubtract(self->goalentity->s.origin, self->s.origin, v);
946 d1 = VectorLength(v);
947 center = tr.fraction;
948 d2 = d1 * ((center + 1) / 2);
949 self->s.angles[YAW] =
self->ideal_yaw =
vectoyaw(v);
952 VectorSet(v, d2, -16, 0);
954 tr =
gi.trace(self->s.origin, self->mins, self->maxs, left_target,
self, MASK_PLAYERSOLID);
957 VectorSet(v, d2, 16, 0);
959 tr =
gi.trace(self->s.origin, self->mins, self->maxs, right_target,
self, MASK_PLAYERSOLID);
962 center = (d1 * center) / d2;
963 if (left >= center && left >
right) {
965 VectorSet(v, d2 * left * 0.5, -16, 0);
969 VectorCopy(self->monsterinfo.last_sighting, self->monsterinfo.saved_goal);
971 VectorCopy(left_target, self->goalentity->s.origin);
972 VectorCopy(left_target, self->monsterinfo.last_sighting);
973 VectorSubtract(self->goalentity->s.origin, self->s.origin, v);
974 self->s.angles[YAW] =
self->ideal_yaw =
vectoyaw(v);
979 VectorSet(v, d2 *
right * 0.5, 16, 0);
983 VectorCopy(self->monsterinfo.last_sighting, self->monsterinfo.saved_goal);
985 VectorCopy(right_target, self->goalentity->s.origin);
986 VectorCopy(right_target, self->monsterinfo.last_sighting);
987 VectorSubtract(self->goalentity->s.origin, self->s.origin, v);
988 self->s.angles[YAW] =
self->ideal_yaw =
vectoyaw(v);
1001 self->goalentity = save;