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

📄 g_misc.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
{$DEFINE CTF}
//100%
{$ALIGN ON}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): game\g_misc.c                                                     }
{          ctf\g_misc.c (if you define CTF)                                  }
{ Content: Saving and loading games                                          }
{                                                                            }
{ Initial conversion by: Carl A Kenner (carlkenner@hotmail.com)              }
{ Initial conversion on: 1-Mar-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 on: 3-Mar-2002                                                     }
{ Updated by: Carl A Kenner                                                  }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{ g_utils.G_FreeEdict, g_combat, m_move, g_func, g_ctf                       }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ Remaining functions                                                        }
{----------------------------------------------------------------------------}
unit g_misc;

{$DEFINE NODEPEND}

interface
Uses
{$IFNDEF NODEPEND}
  {$IFDEF CTF}
    g_ctf,
  {$ENDIF}
  g_combat, m_move, g_func,
{$ENDIF}
q_shared, GameUnit, g_save, g_utils, g_local;


procedure ThrowGib(self: edict_p; gibname: PChar; damage, _type: Integer);
procedure ThrowHead(self: edict_p; gibname: PChar; damage, _type: integer);
procedure ThrowClientHead(self: edict_p; damage: Integer);

procedure ThrowDebris(self: edict_p; modelname: PChar; speed: Single; const origin: vec3_t);

procedure BecomeExplosion1(self: edict_p);

procedure SP_func_areaportal(ent: edict_p); cdecl;
procedure SP_path_corner(self: edict_p); cdecl;
procedure SP_point_combat(self: edict_p); cdecl;
procedure SP_viewthing(ent: edict_p); cdecl;
procedure SP_info_null(self: edict_p); cdecl;
procedure SP_info_notnull(self: edict_p); cdecl;
procedure SP_light(self: edict_p); cdecl;
procedure SP_func_wall(self: edict_p); cdecl;
procedure SP_func_object(self: edict_p); cdecl;
procedure SP_func_explosive(self: edict_p); cdecl;
procedure SP_misc_explobox(self: edict_p); cdecl;
procedure SP_misc_blackhole(ent: edict_p); cdecl;
procedure SP_misc_eastertank(ent: edict_p); cdecl;
procedure SP_misc_easterchick(ent: edict_p); cdecl;
procedure SP_misc_easterchick2(ent: edict_p); cdecl;
procedure SP_monster_commander_body(self: edict_p); cdecl;
procedure SP_misc_banner(ent: edict_p); cdecl;
procedure SP_misc_deadsoldier(ent: edict_p); cdecl;
procedure SP_misc_viper (ent: edict_p); cdecl;
procedure SP_misc_bigviper(ent: edict_p); cdecl;
procedure SP_misc_viper_bomb(self: edict_p); cdecl;
procedure SP_misc_strogg_ship(ent: edict_p); cdecl;
procedure SP_misc_satellite_dish(ent: edict_p); cdecl;
procedure SP_light_mine1(ent: edict_p); cdecl;
procedure SP_light_mine2(ent: edict_p); cdecl;
procedure SP_misc_gib_arm(ent: edict_p); cdecl;
procedure SP_misc_gib_leg(ent: edict_p); cdecl;
procedure SP_misc_gib_head(ent: edict_p); cdecl;
procedure SP_target_character(self: edict_p); cdecl;
procedure SP_target_string(self: edict_p); cdecl;
procedure SP_func_clock(self: edict_p); cdecl;
procedure SP_misc_teleporter(ent: edict_p); cdecl;
procedure SP_misc_teleporter_dest(ent: edict_p); cdecl;

implementation
Uses SysUtils, DateUtils;

{$IFDEF NODEPEND}
//CAK - Change calling convention to cdecl
procedure G_FreeEdict(ed: edict_p); cdecl;
begin
  g_utils.G_FreeEdict(ed);
end;

//g_combat
function T_Damage(targ, inflictor, attacker: edict_p; var dir, point, normal: vec3_t; damage, knockback, dflags, _mod: Integer): edict_p;
begin
  result:=nil;
