⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 g_func.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 4 页
字号:
    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 + -