📄 g_misc.pas
字号:
other.s.event := EV_OTHER_TELEPORT;
{$ENDIF}
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;
(*QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) Hold
Makes this the target of a monster and it will head here
when first activated before going after the activator. If
hold is selected, it will stay here.
*)
procedure point_combat_touch(self, other: edict_p; plane: cplane_p; surf: csurface_p); cdecl;
Var activator: edict_p; savetarget: PChar;
begin
if other.movetarget <> self then
exit;
if self.target<>Nil then begin
other.target := self.target;
other.movetarget := G_PickTarget(other.target);
other.goalentity := other.movetarget;
if other.goalentity=Nil then begin
gi_dprintf('%s at %s target %s does not exist'#10, [self.classname, vtos(self.s.origin), self.target]);
other.movetarget := self;
end;
self.target := Nil;
end else if ((self.spawnflags AND 1)>0)
and ((other.flags AND (FL_SWIM OR FL_FLY))>0) then begin
other.monsterinfo.pausetime := level.time + 100000000;
other.monsterinfo.aiflags := other.monsterinfo.aiflags OR AI_STAND_GROUND;
other.monsterinfo.stand(other);
end;
if other.movetarget = self then begin
other.target := Nil;
other.movetarget := Nil;
other.goalentity := other.enemy;
other.monsterinfo.aiflags := other.monsterinfo.aiflags AND NOT AI_COMBAT_POINT;
end;
if self.pathtarget<>Nil then begin
savetarget := self.target;
self.target := self.pathtarget;
if (other.enemy<>Nil) and (other.enemy.client<>Nil) then
activator := other.enemy
else if (other.oldenemy<>Nil) and (other.oldenemy.client<>Nil) then
activator := other.oldenemy
else if (other.activator<>Nil) and (other.activator.client<>Nil) then
activator := other.activator
else
activator := other;
G_UseTargets(self, activator);
self.target := savetarget;
end;
end;
procedure SP_point_combat(self: edict_p); cdecl;
begin
if deathmatch.value<>0 then begin
G_FreeEdict(self);
exit;
end;
self.solid := SOLID_TRIGGER;
self.touch := point_combat_touch;
VectorSet(self.mins, -8, -8, -16);
VectorSet(self.maxs, 8, 8, 16);
self.svflags := SVF_NOCLIENT;
gi.linkentity(self);
end;
(*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8)
Just for the debugging level. Don't use
*)
{$IFDEF CTF}
Var
robotron: Array[0..3] of Integer;
{$ENDIF}
procedure TH_viewthing(ent: edict_p); cdecl;
begin
ent.s.frame := (ent.s.frame + 1) mod 7;
{$IFDEF CTF}
// ent.s.frame := (ent.s.frame + 1) mod 9;
{$ENDIF}
ent.nextthink := level.time + FRAMETIME;
{$IFDEF CTF}
// exit;
if ent.spawnflags<>0 then begin
if ent.s.frame = 0 then begin
ent.spawnflags := ((ent.spawnflags + 1) mod 4) + 1;
ent.s.modelindex := robotron[ent.spawnflags - 1];
end;
end;
{$ENDIF}
end;
procedure SP_viewthing(ent: edict_p); cdecl;
begin
gi.dprintf ('viewthing spawned'#10);
ent.movetype := MOVETYPE_NONE;
ent.solid := SOLID_BBOX;
ent.s.renderfx := RF_FRAMELERP;
VectorSet (ent.mins, -16, -16, -24);
VectorSet (ent.maxs, 16, 16, 32);
{$IFDEF CTF}
// ent.s.modelindex := gi.modelindex('models/player_y/tris.md2');
{$ENDIF}
ent.s.modelindex := gi.modelindex('models/objects/banner/tris.md2');
gi.linkentity(ent);
ent.nextthink := level.time + 0.5;
ent.think := TH_viewthing;
exit; // CAK - what's the point of this???
end;
(*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for spotlights, etc.
*)
procedure SP_info_null(self: edict_p); cdecl;
begin
G_FreeEdict(self);
end;
(*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for lightning.
*)
procedure SP_info_notnull(self: edict_p); cdecl;
begin
VectorCopy(self.s.origin, self.absmin);
VectorCopy(self.s.origin, self.absmax);
end;
(*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF
Non-displayed light.
Default light value is 300.
Default style is 0.
If targeted, will toggle between on and off.
Default _cone value is 10 (used to set size of light for spotlights)
*)
const
START_OFF = 1;
// CAK - static, so not in interface!!!
procedure light_use(self, other, activator: edict_p); cdecl;
begin
if (self.spawnflags AND START_OFF)>0 then begin
gi.configstring(CS_LIGHTS+self.style, 'm');
self.spawnflags := self.spawnflags AND NOT START_OFF;
end else begin
gi.configstring(CS_LIGHTS+self.style, 'a');
self.spawnflags := self.spawnflags OR START_OFF;
end;
end;
procedure SP_light(self: edict_p); cdecl;
begin
// no targeted lights in deathmatch, because they cause global messages
if (self.targetname=Nil) or (deathmatch.value<>0) then begin
G_FreeEdict(self);
exit;
end;
if self.style >= 32 then begin
self.use := light_use;
if (self.spawnflags AND START_OFF)>0 then
gi.configstring (CS_LIGHTS+self.style, 'a')
else
gi.configstring (CS_LIGHTS+self.style, 'm');
end;
end;
(*QUAKED func_wall (0 .5 .8) ? TRIGGER_SPAWN TOGGLE START_ON ANIMATED ANIMATED_FAST
This is just a solid wall if not inhibited
TRIGGER_SPAWN the wall will not be present until triggered
it will then blink in to existance; it will
kill anything that was in it's way
TOGGLE only valid for TRIGGER_SPAWN walls
this allows the wall to be turned on and off
START_ON only valid for TRIGGER_SPAWN walls
the wall will initially be present
*)
procedure func_wall_use(self, other, activator: edict_p); cdecl;
begin
if self.solid = SOLID_NOT then begin
self.solid := SOLID_BSP;
self.svflags := self.svflags AND NOT SVF_NOCLIENT;
KillBox (self);
end else begin
self.solid := SOLID_NOT;
self.svflags := self.svflags OR SVF_NOCLIENT;
end;
gi.linkentity (self);
if (self.spawnflags AND 2)=0 then
self.use := Nil;
end;
procedure SP_func_wall(self: edict_p); cdecl;
begin
self.movetype := MOVETYPE_PUSH;
gi.setmodel(self, self.model);
if (self.spawnflags AND 8)>0 then
self.s.effects := self.s.effects OR EF_ANIM_ALL;
if (self.spawnflags AND 16)>0 then
self.s.effects := self.s.effects OR EF_ANIM_ALLFAST;
// just a wall
if (self.spawnflags AND 7) = 0 then begin
self.solid := SOLID_BSP;
gi.linkentity (self);
exit;
end;
// it must be TRIGGER_SPAWN
if (self.spawnflags AND 1)=0 then begin
// gi.dprintf('func_wall missing TRIGGER_SPAWN'#10);
self.spawnflags := self.spawnflags OR 1;
end;
// yell if the spawnflags are odd
if (self.spawnflags AND 4)>0 then begin
if (self.spawnflags AND 2)=0 then begin
gi.dprintf('func_wall START_ON without TOGGLE'#10);
self.spawnflags := self.spawnflags OR 2;
end;
end;
self.use := func_wall_use;
if (self.spawnflags AND 4)>0 then begin
self.solid := SOLID_BSP;
end else begin
self.solid := SOLID_NOT;
self.svflags := self.svflags OR SVF_NOCLIENT;
end;
gi.linkentity(self);
end;
(*QUAKED func_object (0 .5 .8) ? TRIGGER_SPAWN ANIMATED ANIMATED_FAST
This is solid bmodel that will fall if it's support it removed.
*)
procedure func_object_touch(self, other: edict_p; plane: cplane_p; surf: csurface_p); cdecl;
begin
// only squash thing we fall on top of
if plane=Nil then
exit;
if plane.normal[2] < 1.0 then
exit;
if other.takedamage = DAMAGE_NO then
exit;
T_Damage(other, self, self, vec3_origin, self.s.origin, vec3_origin, self.dmg, 1, 0, MOD_CRUSH);
end;
procedure func_object_release(self: edict_p); cdecl;
begin
self.movetype := MOVETYPE_TOSS;
self.touch := func_object_touch;
end;
procedure func_object_use(self, other, activator: edict_p); cdecl;
begin
self.solid := SOLID_BSP;
self.svflags := self.svflags AND NOT SVF_NOCLIENT;
self.use := Nil;
KillBox(self);
func_object_release(self);
end;
procedure SP_func_object(self: edict_p); cdecl;
begin
gi.setmodel (self, self.model);
self.mins[0] := self.mins[0] + 1;
self.mins[1] := self.mins[1] + 1;
self.mins[2] := self.mins[2] + 1;
self.maxs[0] := self.maxs[0] - 1;
self.maxs[1] := self.maxs[1] - 1;
self.maxs[2] := self.maxs[2] - 1;
if self.dmg=0 then
self.dmg := 100;
if self.spawnflags = 0 then begin
self.solid := SOLID_BSP;
self.movetype := MOVETYPE_PUSH;
self.think := func_object_release;
self.nextthink := level.time + 2 * FRAMETIME;
end else begin
self.solid := SOLID_NOT;
self.movetype := MOVETYPE_PUSH;
self.use := func_object_use;
self.svflags := self.svflags OR SVF_NOCLIENT;
end;
if (self.spawnflags AND 2)>0 then
self.s.effects := self.s.effects OR EF_ANIM_ALL;
if (self.spawnflags AND 4)>0 then
self.s.effects := self.s.effects OR EF_ANIM_ALLFAST;
self.clipmask := MASK_MONSTERSOLID;
gi.linkentity(self);
end;
(*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST
Any brush that you want to explode or break apart. If you want an
ex0plosion, set dmg and it will do a radius explosion of that amount
at the center of the bursh.
If targeted it will not be shootable.
health defaults to 100.
mass defaults to 75. This determines how much debris is emitted when
it explodes. You get one large chunk per 100 of mass (up to 8) and
one small chunk per 25 of mass (up to 16). So 800 gives the most.
*)
procedure func_explosive_explode(self, inflictor, attacker: edict_p; damage: Integer; point: vec3_t); cdecl;
Var origin, chunkorigin, size: vec3_t; count, mass: Integer;
begin
// bmodel origins are (0 0 0), we need to adjust that here
VectorScale(self.size, 0.5, size);
VectorAdd(self.absmin, size, origin);
VectorCopy(origin, self.s.origin);
self.takedamage := DAMAGE_NO;
if self.dmg<>0 then
T_RadiusDamage(self, attacker, self.dmg, Nil, self.dmg+40, MOD_EXPLOSIVE);
VectorSubtract(self.s.origin, inflictor.s.origin, self.velocity);
VectorNormalize(self.velocity);
VectorScale(self.velocity, 150, self.velocity);
// start chunks towards the center
VectorScale (size, 0.5, size);
mass := self.mass;
if mass=0 then
mass := 75;
// big chunks
if mass >= 100 then begin
count := mass div 100;
if count > 8 then
count := 8;
while count<>0 do begin
dec(count);
chunkorigin[0] := origin[0] + crandom() * size[0];
chunkorigin[1] := origin[1] + crandom() * size[1];
chunkorigin[2] := origin[2] + crandom() * size[2];
ThrowDebris(self, 'models/objects/debris1/tris.md2', 1, chunkorigin);
end;
end;
// small chunks
count := mass div 25;
if count > 16 then
count := 16;
while count<>0 do begin
dec(count);
chunkorigin[0] := origin[0] + crandom() * size[0];
chunkorigin[1] := origin[1] + crandom() * size[1];
chunkorigin[2] := origin[2] + crandom() * size[2];
ThrowDebris (self, 'models/objects/debris2/tris.md2', 2, chunkorigin);
end;
G_UseTargets(self, attacker);
if self.dmg<>0 then
BecomeExplosion1(self)
else
G_FreeEdict(self);
end;
procedure func_explosive_use(self, other, activator: edict_p); cdecl;
begin
func_explosive_explode (self, self, other, self.health, vec3_origin);
end;
procedure func_explosive_spawn(self, other, activator: edict_p); cdecl;
begin
self.solid := SOLID_BSP;
self.svflags := self.svflags AND NOT SVF_NOCLIENT;
self.use := Nil;
KillBox(self);
gi.linkentity(self);
end;
procedure SP_func_explosive(self: edict_p); cdecl;
begin
if deathmatch.value<>0 then begin // auto-remove for deathmatch
G_FreeEdict(self);
exit;
end;
self.movetype := MOVETYPE_PUSH;
gi.modelindex ('models/objects/debris1/tris.md2');
gi.modelindex ('models/objects/debris2/tris.md2');
gi.setmodel(self, self.model);
if (self.spawnflags AND 1)>0 then begin
self.svflags := self.svflags OR SVF_NOCLIENT;
self.solid := SOLID_NOT;
self.use := func_explosive_spawn;
end else begin
self.solid := SOLID_BSP;
if self.targetname<>Nil then
self.use := func_explosive_use;
end;
if (self.spawnflags AND 2)>0 then
self.s.effects := self.s.effects OR EF_ANIM_ALL;
if (self.spawnflags AND 4)>0 then
self.s.effects := self.s.effects OR EF_ANIM_ALLFAST;
if @self.use <> @func_explosive_use then begin
if self.health=0 then
self.health := 100;
self.die := func_explosive_explode;
self.takedamage := DAMAGE_YES;
end;
gi.linkentity(self);
end;
(*QUAKED misc_explobox (0 .5 .8) (-16 -16 0) (16 16 40)
Large exploding box. You can override its mass (100),
health (80), and dmg (150).
*)
procedure barrel_touch(self, other: edict_p; plane: cplane_p; surf: csurface_p); cdecl;
Var ratio: Single; v: vec3_t;
begin
if (other.groundentity=Nil) or (other.groundentity = self) then
exit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -