📄 g_func.pas
字号:
end;
end
else
begin
train_next (self);
end;
end;
procedure train_next (self:pedict_t);
label again;
var
ent:pedict_t;
dest:vec3_t;
first:qboolean;
begin
first := true;
again:
if (not self^.target) then
begin
// gi.dprintf ('train_next: no next target\n');
exit;
end;
ent := G_PickTarget (self^.target);
if (not ent) then
begin
gi.dprintf ('train_next: bad target %s\n', self^.target);
exit;
end;
self^.target := ent^.target;
// check for a teleport path_corner
if (ent^.spawnflags and 1) then
begin
if (not first) then
begin
gi.dprintf ('connected teleport path_corners, see %s at %s\n', ent^.classname, vtos(ent^.s.origin));
exit;
end;
first := false;
VectorSubtract (ent^.s.origin, self^.mins, self^.s.origin);
VectorCopy (self^.s.origin, self^.s.old_origin);
gi.linkentity (self);
goto again;
end;
self^.moveinfo.wait := ent^.wait;
self^.target_ent := ent;
if (not (self^.flags and FL_TEAMSLAVE)) then
begin
if (self^.moveinfo.sound_start) then
gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self^.moveinfo.sound_start, 1, ATTN_STATIC, 0);
self^.s.sound := self^.moveinfo.sound_middle;
end;
VectorSubtract (ent^.s.origin, self^.mins, dest);
self^.moveinfo.state := STATE_TOP;
VectorCopy (self^.s.origin, self^.moveinfo.start_origin);
VectorCopy (dest, self^.moveinfo.end_origin);
Move_Calc (self, dest, train_wait);
self^.spawnflags := self^.spawnflags or TRAIN_START_ON;
end;
procedure train_resume (self:pedict_t);
var
ent:pedict_t;
dest:vec3_t;
begin
ent := self^.target_ent;
VectorSubtract (ent^.s.origin, self^.mins, dest);
self^.moveinfo.state := STATE_TOP;
VectorCopy (self^.s.origin, self^.moveinfo.start_origin);
VectorCopy (dest, self^.moveinfo.end_origin);
Move_Calc (self, dest, train_wait);
self^.spawnflags := self^.spawnflags or TRAIN_START_ON;
end;
procedure func_train_find (self:pedict_t);
var
ent:pedict_t;
begin
if (not self^.target) then
begin
gi.dprintf ('train_find: no target\n');
exit;
end;
ent := G_PickTarget (self^.target);
if (not ent) then
begin
gi.dprintf ('train_find: target %s not found\n', self^.target);
exit;
end;
self^.target := ent^.target;
VectorSubtract (ent^.s.origin, self^.mins, self^.s.origin);
gi.linkentity (self);
// if not triggered, start immediately
if (not self^.targetname) then
self^.spawnflags := self^.spawnflags or TRAIN_START_ON;
if (self^.spawnflags and TRAIN_START_ON) then
begin
self^.nextthink := level.time + FRAMETIME;
self^.think := train_next;
self^.activator := self;
end;
end;
procedure train_use (self:pedict_t; other:pedict_t; activator:pedict_t);
begin
self^.activator := activator;
if (self^.spawnflags and TRAIN_START_ON) then
begin
if (not (self^.spawnflags and TRAIN_TOGGLE)) then
exit;
self^.spawnflags := self^.spawnflags and (not TRAIN_START_ON);
VectorClear (self^.velocity);
self^.nextthink := 0;
end
else
begin
if (self^.target_ent) then
train_resume(self)
else
train_next(self);
end;
end;
procedure SP_func_train (self:pedict_t);
begin
self^.movetype := MOVETYPE_PUSH;
VectorClear (self^.s.angles);
self^.blocked := train_blocked;
if (self^.spawnflags and TRAIN_BLOCK_STOPS) then
self^.dmg := 0
else
begin
if (not self^.dmg) then
self^.dmg := 100;
end;
self^.solid := SOLID_BSP;
gi.setmodel (self, self^.model);
if (st.noise) then
self^.moveinfo.sound_middle := gi.soundindex (st.noise);
if (not self^.speed) then
self^.speed := 100;
self^.moveinfo.speed := self^.speed;
self^.moveinfo.accel := self^.moveinfo.decel := self^.moveinfo.speed;
self^.use := train_use;
gi.linkentity (self);
if (self^.target) then
begin
// start trains on the second frame, to make sure their targets have had
// a chance to spawn
self^.nextthink := level.time + FRAMETIME;
self^.think := func_train_find;
end
else
begin
gi.dprintf ('func_train without a target at %s\n', vtos(self^.absmin));
end;
end;
(*QUAKED trigger_elevator (0.3 0.1 0.6) (-8 -8 -8) (8 8 8)
*)
procedure trigger_elevator_use (self:pedict_t; other:pedict_t; activator:pedict_t);
var
target:pedict_t;
begin
if (self^.movetarget^.nextthink)
begin
// gi.dprintf('elevator busy\n');
exit;
end
if (not other^.pathtarget) then
begin
gi.dprintf('elevator used with no pathtarget\n');
exit;
end;
target := G_PickTarget (other^.pathtarget);
if (not target) then
begin
gi.dprintf('elevator used with bad pathtarget: %s\n', other^.pathtarget);
exit;
end;
self^.movetarget^.target_ent := target;
train_resume (self^.movetarget);
end;
procedure trigger_elevator_init (self:pedict_t);
begin
if (not self^.target) then
begin
gi.dprintf('trigger_elevator has no target\n');
exit;
end;
self^.movetarget := G_PickTarget (self^.target);
if (not self^.movetarget) then
begin
gi.dprintf('trigger_elevator unable to find target %s\n', self^.target);
exit;
end;
if (strcomp(self^.movetarget^.classname, 'func_train') not := 0) then
begin
gi.dprintf('trigger_elevator target %s is not a train\n', self^.target);
exit;
end;
self^.use := trigger_elevator_use;
self^.svflags := SVF_NOCLIENT;
end;
procedure SP_trigger_elevator (self:pedict_t);
begin
self^.think := trigger_elevator_init;
self^.nextthink := level.time + FRAMETIME;
end;
(*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON
"wait" base time between triggering all targets, default is 1
"random" wait variance, default is 0
so, the basic time between firing is a random time between
(wait - random) and (wait + random)
"delay" delay before first firing when turned on, default is 0
"pausetime" additional delay used only the very first time
and only if spawned with START_ON
These can used but not touched.
*)
procedure func_timer_think (self:pedict_t);
begin
G_UseTargets (self, self^.activator);
self^.nextthink := level.time + self^.wait + random * self^.random;
end;
procedure func_timer_use (self:pedict_t; other:pedict_t; activator:pedict_t);
begin
self^.activator := activator;
// if on, turn it off
if (self^.nextthink) then
begin
self^.nextthink := 0;
exit;
end;
// turn it on
if (self^.delay) then
self^.nextthink := level.time + self^.delay
else
func_timer_think (self);
end;
procedure SP_func_timer (self:pedict_t);
begin
if (not self^.wait) then
self^.wait := 1.0;
self^.use := func_timer_use;
self^.think := func_timer_think;
if (self^.random >= self^.wait) then
begin
self^.random := self^.wait - FRAMETIME;
gi.dprintf('func_timer at %s has random >= wait\n', vtos(self^.s.origin));
end;
if (self^.spawnflags and 1) then
begin
self^.nextthink := level.time + 1.0 + st.pausetime + self^.delay + self^.wait + random * self^.random;
self^.activator := self;
end;
self^.svflags := SVF_NOCLIENT;
end;
(*QUAKED func_conveyor (0 .5 .8) ? START_ON TOGGLE
Conveyors are stationary brushes that move what's on them.
The brush should be have a surface with at least one current content enabled.
speed default 100
*)
procedure func_conveyor_use (self:pedict_t; other:pedict_t; activator:pedict_t);
begin
if (self^.spawnflags and 1) then
begin
self^.speed := 0;
self^.spawnflags := self^.spawnflags and (not 1);
end
else
begin
self^.speed := self^.count;
self^.spawnflags |:= 1;
end;
if (not (self^.spawnflags and 2)) then
self^.count := 0;
end;
procedure SP_func_conveyor (self:pedict_t);
begin
if (not self^.speed) then
self^.speed := 100;
if (not (self^.spawnflags and 1)) then
begin
self^.count := self^.speed;
self^.speed := 0;
end;
self^.use := func_conveyor_use;
gi.setmodel (self, self^.model);
self^.solid := SOLID_BSP;
gi.linkentity (self);
end;
(*QUAKED func_door_secret (0 .5 .8) ? always_shoot 1st_left 1st_down
A secret door. Slide back and then to the side.
open_once doors never closes
1st_left 1st move is left of arrow
1st_down 1st move is down from arrow
always_shoot door is shootebale even if targeted
"angle" determines the direction
"dmg" damage to inflic when blocked (default 2)
"wait" how long to hold in the open position (default 5, -1 means hold)
*)
const SECRET_ALWAYS_SHOOT = 1;
const SECRET_1ST_LEFT = 2;
const SECRET_1ST_DOWN = 4;
procedure door_secret_use (self:pedict_t; other:pedict_t; activator:pedict_t) then
begin
// make sure we're not already moving
if (not VectorCompare(self^.s.origin, vec3_origin)) then
exit;
Move_Calc (self, self^.pos1, door_secret_move1);
door_use_areaportals (self, true);
end;
procedure door_secret_move1 (self:pedict_t);
begin
self^.nextthink := level.time + 1.0;
self^.think := door_secret_move2;
end;
procedure door_secret_move2 (self:pedict_t);
begin
Move_Calc (self, self^.pos2, door_secret_move3);
end;
procedure door_secret_move3 (self:pedict_t);
begin
if (self^.wait = -1) then
exit;
self^.nextthink := level.time + self^.wait;
self^.think := door_secret_move4;
end;
procedure door_secret_move4 (self:pedict_t);
begin
Move_Calc (self, self^.pos1, door_secret_move5);
end;
procedure door_secret_move5 (self:pedict_t);
begin
self^.nextthink := level.time + 1.0;
self^.think := door_secret_move6;
end;
procedure door_secret_move6 (self:pedict_t);
begin
Move_Calc (self, vec3_origin, door_secret_done);
end;
procedure door_secret_done (self:pedict_t);
begin
if (not (self^.targetname) or (self^.spawnflags and SECRET_ALWAYS_SHOOT))
begin
self^.health := 0;
self^.takedamage := DAMAGE_YES;
end;
door_use_areaportals (self, false);
end;
procedure door_secret_blocked (self:pedict_t; other:pedict_t);
begin
if (not (other^.svflags and SVF_MONSTER) and (not other^.client) ) then
begin
// give it a chance to go away on it's own terms (like gibs)
T_Damage (other, self, self, vec3_origin, other^.s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH);
// if it's still there, nuke it
if (other) then
BecomeExplosion1 (other);
exit;
end;
if (level.time < self^.touch_debounce_time) then
exit;
self^.touch_debounce_time := level.time + 0.5;
T_Damage (other, self, self, vec3_origin, other^.s.origin, vec3_origin, self^.dmg, 1, 0, MOD_CRUSH);
end;
procedure door_secret_die (self:pedict_t;inflictor :pedict_t; attacker:pedict_t ; damage:smallint;point: vec3_t );
begin
self^.takedamage := DAMAGE_NO;
door_secret_use (self, attacker, attacker);
end;
procedure SP_func_door_secret (ent:pedict_t);
var
forwards, right, up:vec3_t;
side:single;
width:single;
length:single;
begin
ent^.moveinfo.sound_start := gi.soundindex ('doors/dr1_strt.wav');
ent^.moveinfo.sound_middle := gi.soundindex ('doors/dr1_mid.wav');
ent^.moveinfo.sound_end := gi.soundindex ('doors/dr1_end.wav');
ent^.movetype := MOVETYPE_PUSH;
ent^.solid := SOLID_BSP;
gi.setmodel (ent, ent^.model);
ent^.blocked := door_secret_blocked;
ent^.use := door_secret_use;
if (not (ent^.targetname) or (ent^.spawnflags and SECRET_ALWAYS_SHOOT)) then
begin
ent^.health := 0;
ent^.takedamage := DAMAGE_YES;
ent^.die := door_secret_die;
end;
if (not ent^.dmg) then
ent^.dmg := 2;
if (not ent^.wait) then
ent^.wait := 5;
ent^.moveinfo.accel := 50;
ent^.moveinfo.decel := 50;
ent^.moveinfo.speed := 50;
// calculate positions
AngleVectors (ent^.s.angles, forwards, right, up);
VectorClear (ent^.s.angles);
side := 1.0 - (ent^.spawnflags and SECRET_1ST_LEFT);
if (ent^.spawnflags and SECRET_1ST_DOWN) then
width := abs(DotProduct(up, ent^.size))
else
width := abs(DotProduct(right, ent^.size));
length := abs(DotProduct(forwards, ent^.size));
if (ent^.spawnflags and SECRET_1ST_DOWN) then
VectorMA (ent^.s.origin, -1 * width, up, ent^.pos1)
else
VectorMA (ent^.s.origin, side * width, right, ent^.pos1);
VectorMA (ent^.pos1, length, forwards, ent^.pos2);
if (ent^.health) then
begin
ent^.takedamage := DAMAGE_YES;
ent^.die := door_killed;
ent^.max_health := ent^.health;
end
else if (ent^.targetname and ent^.message) then
begin
gi.soundindex ('misc/talk.wav');
ent^.touch := door_touch;
end;
ent^.classname := 'func_door';
gi.linkentity (ent);
end;
(*QUAKED func_killbox (1 0 0) ?
Kills everything inside when fired, irrespective of protection.
*)
procedure use_killbox (self:pedict_t; other:pedict_t ; activator:pedict_t);
begin
KillBox (self);
end;
procedure SP_func_killbox (ent:pedict_t);
begin
gi.setmodel (ent, ent^.model);
ent^.use := use_killbox;
ent^.svflags := SVF_NOCLIENT;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -