📄 m_move.pas
字号:
//100%
{----------------------------------------------------------------------------}
{ }
{ File(s): m_move.c }
{ Content: monster movement }
{ }
{ Initial conversion by : you_known (you_known@163.com) }
{ Initial conversion on : 2002-02-02 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ Copyright (C) 1997-2001 Id Software, Inc. }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
{ }
{ See the GNU General Public License for more details. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : 2003-Apr-17 }
{ Updated by : Scott Price (scott.price@totalise.co.uk) }
{ Updated on : 2003-May-19 }
{ Updated by : Scott Price (scott.price@totalise.co.uk) }
{ }
{----------------------------------------------------------------------------}
{ Notes: }
{----------------------------------------------------------------------------}
unit m_move;
interface
uses
q_shared,
g_local;
function M_walkmove (ent: edict_p; yaw: single; dist: single): qboolean;
procedure M_MoveToGoal (ent: edict_p; dist: single);
procedure M_ChangeYaw (ent: edict_p);
function M_CheckBottom(ent: edict_p): qboolean;
implementation
uses
GameUnit,
g_utils, g_main, CPas;
const
STEPSIZE = 18;
(*
=============
M_CheckBottom
Returns false if any part of the bottom of the entity is off an edge that
is not a staircase.
=============
*)
var
c_yes, c_no: Smallint;
function M_CheckBottom(ent: edict_p): qboolean;
label
realcheck;
var
mins, maxs, start, stop: vec3_t;
trace: trace_t;
x, y: Smallint;
mid, bottom: Single;
begin
VectorAdd(ent^.s.origin, ent^.mins, mins);
VectorAdd(ent^.s.origin, ent^.maxs, maxs);
// if all of the points under the corners are solid world, don't bother
// with the tougher checks
// the corners must be within 16 of the midpoint
start[2] := mins[2] - 1;
for x := 0 to 1 do
for y := 0 to 1 do
begin
if x <> 0 then
start[0] := maxs[0]
else
start[0] := mins[0];
if y <> 0 then
start[1] := maxs[1]
else
start[1] := mins[1];
if gi.pointcontents(start) <> CONTENTS_SOLID then
goto realcheck;
end;
c_yes := c_yes + 1;
Result := True; // we got out easy
Exit;
realcheck:
c_no := c_no + 1;
//
// check it for real...
//
start[2] := mins[2];
// the midpoint must be within 16 of the bottom
stop[0] := (mins[0] + maxs[0])*0.5;
start[0] := stop[0];
stop[1] := (mins[1] + maxs[1])*0.5;
start[1] := stop[1];
stop[2] := start[2] - 2*STEPSIZE;
trace := gi.trace (@start, @vec3_origin, @vec3_origin, @stop, ent, MASK_MONSTERSOLID);
if trace.fraction = 1.0 then
begin
Result := False;
Exit;
end;
bottom := trace.endpos[2];
mid := bottom;
// the corners must be within 16 of the midpoint
for x := 0 to 1 do
for y :=0 to 1 do
begin
if x <> 0 then
stop[0] := maxs[0]
else
stop[0] := mins[0];
start[0] := stop[0];
if y <> 0 then
stop[1] := maxs[1]
else
stop[1] := mins[1];
start[1] := stop[1];
trace := gi.trace (@start, @vec3_origin, @vec3_origin, @stop, ent, MASK_MONSTERSOLID);
if (trace.fraction <> 1.0) and (trace.endpos[2] > bottom) then
bottom := trace.endpos[2];
if (trace.fraction = 1.0) or (mid - trace.endpos[2] > STEPSIZE) then
begin
Result := False;
Exit;
end;
end;
c_yes := c_yes + 1;
Result := True;
end;
(*
=============
SV_movestep
Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done, false is returned, and
pr_global_struct->trace_normal is set to the normal of the blocking wall
=============
*)
//FIXME since we need to test end position contents here, can we avoid doing
//it again later in catagorize position?
function SV_movestep(ent: edict_p; const move: vec3_t; relink: qboolean): qboolean;
var
dz: Single;
oldorg, neworg, end_: vec3_t;
trace: trace_t;
i: Smallint;
stepsizes: Single; //Well,case not sensitive,'stepsizes' replaced 'stepsize'.
test: vec3_t;
contents: smallint;
begin
// try the move
VectorCopy (ent^.s.origin, oldorg);
VectorAdd (ent^.s.origin, move, neworg);
// flying monsters don't step up
if (ent^.flags and (FL_SWIM or FL_FLY) <> 0) then
begin
// try one move with vertical motion, then one without
for i := 0 to 1 do
begin
VectorAdd(ent^.s.origin, move ,neworg);
if (i = 0) and (ent^.enemy <> nil) then
begin
if (ent^.goalentity = nil) then
ent^.goalentity := ent^.enemy;
dz := ent^.s.origin[2] - ent^.goalentity^.s.origin[2];
if (ent^.goalentity^.client <> nil) then
begin
if dz > 40 then
neworg[2] := neworg[2] - 8;
if not ((ent^.flags and FL_SWIM <> 0) and (ent^.waterlevel < 2)) then
if dz < 30 then
neworg[2] := neworg[2] + 8;
end
else
begin
if dz > 8 then
neworg[2] := neworg[2] - 8
else if dz > 0 then
neworg[2] := neworg[2] - dz
else if dz < -8 then
neworg[2] := neworg[2] + 8
else
neworg[2] := neworg[2] + dz;
end;
end;
trace := gi.trace (@ent^.s.origin, @ent^.mins, @ent^.maxs, @neworg, ent, MASK_MONSTERSOLID);
// fly monsters don't enter water voluntarily
if (ent^.flags and FL_FLY <> 0) then
begin
if (ent^.waterlevel = 0) then
begin
test[0] := trace.endpos[0];
test[1] := trace.endpos[1];
test[2] := trace.endpos[2] + ent^.mins[2] + 1;
contents := gi.pointcontents(test);
if (contents and MASK_WATER) <> 0 then
begin
Result := False;
Exit;
end;
end;
end;
// swim monsters don't exit water voluntarily
if (ent^.flags and FL_SWIM <> 0) then
begin
if (ent^.waterlevel < 2) then
begin
test[0] := trace.endpos[0];
test[1] := trace.endpos[1];
test[2] := trace.endpos[2] + ent^.mins[2] + 1;
contents := gi.pointcontents(test);
if (contents and MASK_WATER) = 0 then
begin
Result := False;
Exit;
end;
end;
end;
if trace.fraction = 1 then
begin
VectorCopy (trace.endpos, ent^.s.origin);
if relink then
begin
gi.linkentity (ent);
G_TouchTriggers (ent);
end;
Result := True;
Exit;
end;
if (ent^.enemy = nil) then
Break;
end;
Result := False;
Exit;
end;
// push down from a step height above the wished position
if (ent^.monsterinfo.aiflags and AI_NOSTEP = 0) then
stepsizes := STEPSIZE
else
stepsizes := 1;
neworg[2] := neworg[2] + stepsizes;
VectorCopy (neworg, end_);
end_[2] := end_[2] - stepsizes * 2;
trace := gi.trace (@neworg, @ent^.mins, @ent^.maxs, @end_, ent, MASK_MONSTERSOLID);
if trace.allsolid then
begin
Result := False;
Exit;
end;
if trace.startsolid then
begin
neworg[2] := neworg[2] - stepsizes;
trace := gi.trace (@neworg, @ent^.mins, @ent^.maxs, @end_, ent, MASK_MONSTERSOLID);
if (trace.allsolid or trace.startsolid) then
begin
Result := False;
Exit;
end;
end;
// don't go in to water
if ent^.waterlevel = 0 then
begin
test[0] := trace.endpos[0];
test[1] := trace.endpos[1];
test[2] := trace.endpos[2] + ent^.mins[2] + 1;
contents := gi.pointcontents(test);
if (contents and MASK_WATER) <> 0 then
begin
Result := False;
Exit;
end;
end;
if trace.fraction = 1 then
begin
// if monster had the ground pulled out, go ahead and fall
if (ent^.flags and FL_PARTIALGROUND) <> 0 then
begin
VectorAdd (ent^.s.origin, move, ent^.s.origin);
if relink then
begin
gi.linkentity (ent);
G_TouchTriggers (ent);
end;
ent^.groundentity := nil;
Result := True;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -