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

📄 g_utils.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      begin
        if (@t.use <> nil) then
          t.use(t, ent, activator);
      end;
      if not ent.inuse then
      begin
        gi_dprintf('entity was removed while using targets'#10, []);
        Exit;
      end;
    end;
  end;
end;


(*
=============
TempVector

This is just a convenience function
for making temporary vectors for function calls
=============
*)
function tv(x, y, z: Single): PSingle;
{$IFDEF COMPILER6_UP}{$WRITEABLECONST ON}{$ENDIF}
const
  index: Integer = 0;
  vecs: array[0..7] of vec3_t =
    ((0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0));
{$IFDEF COMPILER6_UP}{$WRITEABLECONST OFF}{$ENDIF}
var
  v: vec3_p;
begin
  // use an array so that multiple tempvectors won't collide
  // for a while
  v := @vecs[index];
  index := (index + 1) and 7;

  v[0] := x;
  v[1] := y;
  v[2] := z;

  Result:= PSingle(v);
end;


(*
=============
VectorToString

This is just a convenience function
for printing vectors
=============
*)
function vtos(const v: vec3_t): PChar;
{$IFDEF COMPILER6_UP}{$WRITEABLECONST ON}{$ENDIF}
const
  index: Integer = 0;
  str: array[0..7, 0..31] of Char = (
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0,
    #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
  );
{$IFDEF COMPILER6_UP}{$WRITEABLECONST OFF}{$ENDIF}
var
  s: PChar;
begin
  // use an array so that multiple vtos won't collide
  s := str[index];
  index := (index + 1) and 7;

  Com_sprintf(s, 32, '(%d %d %d)', [Round(v[0]), Round(v[1]), Round(v[2])]);

  Result:= s;
end;

var
  VEC_UP        : vec3_t        = (0, -1, 0);
  MOVEDIR_UP    : vec3_t	= (0, 0, 1);
  VEC_DOWN      : vec3_t        = (0, -2, 0);
  MOVEDIR_DOWN  : vec3_t        = (0, 0, -1);

procedure G_SetMovedir(var angles: vec3_t; out movedir: vec3_t);
begin
  if VectorCompare(angles, VEC_UP) <> 0 then
  begin
    VectorCopy(MOVEDIR_UP, movedir);
  end
  else if VectorCompare(angles, VEC_DOWN) <> 0 then
  begin
    VectorCopy(MOVEDIR_DOWN, movedir);
  end
  else
  begin
    AngleVectors(angles, @movedir, nil, nil);
  end;

  VectorClear(angles);
end;


function vectoyaw(vec: vec3_t): Single;
var
  yaw: Single;
begin
  if ((* vec[YAW] == 0 && *) vec[PITCH] = 0) then
  begin
    yaw := 0;
    if (vec[q_shared.YAW] > 0) then
      yaw := 90
    else if (vec[q_shared.YAW] < 0) then
      yaw := -90;
  end else
  begin
    yaw := Round((ArcTan2(vec[q_shared.YAW], vec[q_shared.PITCH]) * 180 / M_PI));
    if (yaw < 0) then
      yaw := yaw + 360;
  end;

  Result:= yaw;
end;


procedure vectoangles(const value1: vec3_t; out angles: vec3_t);
var
  forward_: Single;
  yaw, pitch: Single;
begin
  if (value1[1] = 0) and (value1[0] = 0) then
  begin
    yaw := 0;
    if (value1[2] > 0) then
      pitch := 90
    else
      pitch := 270;
  end else
  begin
    if (value1[0] <> 0) then
      yaw := Round(ArcTan2(value1[1], value1[0]) * 180 / M_PI)
    else if (value1[1] > 0) then
      yaw := 90
    else
      yaw := -90;
    if (yaw < 0) then
      yaw := yaw + 360;

    forward_ := sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
    pitch := Round(ArcTan2(value1[2], forward_) * 180 / M_PI);
    if (pitch < 0) then
      pitch := pitch + 360;
  end;

  angles[q_shared.PITCH] := -pitch;
  angles[q_shared.YAW] := yaw;
  angles[q_shared.ROLL] := 0;
end;

function G_CopyString(in_: PChar): PChar;
begin
  Result:= gi.TagMalloc(StrLen(in_)+1, TAG_LEVEL);
  StrCopy(Result, in_);
end;


procedure G_InitEdict(e: edict_p);
begin
  e.inuse := True;
  e.classname := 'noclass';
  e.gravity := 1.0;
  // e->s.number = e - g_edicts;
  e.s.number := (Integer(e) - Integer(g_edicts)) div SizeOf(edict_s); //todo: Clootie: need to check
end;

(*
=================
G_Spawn

Either finds a free edict, or allocates a new one.
Try to avoid reusing an entity that was recently freed, because it
can cause the client to think the entity morphed into something else
instead of being removed and recreated, which can cause interpolated
angles and bad trails.
=================
*)
function G_Spawn: edict_p;
{$Warnings Off}
var
  i, i_hack: Integer; //Clootie: i_hack - is Delphi local cycle variable hack
  e: edict_p;
begin
  e := @g_edicts[Round(maxclients.value)+1];
  // for ( i=maxclients->value+1 ; i<globals.num_edicts ; i++, e++)
  for i:= Round(maxclients.value)+1 to globals.num_edicts - 1 do ;
  begin
    // the first couple seconds of server time can involve a lot of
    // freeing and allocating, so relax the replacement policy
    if not e.inuse and ((e.freetime < 2) or (level.time - e.freetime > 0.5)) then
    begin
      G_InitEdict(e);
      Result:= e;
      Exit;
    end;
    Inc(e); // i++, e++)
    i_hack:= i + 1;
  end;

  if (i_hack = game.maxentities) then
    gi_error('ED_Alloc: no free edicts', []);

  Inc(globals.num_edicts);
  G_InitEdict(e);
  Result:= e;
end;
{$Warnings On}

(*
=================
G_FreeEdict

Marks the edict as free
=================
*)
procedure G_FreeEdict(ed: edict_p);
begin
  gi.unlinkentity(ed);		// unlink from world

  //todo: Clootie: need to check
  if ((Integer(ed) - Integer(g_edicts)) div SizeOf(edict_s) <=
     (maxclients.value + BODY_QUEUE_SIZE)) then
  begin
//  gi_dprintf("tried to free special edict\n");
    Exit;
  end;

  FillChar(ed, SizeOf(ed^), 0);
  ed.classname := 'freed';
  ed.freetime := level.time;
  ed.inuse := false;
end;


(*
============
G_TouchTriggers

============
*)
procedure G_TouchTriggers(const ent: edict_t);
var
  i, num: Integer;
  touch: array [0..MAX_EDICTS-1] of edict_p;
  hit: edict_p;
begin
  // dead things don't activate triggers!
  if ((ent.client = nil) or (ent.svflags and SVF_MONSTER <> 0)) and
     (ent.health <= 0)
  then Exit;

  num := gi.BoxEdicts(ent.absmin, ent.absmax, @touch, MAX_EDICTS, AREA_TRIGGERS);

  // be careful, it is possible to have an entity in this
  // list removed before we get to it (killtriggered)
  for i:= 0 to num - 1 do
  begin
    hit := touch[i];
    if not hit.inuse then Continue;
    if (@hit.touch = nil) then Continue;
    hit.touch(hit, @ent, nil, nil);
  end;
end;

(*
============
G_TouchSolids

Call after linking a new trigger in during gameplay
to force all entities it covers to immediately touch it
============
*)
procedure G_TouchSolids(ent: edict_p);
var
  i, num: Integer;
  touch: array [0..MAX_EDICTS-1] of edict_p;
  hit: edict_p;
begin
  num := gi.BoxEdicts(ent.absmin, ent.absmax, @touch, MAX_EDICTS, AREA_SOLID);

  // be careful, it is possible to have an entity in this
  // list removed before we get to it (killtriggered)
  for i:= 0 to num - 1 do
  begin
    hit := touch[i];

    if not hit.inuse then Continue;
    if (@hit.touch <> nil) then hit.touch(hit, @ent, nil, nil);
    if not ent.inuse then Break;
  end;
end;




(*
==============================================================================

Kill box

==============================================================================
*)          

(*
=================
KillBox

Kills all entities that would touch the proposed new positioning
of ent.  Ent should be unlinked before calling this!
=================
*)
function KillBox(ent: edict_p): qboolean;
var
  tr: trace_t;
begin
  while True do
  begin
    tr := gi.trace(ent.s.origin, ent.mins, ent.maxs, ent.s.origin, nil, MASK_PLAYERSOLID);
    if (tr.ent = nil) then Break;

    // nail it
    T_Damage(@tr.ent, ent, ent, vec3_origin, ent.s.origin, vec3_origin, 100000,
      0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);

    // if we didn't kill it, fail
    if (tr.ent.solid <> SOLID_NOT) then
    begin
      Result:= False;
      Exit;
    end;
  end;

  Result:= True;		// all clear
end;

end.

⌨️ 快捷键说明

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