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

📄 g_monster.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit g_monster;
// Converted by Clairebear in Jan 2002
// Comments
// All original comments retained
//
//procedure M_FliesOn (self pedict_t);
// There's a string with a forward slash in it. Looks like a file name but
// I havent changed the / to a \.
// Removed "Static" declarations for some of the functions but left the
// commented out original header for these in case it makes a difference
//
// LOGIC PRECEDENCE WORRIES
// m_dropToFloor function
// if (trace.fraction == 1 || trace.allsolid) 
// procedure M_MoveFrame (self : pedict_t);
// if (self->s.frame < move->firstframe || self->s.frame > move->lastframe)

{ Dated: 12-July-2002
  Continuation of Conversion:  Scott Price

NOTES:
======
- function/procedures had been organised nicely in alphabetical.  This is a
  bit of a pain when trying to compare to the original and debug the code.
  Have re-arranged in the order of the .c source file.  Once debugged it can
  be rearranged again in a nice alphabetical order.
- Have continued the conversion to completion.
- Some routine declarations in the Interface have been left-out at present.
  Determine which are Static implementations and which are visible. }

{
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.

}
interface

uses
  { TODO:  This uses clause will probably need some attention }
{ #include "g_local.h" }
  game, r_local,
  // 2 versions of this, one in ctf and one in game directories
  q_shared;


(* REMOVED BY SCOTT PRICE:
    - Need to know what we require from other units at compile time.  So safer
      if these actually force a compiler problem, as it requires the attention
      of someone involved in the compile process to ensure correct units are
      used for referencing.
--------------------------------------------------------------------------------
// CNH  Additions to get thing to compile

const MOD_UNKNOWN = 0;
const svc_muzzleflash2 = 0;
const g_edicts = 0;

type
{type edict_s = record
	entity_state_t	s;
	struct gclient_s	*client;
	qboolean	inuse;
	int			linkcount;

	// FIXME: move these fields to a server private sv_entity_t
	link_t		area;				// linked to a division node or leaf

	int			num_clusters;		// if -1, use headnode instead
	int			clusternums[MAX_ENT_CLUSTERS];
	int			headnode;			// unused if num_clusters != -1
	int			areanum, areanum2;

	//================================

	int			svflags;			// SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc
	vec3_t		mins, maxs;
	vec3_t		absmin, absmax, size;
	solid_t		solid;
	int			clipmask;
	edict_t		*owner;

	// the game dll can add anything it wants after
	// this point in the structure
end;
}
  edict_s = record{in game.h}
  end;
  edict_t = edict_s;
  pedict_t = ^edict_t;


  edict_t = record
  end;
  vec3_t = integer;
  procedure fire_bullet (self      : pedict_t;
                         start     : vec3_t;
                         dir       : vec3_t;
                         damage    : integer;
                         kick      : integer;
                         hspread   : integer;
                         vspread   : integer;
                         flashtype : integer);

type TGi = class(tobject)
public
	procedure WriteByte(a : byte);
	procedure WriteShort(a : smallint);
	procedure multicast(a:vec3_t; b:integer);
end;
var gi : Tgi;
*)
// end of additions

(* REMOVED BY SCOTT PRICE:
   - Shouldn't be any for statics.  If there are static utility routines, they
     need to be at the top of the implementation section to be visible to all
     other routines in this unit, for use.
--------------------------------------------------------------------------------
// Forward definitions

{ These were declared as static }
{ procedure M_FliesOff(self : pedict_t); - SP }
{ procedure M_FliesOn (self : pedict_t); - SP } *)

procedure monster_fire_bullet(self: pedict_t; start, dir: vec3_t; damage, kick,
  hspread, vspread, flashtype: Integer);
procedure monster_fire_shotgun(self: pedict_t; start, aimdir: vec3_t; damage,
  kick, hspread, vspread, count, flashtype: Integer);
procedure monster_fire_blaster(self: pedict_t; start, dir: vec3_t; damage, speed,
  flashtype, effect: Integer);
procedure monster_fire_grenade(self: pedict_t; start, aimdir: vec3_t; damage,
  speed, flashtype: Integer);
procedure monster_fire_rocket(self: pedict_t; start, dir: vec3_t; damage,
  speed, flashtype: Integer);
procedure monster_fire_railgun(self: pedict_t; start, aimdir: vec3_t; damage,
  kick, flashtype: Integer);
procedure monster_fire_bfg(self: pedict_t; start, aimdir: vec3_t; damage, speed,
  kick: Integer; damage_radius: single; flashtype: Integer);

procedure M_FlyCheck(self: pedict_t);
procedure AttackFinished(self: pedict_t; time: single);
procedure M_CheckGround(ent: pedict_t);
procedure M_CatagorizePosition(ent: pedict_t);
procedure M_WorldEffects(ent: pedict_t);
procedure M_droptofloor(ent: pedict_t);
procedure M_SetEffects(ent: pedict_t);
procedure M_MoveFrame(self: pedict_t);

procedure monster_think(self: pedict_t);
procedure monster_use(self, other, activator: pedict_t);
procedure monster_triggered_spawn(self: pedict_t);
procedure monster_triggered_spawn_use(self, other, activator: pedict_t);
procedure monster_triggered_start(self: pedict_t);

procedure monster_death_use(self: pedict_t);

function monster_start(self: pedict_t): qboolean; { ???:  This is declared with no body?  Strange }

procedure monster_start_go(self: pedict_t);
procedure walkmonster_start_go(self: Pedict_t);
procedure walkmonster_start(self: Pedict_t);
procedure flymonster_start_go(self: Pedict_t);
procedure flymonster_start(self: Pedict_t);
procedure swimmonster_start_go(self: Pedict_t);
procedure swimmonster_start(self: Pedict_t);



implementation


//
// Monster utility functions
//
procedure M_FliesOff(self: pedict_t);
begin
  //cnh  self->s.effects &= ~EF_FLIES;
  self^.s.effects := self^.s.effects and (not EF_FLIES);
  self^.s.sound := 0;
end;

procedure M_FliesOn(self: pedict_t);
begin
  if (self^.waterlevel <> 0) then
    Exit;
  self^.s.effects := self^.s.effects or EF_FLIES;
  //CNH Not sure about direction of / in next line
  self^.s.sound := gi.soundindex('infantry/inflies1.wav');
  self^.think := M_FliesOff;
  self^.nextthink := level.time + 60;
end;


//
// monster weapons
//

//FIXME mosnters should call these with a totally accurate direction
// and we can mess it up based on skill.  Spread should be for normal
// and we can tighten or loosen based on skill.  We could muck with
// the damages too, but I'm not sure that's such a good idea.
procedure monster_fire_bullet(self: pedict_t; start, dir: vec3_t; damage, kick,
  hspread, vspread, flashtype: Integer);
begin
  fire_bullet(self, start, dir, damage, kick, hspread, vspread, MOD_UNKNOWN);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end

procedure monster_fire_shotgun(self: pedict_t; start, aimdir: vec3_t; damage,
  kick, hspread, vspread, count, flashtype: Integer);
begin
  fire_shotgun(self, start, aimdir, damage, kick, hspread, vspread, count, MOD_UNKNOWN);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end;

procedure monster_fire_blaster(self: pedict_t; start, dir: vec3_t; damage, speed,
  flashtype, effect: Integer);
begin
  fire_blaster(self, start, dir, damage, speed, effect, false);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end;

procedure monster_fire_grenade(self: pedict_t; start, aimdir: vec3_t; damage,
  speed, flashtype: Integer);
begin
  fire_grenade(self, start, aimdir, damage, speed, 2.5, damage+40);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end;

procedure monster_fire_rocket(self: pedict_t; start, dir: vec3_t; damage,
  speed, flashtype: Integer);
begin
  fire_rocket(self, start, dir, damage, speed, damage+20, damage);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end;

procedure monster_fire_railgun(self: pedict_t; start, aimdir: vec3_t; damage,
  kick, flashtype: Integer);
begin
  fire_rail(self, start, aimdir, damage, kick);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end;

procedure monster_fire_bfg(self: pedict_t; start, aimdir: vec3_t; damage, speed,
  kick: Integer; damage_radius: single; flashtype: Integer);
begin
  fire_bfg(self, start, aimdir, damage, speed, damage_radius);

  gi.WriteByte(svc_muzzleflash2);
  gi.WriteShort(self - g_edicts);
  gi.WriteByte(flashtype);
  gi.multicast(start, MULTICAST_PVS);
end;

procedure M_FlyCheck(self: pedict_t);
begin
  if (self^.waterlevel) then
    Exit;

  Randomize;
  if Random(1) > 0.5 then
    Exit;

  self^.think := M_FliesOn;
  //CNH:  self->nextthink = level.time + 5 + 10 * random;
  self^.nextthink := level.time + 5 + (10 * Random(1));
end;

procedure AttackFinished(self: pedict_t; time: single);
begin
  self^.monsterinfo.attack_finished := level.time + time;
end

procedure M_CheckGround (ent : pedict_t);
var
  point: vec3_t;
  trace: trace_t;
begin
  if (ent^.flags and (FL_SWIM or FL_FLY)) <> 0 then
    Exit;

  if (ent^.velocity[2] > 100) then
  begin
    Ent^.groundentity := Nil;
    Exit;
  end;

  // if the hull point one-quarter unit down is solid the entity is on ground
  point[0] := ent^.s.origin[0];
  point[1] := ent^.s.origin[1];
  point[2] := ent^.s.origin[2] - 0.25;

  trace := gi.trace(ent^.s.origin, ent^.mins, ent^.maxs, point, ent, MASK_MONSTERSOLID);

  // check steepness
  //CNH  if ( trace.plane.normal[2] < 0.7 && !trace.startsolid)
  if (trace.plane.normal[2] < 0.7) and (not trace.startsolid) then
  begin
    ent^.groundentity := Nil;
    Exit;
  end;

  //	ent->groundentity = trace.ent;
  //	ent->groundentity_linkcount = trace.ent->linkcount;
  //	if (!trace.startsolid && !trace.allsolid)
  //		VectorCopy (trace.endpos, ent->s.origin);

  //CNH  if (!trace.startsolid && !trace.allsolid)
  if (not trace.startsolid) and (not trace.allsolid) then
  begin
    VectorCopy(trace.endpos, ent^.s.origin);
    ent^.groundentity := trace.ent;
    ent^.groundentity_linkcount := trace.ent^.linkcount;
    ent^.velocity[2] := 0;
  end;
end;

procedure M_CatagorizePosition (ent : pedict_t);
var
  point: vec3_t;
  cont: integer;
begin
  //
  // get waterlevel
  //
  point[0] := ent^.s.origin[0];
  point[1] := ent^.s.origin[1];
  point[2] := ent^.s.origin[2] + ent^.mins[2] + 1;
  cont := gi.pointcontents(point);

  //CNH:  if (!(cont & MASK_WATER))
  if ((cont and MASK_WATER) = 0) then
  begin
    ent^.waterlevel := 0;
    ent^.watertype := 0;
    Exit;
  end;

  ent^.watertype := cont;
  ent^.waterlevel := 1;
  point[2] := point[2] + 26;
  cont := gi.pointcontents(point);
  //CNH:  if (!(cont & MASK_WATER))
  if ((cont and MASK_WATER) = 0 then
    Exit;

  ent^.waterlevel := 2;
  point[2] := point[2] + 22;
  cont := gi.pointcontents(point);
  //CNH:  if (cont & MASK_WATER)
  if (Cont and MASK_WATER) <> 0 then
    ent^.waterlevel := 3;
end;

procedure M_WorldEffects (ent : pedict_t);
var
  dmg: integer;
begin
  if (ent^.health > 0) then
  begin
    //CNH:  if (!(ent->flags & FL_SWIM))
    if (ent^.flags and FL_SWIM) = 0 then
    begin
      if (ent^.waterlevel < 3) then
      begin
        ent^.air_finished := level.time + 12
      end
      else if (ent^.air_finished < level.time) then
      begin// drown!
        if (ent^.pain_debounce_time < level.time) then
        begin
          dmg := 2 + 2 * floor(level.time - ent^.air_finished);
          if (dmg > 15) then
            dmg := 15;
          T_Damage(ent, world, world, vec3_origin, ent^.s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER);
          ent^.pain_debounce_time := level.time + 1;
        end;
      end;
    end
    else
    begin
      if (ent^.waterlevel > 0) then
      begin
        ent^.air_finished := level.time + 9;
      end
      else if (ent^.air_finished < level.time) then
      begin	// suffocate!
        if (ent^.pain_debounce_time < level.time) then
        begin
          dmg := 2 + 2 * floor(level.time - ent^.air_finished);
          if (dmg > 15) then
            dmg := 15;
          T_Damage(ent, world, world, vec3_origin, ent^.s.origin, vec3_origin, dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER);
          ent^.pain_debounce_time := level.time + 1;
        end;
      end;
    end;
  end;

  if (ent^.waterlevel = 0) then
  begin
    if (ent^.flags and FL_INWATER) <> 0 then
    begin
      gi.sound(ent, CHAN_BODY, gi.soundindex('player/watr_out.wav'), 1, ATTN_NORM, 0);
      ent^.flags := ent^.flags AND (NOT FL_INWATER);
    end;

    Exit;
  end;

  //CNH:  if ((ent->watertype & CONTENTS_LAVA) && !(ent->flags & FL_IMMUNE_LAVA))
  if ((enent^.watertype and CONTENTS_LAVA) <> 0) and ((ent^.flags and FL_IMMUNE_LAVA) = 0) then
  begin
    if (ent^.damage_debounce_time < level.time) then
    begin
      ent^.damage_debounce_time := level.time + 0.2;
      T_Damage(ent, world, world, vec3_origin, ent^.s.origin, vec3_origin, 10 * ent^.waterlevel, 0, 0, MOD_LAVA);
    end;
  end;
  //CNH:  if ((ent->watertype & CONTENTS_SLIME) && !(ent->flags & FL_IMMUNE_SLIME))
  if ((ent^.watertype and CONTENTS_SLIME) <> 0) and ((ent^.flags and FL_IMMUNE_SLIME) = 0)then
  begin
    if (ent^.damage_debounce_time < level.time) then
    begin
      ent^.damage_debounce_time := level.time + 1;
      T_Damage(ent, world, world, vec3_origin, ent^.s.origin, vec3_origin, 4 * ent^.waterlevel, 0, 0, MOD_SLIME);
    end;
  end;

  //CNH:  if ( !(ent->flags & FL_INWATER) )
  if (ent^.flags and FL_INWATER) = 0 then
  begin
    //CNH:  if (!(ent->svflags & SVF_DEADMONSTER))
    if (ent^.svflags and SVF_DEADMONSTER) = 0 then
    begin

⌨️ 快捷键说明

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