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

📄 g_func.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 4 页
字号:

  // find the smallest distance any member of the team will be moving
  min := abs(self^.moveinfo.distance);
  for ent := self^.teamchain to ent do
  begin
    dist := abs(ent^.moveinfo.distance);
    if (dist < min) then
      min := dist;
    ent := ent^.teamchain;  
  end;

  time := min / self^.moveinfo.speed;

  // adjust speeds so they will all complete at the same time
  for ent := self to ent do
  begin
    newspeed := fabs(ent^.moveinfo.distance) / time;
    ratio := newspeed / ent^.moveinfo.speed;
    if (ent^.moveinfo.accel = ent^.moveinfo.speed) then
      ent^.moveinfo.accel := newspeed
    else
      ent^.moveinfo.accel := ent^.moveinfo.accel * ratio;
    if (ent^.moveinfo.decel = ent^.moveinfo.speed) then
      ent^.moveinfo.decel := newspeed
    else
      ent^.moveinfo.decel *:= ratio;
    ent^.moveinfo.speed := newspeed;
    ent := ent^.teamchain;
  end;
end;

procedure Think_SpawnDoorTrigger (ent:pedict_t);
var
  other:pedict_t;
  mins,maxs:vec3_t;
begin
  if (ent^.flags and FL_TEAMSLAVE) then
    exit;    // only the team leader spawns a trigger

  VectorCopy (ent^.absmin, mins);
  VectorCopy (ent^.absmax, maxs);

  for other := ent^.teamchain to other do
  begin
    AddPointToBounds (other^.absmin, mins, maxs);
    AddPointToBounds (other^.absmax, mins, maxs);
    other:=other^.teamchain;
  end;

  // expand 
  mins[0] := mins[0] - 60;
  mins[1] := mins[1] - 60;
  maxs[0] := maxs[0] + 60;
  maxs[1] := maxs[1] + 60;

  other := G_Spawn;
  VectorCopy (mins, other^.mins);
  VectorCopy (maxs, other^.maxs);
  other^.owner := ent;
  other^.solid := SOLID_TRIGGER;
  other^.movetype := MOVETYPE_NONE;
  other^.touch := Touch_DoorTrigger;
  gi.linkentity (other);

  if (ent^.spawnflags and DOOR_START_OPEN) then
    door_use_areaportals (ent, true);

  Think_CalcMoveSpeed (ent);
end;

procedure door_blocked  (self:pedict_t; other:pedict_t);
var
  ent: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;

  T_Damage (other, self, self, vec3_origin, other^.s.origin, vec3_origin, self^.dmg, 1, 0, MOD_CRUSH);

  if (self^.spawnflags and DOOR_CRUSHER) then
    exit;


// if a door has a negative wait, it would never come back if blocked,
// so let it just squash the object to death real fast
  if (self^.moveinfo.wait >= 0) then
  begin
    if (self^.moveinfo.state = STATE_DOWN) then
    begin
      for ent := self^.teammaster to ent do
      begin
        door_go_up (ent, ent^.activator);
        ent := ent^.teamchain;
      end;
    end
    else
    begin
      for ent := self^.teammaster to ent do
      begin
        door_go_down (ent);
        ent := ent^.teamchain;
      end;
    end;
  end;
end;

procedure door_killed (self:pedict_t; inflictor:pedict_t ; attacker:pedict_t ; damage:smallint; point:vec3_t );
var
  ent:pedict_t;
begin
  for ent := self^.teammaster to ent do
  begin
    
    ent^.health := ent^.max_health;
    ent^.takedamage := DAMAGE_NO;
    ent:=ent^.teamchain;
  end;
  door_use (self^.teammaster, attacker, attacker);
end;

procedure door_touch (self:pedict_t; other:pedict_t; plane:pcplane_t; surf:pcsurface_t);
begin
  if (not other^.client) then
    exit;

  if (level.time < self^.touch_debounce_time) then
    exit;
  self^.touch_debounce_time := level.time + 5.0;

  gi.centerprintf (other, '%s', self^.message);
  gi.sound (other, CHAN_AUTO, gi.soundindex ('misc/talk1.wav'), 1, ATTN_NORM, 0);
end;

procedure SP_func_door (ent:pedict_t);
var
  abs_movedir:vec3_t;
begin
  if (ent^.sounds <> 1) then
  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');
  end;

  G_SetMovedir (ent^.s.angles, ent^.movedir);
  ent^.movetype := MOVETYPE_PUSH;
  ent^.solid := SOLID_BSP;
  gi.setmodel (ent, ent^.model);

  ent^.blocked := door_blocked;
  ent^.use := door_use;
  
  if (not ent^.speed) then
    ent^.speed := 100;
  if (deathmatch^.value) then
    ent^.speed *:= 2;

  if (not ent^.accel) then
    ent^.accel := ent^.speed;
  if (not ent^.decel) then
    ent^.decel := ent^.speed;

  if (not ent^.wait) then
    ent^.wait := 3;
  if (not st.lip) then
    st.lip := 8;
  if (not ent^.dmg) then
    ent^.dmg := 2;

  // calculate second position
  VectorCopy (ent^.s.origin, ent^.pos1);
  abs_movedir[0] := fabs(ent^.movedir[0]);
  abs_movedir[1] := fabs(ent^.movedir[1]);
  abs_movedir[2] := fabs(ent^.movedir[2]);
  ent^.moveinfo.distance := abs_movedir[0] * ent^.size[0] + abs_movedir[1] * ent^.size[1] + abs_movedir[2] * ent^.size[2] - st.lip;
  VectorMA (ent^.pos1, ent^.moveinfo.distance, ent^.movedir, ent^.pos2);

  // if it starts open, switch the positions
  if (ent^.spawnflags and DOOR_START_OPEN) then
  begin
    VectorCopy (ent^.pos2, ent^.s.origin);
    VectorCopy (ent^.pos1, ent^.pos2);
    VectorCopy (ent^.s.origin, ent^.pos1);
  end;

  ent^.moveinfo.state := STATE_BOTTOM;

  if (ent^.health) then
  begin
    ent^.takedamage := DAMAGE_YES;
    ent^.die := door_killed;
    ent^.max_health := ent^.health;
  end
  else if (ent^.targetname andand ent^.message)
  begin
    gi.soundindex ('misc/talk.wav');
    ent^.touch := door_touch;
  end;
  
  ent^.moveinfo.speed := ent^.speed;
  ent^.moveinfo.accel := ent^.accel;
  ent^.moveinfo.decel := ent^.decel;
  ent^.moveinfo.wait := ent^.wait;
  VectorCopy (ent^.pos1, ent^.moveinfo.start_origin);
  VectorCopy (ent^.s.angles, ent^.moveinfo.start_angles);
  VectorCopy (ent^.pos2, ent^.moveinfo.end_origin);
  VectorCopy (ent^.s.angles, ent^.moveinfo.end_angles);

  if (ent^.spawnflags and 16) then
    ent^.s.effects := ent^.s.effects or EF_ANIM_ALL;
  if (ent^.spawnflags and 64) then
    ent^.s.effects := ent^.s.effects or EF_ANIM_ALLFAST;

  // to simplify logic elsewhere, make non-teamed doors into a team of one
  if (not ent^.team) then
    ent^.teammaster := ent;

  gi.linkentity (ent);

  ent^.nextthink := level.time + FRAMETIME;
  if (ent^.health or ent^.targetname) then
    ent^.think := Think_CalcMoveSpeed
  else
    ent^.think := Think_SpawnDoorTrigger;
end;


(*QUAKED func_door_rotating (0 .5 .8) ? START_OPEN REVERSE CRUSHER NOMONSTER ANIMATED TOGGLE X_AXIS Y_AXIS
TOGGLE causes the door to wait in both the start and end states for a trigger event.

START_OPEN  the door to moves to its destination when spawned, and operate in reverse.  It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
NOMONSTER  monsters will not trigger this door

You need to have an origin brush as part of this entity.  The center of that brush will be
the point around which it is rotated. It will rotate around the Z axis by default.  You can
check either the X_AXIS or Y_AXIS box to change that.

"distance" is how many degrees the door will be rotated.
"speed" determines how fast the door moves; default value is 100.

REVERSE will cause the door to rotate in the opposite direction.

"message"  is printed when the door is touched if it is a trigger door and it hasn't been fired yet
"angle"    determines the opening direction
"targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
"health"  if set, door must be shot open
"speed"    movement speed (100 default)
"wait"    wait before exiting (3 default, -1 := never exit)
"dmg"    damage to inflict when blocked (2 default)
"sounds"
1)  silent
2)  light
3)  medium
4)  heavy
*)

procedure SP_func_door_rotating (ent:pedict_t);
begin
  VectorClear (ent^.s.angles);

  // set the axis of rotation
  VectorClear(ent^.movedir);
  if (ent^.spawnflags and DOOR_X_AXIS) then
    ent^.movedir[2] := 1.0
  else if (ent^.spawnflags and DOOR_Y_AXIS) then
    ent^.movedir[0] := 1.0
  else // Z_AXIS
    ent^.movedir[1] := 1.0;

  // check for reverse rotation
  if (ent^.spawnflags and DOOR_REVERSE) then
    VectorNegate (ent^.movedir, ent^.movedir);

  if (not st.distance) then
  begin
    gi.dprintf('%s at %s with no distance set\n', ent^.classname, vtos(ent^.s.origin));
    st.distance := 90;
  end;

  VectorCopy (ent^.s.angles, ent^.pos1);
  VectorMA (ent^.s.angles, st.distance, ent^.movedir, ent^.pos2);
  ent^.moveinfo.distance := st.distance;

  ent^.movetype := MOVETYPE_PUSH;
  ent^.solid := SOLID_BSP;
  gi.setmodel (ent, ent^.model);

  ent^.blocked := door_blocked;
  ent^.use := door_use;

  if (not ent^.speed) then
    ent^.speed := 100;
  if (not ent^.accel) then
    ent^.accel := ent^.speed;
  if (not ent^.decel) then
    ent^.decel := ent^.speed;

  if (not ent^.wait) then
    ent^.wait := 3;
  if (not ent^.dmg) then
    ent^.dmg := 2;

  if (ent^.sounds <> 1) then
  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');
  end;

  // if it starts open, switch the positions
  if (ent^.spawnflags and DOOR_START_OPEN) then
  begin
    VectorCopy (ent^.pos2, ent^.s.angles);
    VectorCopy (ent^.pos1, ent^.pos2);
    VectorCopy (ent^.s.angles, ent^.pos1);
    VectorNegate (ent^.movedir, ent^.movedir);
  end;

  if (ent^.health) then
  begin
    ent^.takedamage := DAMAGE_YES;
    ent^.die := door_killed;
    ent^.max_health := ent^.health;
  end;
  
  if (ent^.targetname and ent^.message) then
  begin
    gi.soundindex (misc/talk.wav);
    ent^.touch := door_touch;
  end;

  ent^.moveinfo.state := STATE_BOTTOM;
  ent^.moveinfo.speed := ent^.speed;
  ent^.moveinfo.accel := ent^.accel;
  ent^.moveinfo.decel := ent^.decel;
  ent^.moveinfo.wait := ent^.wait;
  VectorCopy (ent^.s.origin, ent^.moveinfo.start_origin);
  VectorCopy (ent^.pos1, ent^.moveinfo.start_angles);
  VectorCopy (ent^.s.origin, ent^.moveinfo.end_origin);
  VectorCopy (ent^.pos2, ent^.moveinfo.end_angles);

  if (ent^.spawnflags and 16) then
    ent^.s.effects := ent^.s.effects or EF_ANIM_ALL;

  // to simplify logic elsewhere, make non-teamed doors into a team of one
  if (not ent^.team) then
    ent^.teammaster := ent;

  gi.linkentity (ent);

  ent^.nextthink := level.time + FRAMETIME;
  if (ent^.health or ent^.targetname) then
    ent^.think := Think_CalcMoveSpeed
  else
    ent^.think := Think_SpawnDoorTrigger;
end;


(*QUAKED func_water (0 .5 .8) ? START_OPEN
func_water is a moveable water brush.  It must be targeted to operate.  Use a non-water texture at your own risk.

START_OPEN causes the water to move to its destination when spawned and operate in reverse.

"angle"    determines the opening direction (up or down only)
"speed"    movement speed (25 default)
"wait"    wait before exiting (-1 default, -1 := TOGGLE)
"lip"    lip remaining at end of move (0 default)
"sounds"  (yes, these need to be changed)
0)  no sound
1)  water
2)  lava
*)

procedure SP_func_water (self:pedict_t);
var
  abs_movedir:vec3_t;
begin
  G_SetMovedir (self^.s.angles, self^.movedir);
  self^.movetype := MOVETYPE_PUSH;
  self^.solid := SOLID_BSP;
  gi.setmodel (self, self^.model);

  case (self^.sounds) of
   
     1: // water
     begin  
      self^.moveinfo.sound_start := gi.soundindex  ('world/mov_watr.wav');
      self^.moveinfo.sound_end := gi.soundindex  ('world/stp_watr.wav');
      break;
                 end;
     2: // lava
     begin
      self^.moveinfo.sound_start := gi.soundindex  ('world/mov_watr.wav');
      self^.moveinfo.sound_end := gi.soundindex  ('world/stp_watr.wav');
      break;
     end;
                 else break;  
  end;

  // calculate second position
  VectorCopy (self^.s.origin, self^.pos1);
  abs_movedir[0] := abs(self^.movedir[0]);
  abs_movedir[1] := abs(self^.movedir[1]);
  abs_movedir[2] := abs(self^.movedir[2]);
  self^.moveinfo.distance := abs_movedir[0] * self^.size[0] + abs_movedir[1] * self^.size[1] + abs_movedir[2] * self^.size[2] - st.lip;
  VectorMA (self^.pos1, self^.moveinfo.distance, self^.movedir, self^.pos2);

  // if it starts open, switch the positions
  if (self^.spawnflags and DOOR_START_OPEN) then
  begin
    VectorCopy (self^.pos2, self^.s.origin);
    VectorCopy (self^.pos1, self^.pos2);
    VectorCopy (self^.s.origin, self^.pos1);
  end;

  VectorCopy (self^.pos1, self^.moveinfo.start_origin);
  VectorCopy (self^.s.angles, self^.moveinfo.start_angles);
  VectorCopy (self^.pos2, self^.moveinfo.end_origin);
  VectorCopy (self^.s.angles, self^.moveinfo.end_angles);

  self^.moveinfo.state := STATE_BOTTOM;

  if (not self^.speed) then
    self^.speed := 25;
  self^.moveinfo.speed := self^.speed;
  self^.moveinfo.decel := self^.moveinfo.speed;
  self^.moveinfo.accel := self^.moveinfo.decel;

  if (not self^.wait) then
    self^.wait := -1;
  self^.moveinfo.wait := self^.wait;

  self^.use := door_use;

  if (self^.wait = -1) then
    self^.spawnflags := self^.spawnflags or DOOR_TOGGLE;

  self^.classname := 'func_door';

  gi.linkentity (self);
end;


const TRAIN_START_ON  =  1;
const TRAIN_TOGGLE  =  2;
const TRAIN_BLOCK_STOPS  = 4;

(*QUAKED func_train (0 .5 .8) ? START_ON TOGGLE BLOCK_STOPS
Trains are moving platforms that players can ride.
The targets origin specifies the min point of the train at each corner.
The train spawns at the first target it is pointing at.
If the train is the target of a button or trigger, it will not begin moving until activated.
speed  default 100
dmg    default  2
noise  looping sound to play when the train is in motion

*)


procedure train_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;

  if (not self^.dmg) 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 train_wait (self:pedict_t);
var
    savetarget:pchar;
    ent:pedict_t;
begin
  if (self^.target_ent^.pathtarget) then
  begin


    ent := self^.target_ent;
    savetarget := ent^.target;
    ent^.target := ent^.pathtarget;
    G_UseTargets (ent, self^.activator);
    ent^.target := savetarget;

    // make sure we didn't get killed by a killtarget
    if (not self^.inuse) then
      exit;
  end;

  if (self^.moveinfo.wait) then
  begin
    if (self^.moveinfo.wait > 0) then
    begin
      self^.nextthink := level.time + self^.moveinfo.wait;
      self^.think := train_next;
    end
    else if (self^.spawnflags and TRAIN_TOGGLE) then  // andand wait < 0
    begin
      train_next (self);
      self^.spawnflags and:= ~TRAIN_START_ON;
      VectorClear (self^.velocity);
      self^.nextthink := 0;
    end;

    if (not (self^.flags and FL_TEAMSLAVE)) then
    begin
      if (self^.moveinfo.sound_end) then
        gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self^.moveinfo.sound_end, 1, ATTN_STATIC, 0);
      self^.s.sound := 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -