📄 g_monster.pas
字号:
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 + -