📄 m_move.pas
字号:
G_TouchTriggers (ent);
end;
result := True;
end;
VectorCopy (oldorg, ent^.s.origin);
result := False;
end;
if (ent^.flags and FL_PARTILGROUND) then
begin
ent^.flags := ent^.flags and (not FL_PARTILGROUND);
end;
ent^.groundentity := trace.ent;
ent^.groundentity_linkcount := trace.ent^.linkcount;
// the move is ok
if relink then
begin
gi.linkentity (ent);
G_TouchTriggers (ent);
end;
result := True;
end;
//============================================================================
(*
===============
M_ChangeYaw
===============
*)
procedure M_ChangeYaw (ent:pedict);
var ideal:single;
current:single;
move:single;
speed:single;
begin
current := anglemod (ent^.s.angles[YAW]);
ideal := ent^.ideal_yaw;
if current = ideal then
exit;
move := ideal - current;
speed := ent^.yaw_speed;
if ideal > current then
begin
if move >= 180 then
move := move - 360;
end
else
begin
if move <= -180 then
move := move + 360;
end;
if move >0 then
begin
if move > speed then
move := speed;
end
else
begin
if move < -speed then
move := -speed;
end;
ent^.s.angles[YAW] := anglemod (current + move);
end;
(*
======================
SV_StepDirection
Turns to the movement direction, and walks the current distance if
facing it.
======================
*)
function SV_StepDirection (ent:pedict_t; yaw:single; dist:single):qboolean;
var move, oldorigin:vec3_t;
delta:single;
begin
ent^.ideal_yaw := yaw;
M_ChangeYaw (ent);
yaw := yaw*M_PI*2 / 360;
move[0] := cos(yaw)*dist;
move[1] := sin(yaw)*dist;
move[2] := 0;
VectorCopy (ent^.s.origin, oldorigin);
if (SV_movestep (ent, move, false))
begin
delta := ent^s.angles[YAW] - ent^.ideal_yaw;
if ((delta > 45) and (delta < 315))
begin // not turned far enough, so don't take the step
VectorCopy (oldorigin, ent^.s.origin);
end;
gi.linkentity (ent);
G_TouchTriggers (ent);
result := True;
end;
gi.linkentity (ent);
G_TouchTriggers (ent);
result := False;
end;
(*
======================
SV_FixCheckBottom
======================
*)
procedure SV_FixCheckBottom (ent:pedict_t);
begin
ent^.flags := ent^.flags or FL_PARTIALGROUND;
end;
(*
================
SV_NewChaseDir
================
*)
const DI_NODIR = -1;
procedure SV_NewChaseDir (actor:pedict_t; enemy:pedict_t; dist:single);
var deltax,deltay:single;
d[3]:single;
tdir, olddir, turnaround:single;
begin
//FIXME: how did we get here with no enemy
if not (enemy) then
exit;
olddir := anglemod( int((actor^.ideal_yaw/45)*45) );
turnaround := anglemod(olddir - 180);
deltax := enemy^.s.origin[0] - actor^.s.origin[0];
deltay := enemy^.s.origin[1] - actor^.s.origin[1];
if (deltax>10) then
d[1] := 0;
else if (deltax<-10) then
d[1] := 180;
else
d[1] := DI_NODIR;
if (deltay<-10) then
d[2] := 270;
else if (deltay>10) then
d[2] := 90;
else
d[2] := DI_NODIR;
// try direct route
if ((d[1] <> DI_NODIR) and (d[2] <> DI_NODIR)) then
begin
if (d[1] = 0) then
begin
if d[2] = 90 then d[2] := 45
else d[2] := 315;
tdir := d[2];
end
else
begin
if d[2] = 90 then d[2] := 135
else d[2] := 215;
tdir := d[2];
end;
if ((tdir <> turnaround) and (SV_StepDirection(actor, tdir, dist))) then
exit;
end;
// try other directions
if ( ((random(360)and 3) and 1) or abs(deltay)>abs(deltax)) then //??
begin
tdir:=d[1];
d[1]:=d[2];
d[2]:=tdir;
end;
if ((d[1] <> DI_NODIR) and (d[1] <> turnaround)
and (SV_StepDirection(actor, d[1], dist))) then
exit;
if ((d[2]<>DI_NODIR) and (d[2]<>turnaround)
and (SV_StepDirection(actor, d[2], dist))) then
exit;
(* there is no direct path to the player, so pick another direction *)
if ((olddir <> DI_NODIR) and (SV_StepDirection(actor, olddir, dist))) then
exit;
if (random(360) and 1) then (*randomly determine direction of search*)
begin
for tdir := 0 to 315 do
begin
tdir := tdir + 45;
if ((tdir<>turnaround) and (SV_StepDirection(actor, tdir, dist)) ) then
exit;
end;
end
else
begin
for tdir :=315 downto 0 do
begin
tdir := tdir - 45;
if ((tdir<>turnaround) and (SV_StepDirection(actor, tdir, dist)) ) then
exit;
end;
end;
if ((turnaround <> DI_NODIR) and (SV_StepDirection(actor, turnaround, dist)) ) then
exit;
actor^.ideal_yaw = olddir; // can't move
// if a bridge was pulled out from underneath a monster, it may not have
// a valid standing position at all
if (not M_CheckBottom (actor)) then
SV_FixCheckBottom (actor);
end;
(*
======================
SV_CloseEnough
======================
*)
function SV_CloseEnough (ent:pedict_t; goal:pedict_t; dist:single):qboolean;
var
i:smallint;
begin
for i:=0 to 2 do
begin
if (goal^.absmin[i] > ent^.absmax[i] + dist) then
result := false;
if (goal^.absmax[i] < ent^.absmin[i] - dist) then
result := false;
end;
result :=true;
end;
(*
======================
M_MoveToGoal
======================
*)
procedure M_MoveToGoal (ent:pedict_t; dist:single);
var
goal:pedict_t;
begin
goal := ent^.goalentity;
if (not ent^.groundentity and not(ent^.flags and (FL_FLY or FL_SWIM))) then
exit;
// if the next step hits the enemy, return immediately
if (ent^.enemy and SV_CloseEnough (ent, ent^.enemy, dist) ) then
exit;
// bump around...
if ( (random(360)and 3)=1 or not SV_StepDirection (ent, ent^.ideal_yaw, dist)) then
begin
if (ent^.inuse) then
SV_NewChaseDir (ent, goal, dist);
end;
end;
(*
===============
M_walkmove
===============
*)
function M_walkmove (ent:pedict_t; yaw:single; dist:single):qboolean;
var
move:vec3_t;
begin
if (not ent^.groundentity and not(ent^.flags and (FL_FLY or FL_SWIM))) then
result := false;
yaw := yaw*M_PI*2 / 360;
move[0] := cos(yaw)*dist;
move[1] := sin(yaw)*dist;
move[2] := 0;
result := SV_movestep(ent, move, true);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -