📄 g_misc.pas
字号:
(*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
*)
procedure TH_viewthing(ent: edict_p); cdecl;
begin
ent.s.frame := (ent.s.frame + 1) mod 7;
ent.nextthink := level.time + FRAMETIME;
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);
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; const 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;
ratio := other.mass / self.mass;
VectorSubtract(self.s.origin, other.s.origin, v);
M_walkmove(self, vectoyaw(v), 20 * ratio * FRAMETIME);
end;
procedure barrel_explode(self: edict_p); cdecl;
Var org: vec3_t; spd: Single; save: vec3_t;
begin
T_RadiusDamage (self, self.activator, self.dmg, Nil, self.dmg+40, MOD_BARREL);
VectorCopy(self.s.origin, save);
VectorMA(self.absmin, 0.5, self.size, self.s.origin);
// a few big chunks
spd := 1.5 * self.dmg / 200;
org[0] := self.s.origin[0] + crandom() * self.size[0];
org[1] := self.s.origin[1] + crandom() * self.size[1];
org[2] := self.s.origin[2] + crandom() * self.size[2];
ThrowDebris(self, 'models/objects/debris1/tris.md2', spd, org);
org[0] := self.s.origin[0] + crandom() * self.size[0];
org[1] := self.s.origin[1] + crandom() * self.size[1];
org[2] := self.s.origin[2] + crandom() * self.size[2];
ThrowDebris(self, 'models/objects/debris1/tris.md2', spd, org);
// bottom corners
spd := 1.75 * self.dmg / 200;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -