📄 g_ai.pas
字号:
(* =============
ai_run_slide
Strafe sideways, but stay at aproximately the same range
============= *)
procedure ai_run_slide(self: Pedict_t, distance: Single);
var
ofs: Single;
begin
self^.ideal_yaw := enemy_yaw;
M_ChangeYaw(self);
if (self^.monsterinfo.lefty) then
ofs := 90
else
ofs := -90;
if (M_walkmove(self, self^.ideal_yaw + ofs, distance)) then
Exit;
self^.monsterinfo.lefty := (1 - self^.monsterinfo.lefty);
M_walkmove(self, (self^.ideal_yaw - ofs), distance);
end;
(* =============
ai_checkattack
Decides if we're going to attack or do something else
used by ai_run and ai_stand
============= *)
function ai_checkattack(self: Pedict_t; dist: Single): qboolean;
var
temp: vec3_t;
hesDeadJim: qboolean;s
begin
{ this causes monsters to run blindly to the combat point w/o firing }
if (self^.goalentity) then begin
if (self^.monsterinfo.aiflags AND AI_COMBAT_POINT) <> 0 then begin
Result := False;
Exit;
end;
if (self^.monsterinfo.aiflags AND AI_SOUND_TARGET) <> 0 then begin
if ((level.time - self^.enemy^.teleport_time) > 5.0) then begin
if (self^.goalentity = self^.enemy) then begin
if (self^.movetarget) then
self^.goalentity := self^.movetarget
else
self^.goalentity := NULL;
end;
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags &= ~AI_SOUND_TARGET;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT AI_SOUND_TARGET);
if (self^.monsterinfo.aiflags AND AI_TEMP_STAND_GROUND) <> 0 then
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT (AI_STAND_GROUND OR AI_TEMP_STAND_GROUND));
end else begin
self^.show_hostile := (level.time + 1);
Result := False;
Exit;
end;
end;
end;
enemy_vis := False;
{ see if the enemy is dead }
hesDeadJim := False;
{ TODO: Translate the Line Below: }
if ((self^.enemy = Nil) OR (NOT self^.enemy^.inuse)) then
hesDeadJim := True
else if (self^.monsterinfo.aiflags AND AI_MEDIC) then begin
if (self^.enemy^.health > 0) then begin
hesDeadJim := True;
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags &= ~AI_MEDIC;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT AI_MEDIC);
end;
end else begin
if (self^.monsterinfo.aiflags AND AI_BRUTAL) <> 0 then begin
if (self^.enemy^.health <= -80) then
hesDeadJim := True;
end else begin
if (self^.enemy^.health <= 0) then
hesDeadJim := True;
end;
end;
if (hesDeadJim) then begin
self^.enemy := NULL;
// FIXME: look all around for other targets
{ TODO: Translate the Line Below: }
// ORIGINAL: if (self->oldenemy && self->oldenemy->health > 0)
if ((self^.oldenemy <> Nil) AND (self^.oldenemy^.health > 0)) then begin
self^.enemy := self^.oldenemy;
self^.oldenemy := NULL;
HuntTarget(self);
end else begin
if (self^.movetarget) then begin
self^.goalentity := self^.movetarget;
self^.monsterinfo.walk(self);
end else begin
{ we need the pausetime otherwise the stand code
will just revert to walking with no target and
the monsters will wonder around aimlessly trying
to hunt the world entity }
self^.monsterinfo.pausetime := (level.time + 100000000);
self^.monsterinfo.stand(self);
end;
Result := True;
Exit;
end;
end;
{ wake up other monsters }
self^.show_hostile := (level.time + 1);
{ check knowledge of enemy }
enemy_vis := visible(self, self^.enemy);
if (enemy_vis) then begin
self^.monsterinfo.search_time := (level.time + 5);
VectorCopy(self^.enemy^.s.origin, self^.monsterinfo.last_sighting);
end;
// look for other coop players here
// if (coop && self->monsterinfo.search_time < level.time)
// {
// if (FindTarget (self))
// return true;
// }
enemy_infront := infront(self, self^.enemy);
enemy_range := range(self, self^.enemy);
VectorSubtract(self^.enemy^.s.origin, self^.s.origin, temp);
enemy_yaw := vectoyaw(temp);
// JDC self->ideal_yaw = enemy_yaw;
if (self^.monsterinfo.attack_state = AS_MISSILE) then begin
ai_run_missile(self);
Result := True;
Exit;
end;
if (self^.monsterinfo.attack_state = AS_MELEE) then begin
ai_run_melee(self);
Result := True;
end;
{ if enemy is not currently visible, we will never attack }
if (NOT enemy_vis) then begin
Result := False;
Exit;
end;
Result := self^.monsterinfo.checkattack(self);
end;
(* =============
ai_run
The monster has an enemy it is trying to kill
============= *)
procedure ai_run(self: Pedict_t; dist: Single);
var
v, v_forward, v_right, left_target, right_target: vec3_t;
tempgoal, save, marker: Pedict_t;
new: qboolean;
d1, d2, left, center, right: Single {float};
tr: trace_t;
begin
{ Originally Removed comments by ID start the line like:
// eg...}
{ if we're going to a combat point, just proceed }
if (self^.monsterinfo.aiflags AND AI_COMBAT_POINT) <> 0 then begin
M_MoveToGoal(self, dist);
Exit;
end;
if (self^.monsterinfo.aiflags AND AI_SOUND_TARGET) <> 0 then begin
VectorSubtract(self^.s.origin, self^.enemy^.s.origin, v);
if (VectorLength(v) < 64) then begin
{ TODO: Translate the Line Below: }
// ORIGINAL: self^.monsterinfo.aiflags |= (AI_STAND_GROUND OR AI_TEMP_STAND_GROUND);
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags OR (AI_STAND_GROUND OR AI_TEMP_STAND_GROUND);
self^.monsterinfo.stand(self);
Exit;
end;
M_MoveToGoal(self, dist);
if (NOT FindTarget(self)) then
Exit;
end;
if (ai_checkattack(self, dist)) then
Exit;
if (self^.monsterinfo.attack_state = AS_SLIDING) then begin
ai_run_slide(self, dist);
Exit;
end;
if (enemy_vis) then begin
// if (self.aiflags & AI_LOST_SIGHT)
// dprint("regained sight\n");
M_MoveToGoal(self, dist);
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT AI_LOST_SIGHT);
VectorCopy(self^.enemy^.s.origin, self^.monsterinfo.last_sighting);
self^.monsterinfo.trail_time := level.time;
Exit;
end;
{ coop will change to another enemy if visible }
if (coop^.value) then begin
// FIXME: insane guys get mad with this, which causes crashes!
if (FindTarget(self)) then
Exit;
end;
{ TODO: Translate the Line Below: }
// ORIGINAL: if ((self->monsterinfo.search_time) && (level.time > (self->monsterinfo.search_time + 20)))
if ((self^.monsterinfo.search_time <> 0) AND (level.time > (self^.monsterinfo.search_time + 20))) then begin
M_MoveToGoal(self, dist);
self^.monsterinfo.search_time := 0;
// dprint("search timeout\n");
Exit;
end;
save := self^.goalentity;
tempgoal := G_Spawn();
self^.goalentity := tempgoal;
new := False;
if ((self^.monsterinfo.aiflags AND AI_LOST_SIGHT) = 0) then begin
// just lost sight of the player, decide where to go first
// dprint("lost sight of player, last seen at "); dprint(vtos(self.last_sighting)); dprint("\n");
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags |= (AI_LOST_SIGHT | AI_PURSUIT_LAST_SEEN);
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags OR (AI_LOST_SIGHT OR AI_PURSUIT_LAST_SEEN);
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags &= ~(AI_PURSUE_NEXT | AI_PURSUE_TEMP);
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT (AI_PURSUE_NEXT OR AI_PURSUE_TEMP));
new := True;
end;
if (self^.monsterinfo.aiflags AND AI_PURSUE_NEXT) <> 0 then begin
{ TODO: Translate the Line Below: }
// ORIGINAL: self^.monsterinfo.aiflags &= ~AI_PURSUE_NEXT;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT AI_PURSUE_NEXT);
// dprint("reached current goal: "); dprint(vtos(self.origin)); dprint(" "); dprint(vtos(self.last_sighting)); dprint(" "); dprint(ftos(vlen(self.origin - self.last_sighting))); dprint("\n");
{ give ourself more time since we got this far }
self^.monsterinfo.search_time := (level.time + 5);
if (self^.monsterinfo.aiflags AND AI_PURSUE_TEMP) then begin
// dprint("was temp goal; retrying original\n");
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags &= ~AI_PURSUE_TEMP;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT AI_PURSUE_TEMP);
marker := NULL;
VectorCopy(self^.monsterinfo.saved_goal, self^.monsterinfo.last_sighting);
new := True;
end else if (self^.monsterinfo.aiflags AND AI_PURSUIT_LAST_SEEN) then begin
{ TODO: Translate the Line Below: }
// ORIGINAL: self^.monsterinfo.aiflags &= ~AI_PURSUIT_LAST_SEEN;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags AND (NOT AI_PURSUIT_LAST_SEEN);
marker := PlayerTrail_PickFirst(self);
end else begin
marker := PlayerTrail_PickNext(self);
end;
if (marker) then begin
VectorCopy(marker^.s.origin, self^.monsterinfo.last_sighting);
self^.monsterinfo.trail_time := marker^.timestamp;
// self->s.angles[YAW] = self->ideal_yaw = marker->s.angles[YAW];
self^.ideal_yaw := marker^.s.angles[YAW];
self^.s.angles[YAW] := self^.ideal_yaw;
// dprint("heading is "); dprint(ftos(self.ideal_yaw)); dprint("\n");
// debug_drawline(self.origin, self.last_sighting, 52);
new := True;
end;
end;
VectorSubtract(self^.s.origin, self^.monsterinfo.last_sighting, v);
d1 := VectorLength(v);
if (d1 <= dist) then begin
{ TODO: Translate the Line Below: }
// ORIGINAL: self^.monsterinfo.aiflags |= AI_PURSUE_NEXT;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags OR AI_PURSUE_NEXT;
dist := d1;
end;
VectorCopy(self^.monsterinfo.last_sighting, self^.goalentity^.s.origin);
if (new) then begin
// gi.dprintf("checking for course correction\n");
tr := gi.trace(self^.s.origin, self^.mins, self^.maxs, self^.monsterinfo.last_sighting, self, MASK_PLAYERSOLID);
if (tr.fraction < 1) then begin
VectorSubtract(self^.goalentity^.s.origin, self^.s.origin, v);
d1 := VectorLength(v);
center := tr.fraction;
d2 := (d1 * ((center + 1) / 2));
//self^.s.angles[YAW] = self^.ideal_yaw = vectoyaw(v);
self^.ideal_yaw := vectoyaw(v);
self^.s.angles[YAW] := self^.ideal_yaw;
AngleVectors(self^.s.angles, v_forward, v_right, NULL);
VectorSet(v, d2, -16, 0);
G_ProjectSource(self^.s.origin, v, v_forward, v_right, left_target);
tr := gi.trace(self^.s.origin, self^.mins, self^.maxs, left_target, self, MASK_PLAYERSOLID);
left := tr.fraction;
VectorSet(v, d2, 16, 0);
G_ProjectSource(self^.s.origin, v, v_forward, v_right, right_target);
tr := gi.trace(self^.s.origin, self^.mins, self^.maxs, right_target, self, MASK_PLAYERSOLID);
right := tr.fraction;
center := ((d1 * center) / d2);
{ TODO: Translate the Line Below: }
// ORIGINAL: if (left >= center && left > right)
if ((left >= center) AND (left > right)) then begin
if (left < 1) then begin
VectorSet(v, (d2 * left * 0.5), -16, 0);
G_ProjectSource(self^.s.origin, v, v_forward, v_right, left_target);
// gi.dprintf("incomplete path, go part way and adjust again\n");
end;
VectorCopy(self^.monsterinfo.last_sighting, self^.monsterinfo.saved_goal);
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags |= AI_PURSUE_TEMP;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags OR AI_PURSUE_TEMP;
VectorCopy(left_target, self^.goalentity^.s.origin);
VectorCopy(left_target, self^.monsterinfo.last_sighting);
VectorSubtract(self^.goalentity^.s.origin, self^.s.origin, v);
//self^.s.angles[YAW] = self^.ideal_yaw = vectoyaw(v);
self^.ideal_yaw := vectoyaw(v);
self^.s.angles[YAW] := self^.ideal_yaw;
// gi.dprintf("adjusted left\n");
// debug_drawline(self.origin, self.last_sighting, 152);
{ TODO: Translate the Line Below: }
end else if ((right >= center) AND (right > left)) then begin
if (right < 1) then begin
VectorSet(v, (d2 * right * 0.5), 16, 0);
G_ProjectSource(self^.s.origin, v, v_forward, v_right, right_target);
// gi.dprintf("incomplete path, go part way and adjust again\n");
end;
VectorCopy(self^.monsterinfo.last_sighting, self^.monsterinfo.saved_goal);
{ TODO: Translate the Line Below: }
// ORIGINAL: self->monsterinfo.aiflags |= AI_PURSUE_TEMP;
self^.monsterinfo.aiflags := self^.monsterinfo.aiflags OR AI_PURSUE_TEMP;
VectorCopy(right_target, self^.goalentity^.s.origin);
VectorCopy(right_target, self^.monsterinfo.last_sighting);
VectorSubtract(self^.goalentity^.s.origin, self^.s.origin, v);
//self^.s.angles[YAW] = self^.ideal_yaw = vectoyaw(v);
self^.ideal_yaw := vectoyaw(v);
self^.s.angles[YAW] := self^.ideal_yaw;
// gi.dprintf("adjusted right\n");
// debug_drawline(self.origin, self.last_sighting, 152);
end;
end;
// else gi.dprintf("course was fine\n");
end;
M_MoveToGoal(self, dist);
G_FreeEdict(tempgoal);
if (self) then
self^.goalentity := save;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -