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

📄 g_utils.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): g_local.h (part), g_utils.c                                       }
{ Content: Quake2\(Game|CTF)\ misc utility functions for game module         }
{                                                                            }
{ Initial conversion by : Clootie (Alexey Barkovoy) - clootie@reactor.ru     }
{ Initial conversion on : 27-Feb-2002                                        }
{                                                                            }
{ 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:                                                                 }
{ 1) 03-Mar-2002 - Clootie (clootie@reactor.ru)                              }
{    Changed "G_FreeEdict" calling convention to "cdecl"                     }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{                                                                            }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{----------------------------------------------------------------------------}

// Remove DOT before $DEFINE in next line to allow non-dependable compilation //
{$DEFINE NODEPEND}
// non-dependable compilation will use STUBS for some external symbols


{$Include ..\JEDI.inc}

unit g_utils;

interface

uses
  q_shared, g_local, g_main{$IFNDEF COMPILER6_UP}, Windows{$ENDIF};

// g_utils.c -- misc utility functions for game module

//
// g_utils.c
//

function KillBox(ent: edict_p): qboolean;
procedure G_ProjectSource(const point, distance, forward, right: vec3_t;
  out result: vec3_t);
function G_Find(from: edict_p; fieldofs: Integer; match: PChar): edict_p;
function findradius(from: edict_p; org: vec3_t; rad: Single): edict_p;
function G_PickTarget(targetname: PChar): edict_p;
procedure G_UseTargets(ent: edict_p; activator: edict_p);
procedure G_SetMovedir(var angles: vec3_t; out movedir: vec3_t);

procedure G_InitEdict(e: edict_p);
function G_Spawn: edict_p;
procedure G_FreeEdict(ed: edict_p); cdecl;

procedure G_TouchTriggers(const ent: edict_t);
procedure G_TouchSolids(ent: edict_p);

function G_CopyString(in_: PChar): PChar;

function tv(x, y, z: Single): PSingle;
function vtos(const v: vec3_t): PChar;

function vectoyaw(vec: vec3_t): Single;
procedure vectoangles(const value1: vec3_t; out angles: vec3_t);


implementation

uses
  Math, SysUtils,
  GameUnit;

{$IFDEF NODEPEND}
// g_combat.pas
procedure T_Damage(targ, inflictor, attacker: edict_p; const dir, point, normal: vec3_t;
  damage, knockback, dflags, mod_: Integer); begin end;
{$ENDIF}

procedure G_ProjectSource(const point, distance, forward, right: vec3_t;
  out result: vec3_t);
begin
  result[0] := point[0] + forward[0] * distance[0] + right[0] * distance[1];
  result[1] := point[1] + forward[1] * distance[0] + right[1] * distance[1];
  result[2] := point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
end;


(*
=============
G_Find

Searches all active entities for the next one that holds
the matching string at fieldofs (use the FOFS() macro) in the structure.

Searches beginning at the edict after from, or the beginning if NULL
NULL will be returned if the end of the list is reached.

=============
*)
function G_Find(from: edict_p; fieldofs: Integer; match: PChar): edict_p;
var
  s: PChar;
begin
  if (from = nil) then
    from := edict_p(g_edicts) //Clootie: we take first pointer of array
  else
    Inc(from); //Clootie: Shift to next element in pointer to array of "edict_t"

  // for ( ; from < &g_edicts[globals.num_edicts] ; from++)
  while (Integer(from) < Integer(@g_edicts[globals.num_edicts])) do
  begin
    if (not from.inuse) then
    begin
      Inc(from);
      Continue;
    end;

    s := PChar(Integer(from) + fieldofs);
    if (s = nil) then
    begin
      Inc(from);
      Continue;
    end;

    if (Q_stricmp(s, match) = 0) then
    begin
      Result := from;
      Exit;
    end;

    Inc(from);
  end;

  Result := nil;
end;


(*
=================
findradius

Returns entities that have origins within a spherical area

findradius (origin, radius)
=================
*)
function findradius(from: edict_p; org: vec3_t; rad: Single): edict_p;
var
  eorg: vec3_t;
  j: Integer;
begin
  if (from = nil) then
    from := edict_p(g_edicts) //Clootie: we take first pointer of array
  else
    Inc(from); //Clootie: Shift to next element in pointer to array of "edict_t"

  // for ( ; from < &g_edicts[globals.num_edicts]; from++)
  while Integer(from) < Integer(@g_edicts[globals.num_edicts]) do
  begin
    if (not from.inuse) or (from.solid = SOLID_NOT) then
    begin
      Inc(from);
      Continue;
    end;

    for j:= 0 to 2 do
      eorg[j] := org[j] - (from.s.origin[j] + (from.mins[j] + from.maxs[j])*0.5);

    if (VectorLength(eorg) > rad) then
    begin
      Inc(from);
      Continue;
    end;
    Result:= from;
    Exit;
  end;

  Result := nil;
end;


(*
=============
G_PickTarget

Searches all active entities for the next one that holds
the matching string at fieldofs (use the FOFS() macro) in the structure.

Searches beginning at the edict after from, or the beginning if NULL
NULL will be returned if the end of the list is reached.

=============
*)
const
  MAXCHOICES    = 8;

function G_PickTarget(targetname: PChar): edict_p;
var
  ent: edict_p;
  num_choices: Integer;
  choice: array [0..MAXCHOICES-1] of edict_p;
begin
  ent := nil;
  num_choices := 0;

  if (targetname = nil) then
  begin
    gi_dprintf('G_PickTarget called with NULL targetname'#10, ['']);
    Result := nil;
    Exit;
  end;

  while True do
  begin
    // ent := G_Find(ent, FOFS(targetname), targetname);
    ent := G_Find(ent, Integer(@edict_p(nil).targetname){FOFS(targetname)}, targetname);
    if (ent = nil) then Break;
    choice[num_choices] := ent;
    Inc(num_choices);
    if (num_choices = MAXCHOICES) then Break;
  end;

  if (num_choices = 0) then
  begin
    gi_dprintf('G_PickTarget: target %s not found'#10, [targetname]);
    Result := nil;
    Exit;
  end;

  Result:= choice[Random(MaxInt) mod num_choices]; //todo: "rand()"
end;

procedure Think_Delay(ent: edict_p); cdecl;
begin
  G_UseTargets(ent, ent.activator);
  G_FreeEdict(ent);
end;


(*
==============================
G_UseTargets

the global "activator" should be set to the entity that initiated the firing.

If self.delay is set, a DelayedUse entity will be created that will actually
do the SUB_UseTargets after that many seconds have passed.

Centerprints any self.message to the activator.

Search for (string)targetname in all entities that
match (string)self.target and call their .use function

==============================
*)
procedure G_UseTargets(ent: edict_p; activator: edict_p);
var
  t: edict_p;
begin
//
// check for a delay
//
  if (ent.delay <> 0) then
  begin
  // create a temp object to fire at a later time
    t := G_Spawn;
    t.classname := 'DelayedUse';
    t.nextthink := level.time + ent.delay;
    t.think := Think_Delay;
    t.activator := activator;
    if (activator = nil) then
      gi_dprintf('Think_Delay with no activator'#10, []);
    t._message := ent._message;
    t.target := ent.target;
    t.killtarget := ent.killtarget;
    Exit;
  end;


//
// print the message
//
  if (ent._message <> nil) and ((activator.svflags and SVF_MONSTER) = 0) then
  begin
    gi_centerprintf(activator, '%s', [ent._message]);
    if (ent.noise_index <> 0) then
      gi.sound(activator, CHAN_AUTO, ent.noise_index, 1, ATTN_NORM, 0)
    else
      gi.sound(activator, CHAN_AUTO, gi.soundindex('misc/talk1.wav'), 1, ATTN_NORM, 0);
  end;

//
// kill killtargets
//
  if (ent.killtarget <> nil) then
  begin
    t := nil;
    // while ((t = G_Find (t, FOFS(targetname), ent->killtarget)))
    t := G_Find(t, Integer(@edict_p(nil).targetname){FOFS(targetname)}, ent.killtarget);
    while (t <> nil) do
    begin
      G_FreeEdict(t);
      if not ent.inuse then
      begin
        gi_dprintf('entity was removed while using killtargets'#10, []);
        Exit;
      end;
      t := G_Find(t, Integer(@edict_p(nil).targetname){FOFS(targetname)}, ent.killtarget);
    end;
  end;

//	gi_dprintf("TARGET: activating %s\n", ent->target);

//
// fire targets
//
  if (ent.target <> nil) then
  begin
    t := nil;
    // while ((t = G_Find (t, FOFS(targetname), ent->target)))
    t := G_Find(t, Integer(@edict_p(nil).targetname){FOFS(targetname)}, ent.target);
    while (t <> nil) do
    begin
      // doors fire area portals in a specific way
      if (Q_stricmp(t.classname, 'func_areaportal') <> 0) and
         ((Q_stricmp(ent.classname, 'func_door') <> 0) or
          (Q_stricmp(ent.classname, 'func_door_rotating') <> 0))
      then Continue;

      if (t = ent) then
      begin
        gi_dprintf('WARNING: Entity used itself.'#10, []);
      end else

⌨️ 快捷键说明

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