end;
procedure T_RadiusDamage(inflictor, attacker: edict_p; damage: Single; ignore: edict_p; radius: Single; _mod: Integer); begin end;

// m_move
function M_walkmove(ent: edict_p; yaw:single; dist:single): qboolean;
begin
  Result:=false;
end;

//g_monster
procedure M_droptofloor(ent: edict_p); cdecl; begin end;

//g_func
procedure train_use(self, other, activator: edict_p); cdecl; begin end;
procedure func_train_find(self: edict_p); cdecl; begin end;

{$IFDEF CTF}
//g_ctf
type ctfteam_t = (CTF_NOTEAM, CTF_TEAM1, CTF_TEAM2);
procedure CTFResetFlag(ctf_team: ctfteam_t); begin end;
function CTFTeamName(team: ctfteam_t): PChar;
begin
  Result:='';
end;
procedure CTFRespawnTech(ent: edict_p); begin end;
procedure CTFPlayerResetGrapple(ent: edict_p); begin end;
{$ENDIF}

{$ENDIF}

// g_misc.c

(*QUAKED func_group (0 0 0) ?
Used to group brushes together just for editor convenience.
*)

//====================================================:=

procedure Use_Areaportal(ent, other, activator: edict_p); cdecl;
begin
  ent.count := ent.count XOR 1;	// toggle state
//  gi_dprintf('portalstate: %i = %i\n', [ent.style, ent.count]);
  gi.SetAreaPortalState(ent.style, ent.count<>0);
end;

(*QUAKED func_areaportal (0 0 0) ?

This is a non-visible object that divides the world into
areas that are seperated when this portal is not activated.
Usually enclosed in the middle of a door.
*)
procedure SP_func_areaportal(ent: edict_p); cdecl;
begin
  ent.use := Use_Areaportal;
  ent.count := 0; // always start closed;
end;

//====================================================:=


(*
=================
Misc functions
=================
*)
procedure VelocityForDamage(damage: Integer; var v: vec3_t);
begin
  v[0] := 100.0 * crandom();
  v[1] := 100.0 * crandom();
  v[2] := 200.0 + 100.0 * _random();

  if damage < 50 then
    VectorScale (v, 0.7, v)
  else
    VectorScale (v, 1.2, v);
end;

procedure ClipGibVelocity(ent: edict_p);
begin
  if ent.velocity[0] < -300 then
    ent.velocity[0] := -300
  else if ent.velocity[0] > 300 then
    ent.velocity[0] := 300;
  if ent.velocity[1] < -300 then
    ent.velocity[1] := -300
  else if ent.velocity[1] > 300 then
    ent.velocity[1] := 300;
  if ent.velocity[2] < 200 then
    ent.velocity[2] := 200 // always some upwards
  else if ent.velocity[2] > 500 then
    ent.velocity[2] := 500;
end;


(*
=================
gibs
=================
*)
procedure gib_think(self: edict_p); cdecl;
begin
  Inc(self.s.frame);
  self.nextthink := level.time + FRAMETIME;

  if self.s.frame = 10 then begin
    self.think := G_FreeEdict;
    self.nextthink := level.time + 8 + _random()*10;
  end;
end;

procedure gib_touch(self, other: edict_p; plane: cplane_p; surf: csurface_p); cdecl;
Var normal_angles, right: vec3_t;
begin
  if self.groundentity=Nil then
    exit;

  self.touch := Nil;

  if plane<>Nil then begin
    gi.sound (self, CHAN_VOICE, gi.soundindex ('misc/fhit3.wav'), 1, ATTN_NORM, 0);

    vectoangles(plane.normal, normal_angles);
    AngleVectors(normal_angles, Nil, @right, Nil);
    vectoangles (right, self.s.angles);

    if self.s.modelindex = sm_meat_index then begin
      inc(self.s.frame);
      self.think := gib_think;
      self.nextthink := level.time + FRAMETIME;
    end;
  end;
end;

procedure gib_die(self, inflictor, attacker: edict_p; damage: Integer; point: vec3_t); cdecl;
begin
  G_FreeEdict(self);
end;

procedure ThrowGib(self: edict_p; gibname: PChar; damage, _type: Integer);
Var gib: edict_p; vd, origin, size: vec3_t; vscale: Single;
begin
  gib := G_Spawn();

  VectorScale(self.size, 0.5, size);
  VectorAdd(self.absmin, size, origin);
  gib.s.origin[0] := origin[0] + crandom() * size[0];
  gib.s.origin[1] := origin[1] + crandom() * size[1];
  gib.s.origin[2] := origin[2] + crandom() * size[2];

  gi.setmodel(gib, gibname);
  gib.solid := SOLID_NOT;
  gib.s.effects := gib.s.effects OR EF_GIB;
  gib.flags := gib.flags OR FL_NO_KNOCKBACK;
  gib.takedamage := DAMAGE_YES;
  gib.die := gib_die;

  if _type = GIB_ORGANIC then begin
    gib.movetype := MOVETYPE_TOSS;
    gib.touch := gib_touch;
    vscale := 0.5;
  end else begin
    gib.movetype := MOVETYPE_BOUNCE;
    vscale := 1.0;
  end;

  VelocityForDamage(damage, vd);
  VectorMA(self.velocity, vscale, vd, gib.velocity);
  ClipGibVelocity(gib);
  gib.avelocity[0] := _random()*600;
  gib.avelocity[1] := _random()*600;
  gib.avelocity[2] := _random()*600;

  gib.think := G_FreeEdict;
  gib.nextthink := level.time + 10 + _random()*10;

  gi.linkentity(gib);
end;

procedure ThrowHead(self: edict_p; gibname: PChar; damage, _type: integer);
Var vd: vec3_t; vscale: Single;
begin
  self.s.skinnum := 0;
  self.s.frame := 0;
  VectorClear(self.mins);
  VectorClear(self.maxs);

  self.s.modelindex2 := 0;
  gi.setmodel(self, gibname);
  self.solid := SOLID_NOT;
  self.s.effects := self.s.effects OR EF_GIB;
  self.s.effects := self.s.effects AND (NOT EF_FLIES);
  self.s.sound := 0;
  self.flags := self.flags OR FL_NO_KNOCKBACK;
  self.svflags := self.svflags AND (NOT SVF_MONSTER);
  self.takedamage := DAMAGE_YES;
  self.die := gib_die;

  if _type = GIB_ORGANIC then begin
    self.movetype := MOVETYPE_TOSS;
    self.touch := gib_touch;
    vscale := 0.5;
  end else begin
    self.movetype := MOVETYPE_BOUNCE;
    vscale := 1.0;
  end;

  VelocityForDamage(damage, vd);
  VectorMA(self.velocity, vscale, vd, self.velocity);
  ClipGibVelocity(self);

  self.avelocity[YAW] := crandom()*600;

  self.think := G_FreeEdict;
  self.nextthink := level.time + 10 + _random()*10;

  gi.linkentity (self);
end;


procedure ThrowClientHead(self: edict_p; damage: Integer);
Var vd: vec3_t; gibname: PChar;
begin
  if System.Random(2)=1 then begin
    gibname := 'models/objects/gibs/head2/tris.md2';
    self.s.skinnum := 1; // second skin is player
  end else begin
    gibname := 'models/objects/gibs/skull/tris.md2';
    self.s.skinnum := 0;
  end;

  self.s.origin[2] := self.s.origin[2] + 32;
  self.s.frame := 0;
  gi.setmodel(self, gibname);
  VectorSet(self.mins, -16, -16, 0);
  VectorSet(self.maxs, 16, 16, 16);

  self.takedamage := DAMAGE_NO;
  self.solid := SOLID_NOT;
  self.s.effects := EF_GIB;
  self.s.sound := 0;
  self.flags := self.flags OR FL_NO_KNOCKBACK;

  self.movetype := MOVETYPE_BOUNCE;
  VelocityForDamage (damage, vd);
  VectorAdd (self.velocity, vd, self.velocity);

  if self.client<>Nil then begin // bodies in the queue don't have a client anymore
    self.client.anim_priority := ANIM_DEATH;
    self.client.anim_end := self.s.frame;
{$IFNDEF CTF}
  end else begin
    self.think := Nil;
    self.nextthink := 0;
{$ENDIF}
  end;

  gi.linkentity(self);
end;


(*
=================
debris
=================
*)
procedure debris_die(self, inflictor, attacker: edict_p; damage: integer; point: vec3_t); cdecl;
begin
  G_FreeEdict(self);
end;

procedure ThrowDebris(self: edict_p; modelname: PChar; speed: Single; const origin: vec3_t);
Var chunk: edict_p; v: vec3_t;
begin
  chunk := G_Spawn();
  VectorCopy(origin, chunk.s.origin);
  gi.setmodel(chunk, modelname);
  v[0] := 100 * crandom();
  v[1] := 100 * crandom();
  v[2] := 100 + 100 * crandom();
  VectorMA(self.velocity, speed, v, chunk.velocity);
  chunk.movetype := MOVETYPE_BOUNCE;
  chunk.solid := SOLID_NOT;
  chunk.avelocity[0] := _random()*600;
  chunk.avelocity[1] := _random()*600;
  chunk.avelocity[2] := _random()*600;
  chunk.think := G_FreeEdict;
  chunk.nextthink := level.time + 5 + _random()*5;
  chunk.s.frame := 0;
  chunk.flags := 0;
  chunk.classname := 'debris';
  chunk.takedamage := DAMAGE_YES;
  chunk.die := debris_die;
  gi.linkentity(chunk);
end;


procedure BecomeExplosion1(self: edict_p);
begin
{$IFDEF CTF}
//ZOID
  //flags are important
  if strcomp(self.classname, 'item_flag_team1') = 0 then begin
    CTFResetFlag(CTF_TEAM1); // this will free self!
    gi_bprintf(PRINT_HIGH, 'The %s flag has returned!'#10,
      [CTFTeamName(CTF_TEAM1)]);
    exit;
  end;
  if strcomp(self.classname, 'item_flag_team2') = 0 then begin
    CTFResetFlag(CTF_TEAM2); // this will free self!
    gi_bprintf(PRINT_HIGH, 'The %s flag has returned!'#10,
      [CTFTeamName(CTF_TEAM1)]);
    exit;
  end;
  // techs are important too
  if (self.item<>Nil) and ((self.item.flags AND IT_TECH)<>0) then begin
    CTFRespawnTech(self); // this frees self!
    exit;
  end;
//ZOID
{$ENDIF}

  gi.WriteByte(svc_temp_entity);
  gi.WriteByte(Ord(TE_EXPLOSION1));
  gi.WritePosition(self.s.origin);
  gi.multicast(self.s.origin, MULTICAST_PVS);

  G_FreeEdict(self);
end;


procedure BecomeExplosion2(self: edict_p);
begin
  gi.WriteByte (svc_temp_entity);
  gi.WriteByte(Ord(TE_EXPLOSION2));
  gi.WritePosition (self.s.origin);
  gi.multicast (self.s.origin, MULTICAST_PVS);

  G_FreeEdict (self);
end;


(*QUAKED path_corner (.5 .3 0) (-8 -8 -8) (8 8 8) TELEPORT
Target: next path corner
Pathtarget: gets used when an entity that has
  this path_corner targeted touches it
*)

procedure path_corner_touch(self, other: edict_p; plane: cplane_p; surf: csurface_p); cdecl;
Var v: vec3_t; next: edict_p; savetarget: PChar;
begin
  if other.movetarget <> self then
    exit;

  if other.enemy<>Nil then
    exit;

  if self.pathtarget<>Nil then begin
    savetarget := self.target;
    self.target := self.pathtarget;
    G_UseTargets(self, other);
    self.target := savetarget;
  end;

  if self.target<>Nil then
    next := G_PickTarget(self.target)
  else
    next := Nil;

  if (next<>Nil) and ((next.spawnflags AND 1)>0) then
  begin
    VectorCopy (next.s.origin, v);
    v[2] := v[2] + next.mins[2];
    v[2] := v[2] - other.mins[2];
    VectorCopy(v, other.s.origin);
    next := G_PickTarget(next.target);
{$IFNDEF CTF}

⌨️ 快捷键说明

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