⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_move.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
(*
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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*)
// m_move.c -- monster movement
{******************************************************
   Name: m_move.pas
   Translator: you_known
   Description: a part of Quake 2 - Visual C to Delphi
                Conversion
   Date: 2002-02-02 22:10
   E-mail: you_known@163.com
******************************************************}

unit m_move;

interface


implementation

uses
  game,
  g_local,
  g_utils,
  q_shared;

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:pedict_t):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] := mins[0] else start[0] := maxs[0];
                if y = 0 then
                 start[1] := mins[1] else start[1] := maxs[1];
                if gi.pointcontents(start) <> CONTENTS_SOLID then
                 goto realcheck;
            end;
       c_yes := c_yes + 1;
       result:=True;          // we got out easy

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
              result := False;
       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] := mins[0] else stop[0] := maxs[0];
                 start[0] := stop[0];
                if y = 0 then
                 stop[1] := mins[1] else stop[1] := maxs[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 result := False;
            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:pedict_t; move:vec3_t; relink:qboolean):qboolean;
var  dz:Single;
     oldorg, neworg, vend:vec3_t; //We can not use 'end' here,so I used vend.
     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 not (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 not (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)=1 then
                                     result := False;
                          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 not (contents and MASK_WATER)=1 then
                                     result := False;
                           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;
                        end;

                        if not (ent^.enemy<>nil) then
                               break;
                 end;
                 result := False;
        end;
// push down from a step height above the wished position
	if not (ent^.monsterinfo.aiflags and AI_NOSTEP<>0) then
		stepsizes := STEPSIZE
	else
		stepsizes := 1;

        neworg[2] := neworg[2] + stepsizes;
        VectorCopy (neworg, vend);
        vend[2] := Pointer(Cardinal(@vend) - stepsizes * 2);

        trace := gi.trace (neworg, ent^.mins, ent^.maxs, vend, ent, MASK_MONSTERSOLID);

        if trace.allsolid then
            result := False;
        if trace.startsolid then
         begin
            neworg[2] := neworg[2] - stepsizes;
            trace := gi.trace (neworg, ent^.mins, ent^.maxs, vend, ent, MASK_MONSTERSOLID);
            if (trace.allsolid or trace.startsolid) then
                    result := False;
         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)
                     result := False;
          end;

          if trace.fraction = 1 then
           begin
           // if monster had the ground pulled out, go ahead and fall
              if (ent^.flags and FL_PARTIALGROUND) 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;
               end;

               result := False;    // walked off an edge
           end;

// check point traces down for dangling corners
          VectorCopy (trace.endpos, ent^.s.origin);

          if not (M_CheckBottom (ent)) then
           begin
              if (ent^.flags and FL_PARTIALGROUND) then
               begin
                   // entity had floor mostly pulled out from underneath it
		   // and is trying to correct
                   if relink then
                    begin
                       gi.linkentity (ent);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -