📄 g_misc.pas
字号:
{$ALIGN ON}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{ }
{ File(s): game\g_misc.c }
{ 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 }
{----------------------------------------------------------------------------}
{ * TODO: }
{ Remaining functions }
{----------------------------------------------------------------------------}
unit g_misc;
interface
uses
g_combat,
m_move,
g_func,
q_shared,
q_shared_add,
game_add,
GameUnit,
g_save,
g_utils,
g_local_add,
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,
g_monster,
g_main,
CPas;
// 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; const 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 (rand() AND 1) <> 0 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;
end else
begin
self^.think := Nil;
self^.nextthink := 0;
end;
gi.linkentity(self);
end;
(*
=================
debris
=================
*)
procedure debris_die(self, inflictor, attacker: edict_p; damage: integer; const 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
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);
other.s.event := EV_OTHER_TELEPORT;
end;
other.goalentity := next;
other.movetarget := next;
if self.wait<>0 then
begin
other.monsterinfo.pausetime := level.time + self.wait;
other.monsterinfo.stand(other);
exit;
end;
if other.movetarget=Nil then
begin
other.monsterinfo.pausetime := level.time + 100000000;
other.monsterinfo.stand (other);
end
else
begin
VectorSubtract (other.goalentity.s.origin, other.s.origin, v);
other.ideal_yaw := vectoyaw (v);
end;
end;
procedure SP_path_corner(self: edict_p); {cdecl;}
begin
if self.targetname=Nil then
begin
gi.dprintf('path_corner with no targetname at %s'#10, vtos(self.s.origin));
G_FreeEdict (self);
exit;
end;
self.solid := SOLID_TRIGGER;
self.touch := path_corner_touch;
VectorSet (self.mins, -8, -8, -8);
VectorSet (self.maxs, 8, 8, 8);
self.svflags := self.svflags OR SVF_NOCLIENT;
gi.linkentity (self);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -