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

📄 g_monster.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      if ((ent^.watertype and CONTENTS_LAVA) <> 0) then
      begin
        if (random <= 0.5) then
          gi.sound(ent, CHAN_BODY, gi.soundindex('player/lava1.wav'), 1, ATTN_NORM, 0)
        else
          gi.sound(ent, CHAN_BODY, gi.soundindex('player/lava2.wav'), 1, ATTN_NORM, 0);
      end
      else if (ent^.watertype and CONTENTS_SLIME) <> 0 then
        gi.sound(ent, CHAN_BODY, gi.soundindex('player/watr_in.wav'), 1, ATTN_NORM, 0)
      else if (ent^.watertype and CONTENTS_WATER) <> 0 then
        gi.sound(ent, CHAN_BODY, gi.soundindex('player/watr_in.wav'), 1, ATTN_NORM, 0);
    end;

    //CNH    ent->flags |= FL_INWATER;
    ent^.flags := ent^.flags or FL_INWATER;
    ent^.damage_debounce_time := 0;
  end;
end;

procedure M_droptofloor(ent: pedict_t);
var
  end_: vec3_t;
  trace: trace_t;
begin
  Inc(ent^.s.origin[2]);
  VectorCopy(ent^.s.origin, end_);
  dec(end_[2], 256);

  trace := gi.trace(ent^.s.origin, ent^.mins, ent^.maxs, end_, ent, MASK_MONSTERSOLID);

  //CNH:  if (trace.fraction == 1 || trace.allsolid)
  if (trace.fraction = 1) or (trace.allsolid) then
    Exit;

  VectorCopy(trace.endpos, ent^.s.origin);

  gi.linkentity(ent);
  M_CheckGround(ent);
  M_CatagorizePosition(ent);
end;

procedure M_SetEffects(ent: pedict_t);
begin
  ent^.s.effects := ent^.s.effects and (not (EF_COLOR_SHELL or EF_POWERSCREEN));
  //CNH  ent->s.renderfx &= ~(RF_SHELL_RED|RF_SHELL_GREEN|RF_SHELL_BLUE);
  ent^.s.renderfx := ent^.s.renderfx and (not (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE));

  if (ent^.monsterinfo.aiflags and AI_RESURRECTING) <> 0 then
  begin
    ent^.s.effects := ent^.s.effects or EF_COLOR_SHELL;
    ent^.s.renderfx := ent^.s.renderfx or RF_SHELL_RED;
  end;

  if (ent^.health <= 0) then
    Exit;

  if (ent^.powerarmor_time > level.time) then
  begin
    if (ent^.monsterinfo.power_armor_type = POWER_ARMOR_SCREEN) then
    begin
      ent^.s.effects := ent^.s.effects or EF_POWERSCREEN;
    end
    else if (ent^.monsterinfo.power_armor_type = POWER_ARMOR_SHIELD) then
    begin
      ent^.s.effects := ent^.s.effects or EF_COLOR_SHELL;
      ent^.s.renderfx := ent^.s.renderfx or RF_SHELL_GREEN;
    end;
  end;
end;

procedure M_MoveFrame(self: pedict_t);
{ Added by Scott Price.  This needs to be defined/found/included:
type
  pmmove_t = ^mmove_t
}
var
  move: pmmove_t;
  index: integer;
begin
  move := self^.monsterinfo.currentmove;
  self^.nextthink := level.time + FRAMETIME;

  if ((self^.monsterinfo.nextframe) and (self^.monsterinfo.nextframe >= move^.firstframe)
  and (self^.monsterinfo.nextframe <= move^.lastframe)) then
  begin
    self^.s.frame := self^.monsterinfo.nextframe;
    self^.monsterinfo.nextframe := 0;
  end
  else
  begin
    if (self^.s.frame = move^.lastframe)then
    begin
      if Assigned(move^.endfunc) then
      begin
        move^.endfunc(self);

        // regrab move, endfunc is very likely to change it
        move := self^.monsterinfo.currentmove;

        // check for death
        if (self^.svflags and SVF_DEADMONSTER) <> 0 then
          Exit;
      end;
    end;

    if (self^.s.frame < move^.firstframe) or (self^.s.frame > move^.lastframe) then
    begin
      //CNH:  self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
      self^.monsterinfo.aiflags := self^.monsterinfo.aiflags and (not AI_HOLD_FRAME);
      self^.s.frame := move^.firstframe;
    end
    else
    begin
      if (self^.monsterinfo.aiflags AND AI_HOLD_FRAME) = 0 then
      begin
        Inc(self^.s.frame);
        if (self^.s.frame > move^.lastframe) then
          self^.s.frame := move^.firstframe;
      end;
    end;
  end;

  index := self^.s.frame - move^.firstframe;
  if Assigned(move^.frame[index].aifunc) then
    //CNH:  if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
    if (self^.monsterinfo.aiflags and AI_HOLD_FRAME) = 0 then
      move^.frame[index].aifunc(self, move^.frame[index].dist * self^.monsterinfo.scale)
    else
      move^.frame[index].aifunc(self, 0);

  if Assigned(move^.frame[index].thinkfunc) then
    move^.frame[index].thinkfunc(self);
end;

procedure monster_think(self: pedict_t);
begin
  M_MoveFrame(self);
  if (self^.linkcount <> self^.monsterinfo.linkcount) then
  begin
    self^.monsterinfo.linkcount := self^.linkcount;
    M_CheckGround(self);
  end;

  M_CatagorizePosition(self);
  M_WorldEffects(self);
  M_SetEffects(self);
end;

{ ================
monster_use

Using a monster makes it angry at the current activator
================ }

procedure monster_use(self, other, activator: pedict_t);
begin
  if (self^.enemy)then
    Exit;
  if (self^.health <= 0)then
    Exit;
  if (activator^.flags and FL_NOTARGET) <> 0then
    Exit;
  //CNH:  if (!(activator->client) && !(activator->monsterinfo.aiflags & AI_GOOD_GUY))
  if (activator^.client = 0) and ((activator^.monsterinfo.aiflags and AI_GOOD_GUY) = 0) then
    Exit;

  // delay reaction so if the monster is teleported, its sound is still heard
  self^.enemy := activator;
  FoundTarget(self);
end;

procedure monster_triggered_spawn(self: pedict_t);
begin
  Inc(self^.s.origin[2], 1);
  KillBox(self);

  self^.solid := SOLID_BBOX;
  self^.movetype := MOVETYPE_STEP;
  //CNH:  self->svflags &= ~SVF_NOCLIENT;
  self^.svflags := self^.svflags and (NOT SVF_NOCLIENT);
  self^.air_finished := level.time + 12;
  gi.linkentity(self);

  monster_start_go(self);

  //CNH:  if (self->enemy && !(self->spawnflags & 1) && !(self->enemy->flags & FL_NOTARGET))
  if (self^.enemy <> Nil) AND ((self^.spawnflags AND 1) = 0) AND ((self^.enemy^.flags AND FL_NOTARGET) = 0) then
    if Assigned(self^.enemy) and ((self^.spawnflags and 1) = 0) and ((self^.enemy^.flage and FL_NOTARGET) = 0)) then
    begin
      FoundTarget(self)
    end
    else
    begin
      self^.enemy := Nil;
    end;
end;

procedure monster_triggered_spawn_use(self, other, activator: pedict_t);
begin
  // we have a one frame delay here so we don't telefrag the guy who activated us
  self^.think := monster_triggered_spawn;
  self^.nextthink := level.time + FRAMETIME;
  if Assigned(activator^.client) then
    self^.enemy := activator;
  self^.use := monster_use;
end;

procedure monster_triggered_start(self: pedict_t);
begin
  self^.solid := SOLID_NOT;
  self^.movetype := MOVETYPE_NONE;
  self^.svflags := self^.svflags or SVF_NOCLIENT;
  self^.nextthink := 0;
  self^.use := monster_triggered_spawn_use;
end;

{ ================
monster_death_use

When a monster dies, it fires all of its targets with the current
enemy as activator.
================ }

procedure monster_death_use(self : pedict_t);
begin
  self^.flags := self^.flags and (NOT (FL_FLY or FL_SWIM));
  self^.monsterinfo.aiflags := self^.monsterinfo.aiflags and AI_GOOD_GUY;

  if Assigned(self^.item) then
  begin
    Drop_Item(self, self^.item);
    self^.item := Nil;
  end;

  if (self^.deathtarget)then
    self^.target := self^.deathtarget;

  if (self^.target = Nil) then
    Exit;

  G_UseTargets(self, self^.enemy);
end;

//============================================================================

function monster_start(self: pedict_t): qboolean;
begin
  if (deathmatch^.value) then
  begin
    G_FreeEdict(self);
    result := false;
    exit;
  end;

  //CNH:  if ((self->spawnflags & 4) && !(self->monsterinfo.aiflags & AI_GOOD_GUY))
  if ((self^.spawnflags and 4) <> 0) and ((self^.monsterinfo.aiflags and AI_GOOD_GUY) = 0) then
  begin
    self^.spawnflags := self^.spawnflags and (not 4);
    self^.spawnflags := self^.spawnflags or 1;
    { The following line was originally commented out }
//  gi.dprintf("fixed spawnflags on %s at %s\n", self->classname, vtos(self->s.origin));
  end;

  if (self^.monsterinfo.aiflags and AI_GOOD_GUY) = 0then
    Inc(level.total_monsters);

  self^.nextthink := level.time + FRAMETIME;
  self^.svflags := self^.svflags or SVF_MONSTER;
  self^.s.renderfx := self^.s.renderfx or RF_FRAMELERP;
  self^.takedamage := DAMAGE_AIM;
  self^.air_finished := level.time + 12;
  self^.use := monster_use;
  self^.max_health := self^.health;
  self^.clipmask := MASK_MONSTERSOLID;

  self^.s.skinnum := 0;
  self^.deadflag := DEAD_NO;
  self^.svflags := self^.svflags and (not SVF_DEADMONSTER);

  if (self^.monsterinfo.checkattack = 0) then
    self^.monsterinfo.checkattack := M_CheckAttack;

  VectorCopy(self^.s.origin, self^.s.old_origin);

  if (st.item) then
  begin
    self^.item := FindItemByClassname(st.item);
    if (self^.item = 0) then
      gi.dprintf('%s at %s has bad item: %s'#10, self^.classname, vtos(self^.s.origin), st.item);
  end;

  // randomize what frame they start on
  if (self^.monsterinfo.currentmove) then
    self^.s.frame := self^.monsterinfo.currentmove^.firstframe +
                      (Random(RAND_MAX + 1) mod (self^.monsterinfo.currentmove^.lastframe
                      - self^.monsterinfo.currentmove^.firstframe + 1));

  Result := True;
end;

  { TODO:  Determine if the following routines need Interface declarations }
  
procedure monster_start_go(self: pedict_t);
var
  v: vec3_t;
  notcombat, fixup: qboolean;
  target: Pedict_t;
begin
  if (self^.health <= 0) then
    Exit;

  // check for target to combat_point and change to combattarget
  if (self^.target) then
  begin
    target := Nil;
    notcombat := False;
    fixup := False;

    target := G_Find(target, FOFS(targetname), self^.target);
    while ((target <> Nil) do
    begin
      TRY
        if (strcmp(target^.classname, 'point_combat') = 0) then
        begin
          self^.combattarget := self^.target;
          fixup := True;
        end
        else
        begin
          notcombat := True;
        end;
      FINALLY
        target := G_Find(target, FOFS(targetname), self^.target);
      END;
    end;
    if (notcombat) AND (self^.combattarget) then
      gi.dprintf('%s at %s has target with mixed types'#10, self^.classname, vtos(self^.s.origin));

    if (fixup) then
      self^.target := Nil;
  end;

  // validate combattarget
  if (self^.combattarget) then
  begin
    target := Nil;
    target := G_Find(target, FOFS(targetname), self^.combattarget);
    while (target <> Nil) do
    begin
      TRY
        if (strcmp(target^.classname, 'point_combat') <> 0) then
        begin
          gi.dprintf('%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)'#10,
            self^.classname, Integer(self^.s.origin[0]), Integer(self^.s.origin[1]), Integer(self^.s.origin[2]),
            self^.combattarget, target^.classname, Integer(target^.s.origin[0]), Integer(target^.s.origin[1]),
            Integer(target^.s.origin[2]));
        end;
      FINALLY
        target := G_Find(target, FOFS(targetname), self^.combattarget);
      END;
    end;
  end;

  if (self^.target) then
  begin
    self^.movetarget := G_PickTarget(self^.target)
    self^.goalentity := self^.movetarget;
    if (self^.movetarget = 0) then
    begin
      gi.dprintf ('%s can''t find target %s at %s'#10, self^.classname, self^.target, vtos(self^.s.origin));
      self^.target := Nil;
      self^.monsterinfo.pausetime := 100000000;
      self^.monsterinfo.stand(self);
    end
    else if (strcmp(self^.movetarget^.classname, 'path_corner') = 0) then
    begin
      VectorSubtract(self^.goalentity^.s.origin, self^.s.origin, v);
      self^.s.angles[YAW] := vectoyaw(v);
      self^.ideal_yaw := self^.s.angles[YAW];
      self^.monsterinfo.walk(self);
      self^.target := Nil;
    end
    else
    begin
      self^.movetarget := Nil;
      self^.goalentity := self^.movetarget;
      self^.monsterinfo.pausetime := 100000000;
      self^.monsterinfo.stand(self);
    end;
  end
  else
  begin
    self^.monsterinfo.pausetime := 100000000;
    self^.monsterinfo.stand(self);
  end;

  self^.think := monster_think;
  self^.nextthink := level.time + FRAMETIME;
end;

procedure walkmonster_start_go(self: Pedict_t);
begin
  if ((self^.spawnflags AND 2) = 0) AND (level.time < 1) then
  begin
    M_droptofloor(self);

    if (self^.groundentity) then
      if (M_walkmove(self, 0, 0) = 0) then
        gi.dprintf('%s in solid at %s'#10, self^.classname, vtos(self^.s.origin));
  end;

  if (self^.yaw_speed = 0) then
    self^.yaw_speed := 20;
  self^.viewheight := 25;

  monster_start_go(self);

  if (self^.spawnflags AND 2) <> 0 then
    monster_triggered_start(self);
end;

procedure walkmonster_start(self: Pedict_t);
begin
  self^.think := walkmonster_start_go;
  monster_start(self);
end;

procedure flymonster_start_go(self: Pedict_t);
begin
  if (M_walkmove(self, 0, 0) = 0) then
    gi.dprintf('%s in solid at %s'#10, self^.classname, vtos(self^.s.origin));

  if (self^.yaw_speed = 0) then
    self^.yaw_speed := 10;

  self^.viewheight := 25;

  monster_start_go(self);

  if (self^.spawnflags AND 2) <> 0 then
    monster_triggered_start(self);
end;

procedure flymonster_start(self: Pedict_t);
begin
  self^.flags := self^.flags OR FL_FLY;
  self^.think := flymonster_start_go;
  monster_start(self);
end;

procedure swimmonster_start_go(self: Pedict_t);
begin
  if (self^.yaw_speed = 0) then
    self^.yaw_speed := 10;

  self^.viewheight := 10;

  monster_start_go(self);

  if (self^.spawnflags AND 2) <> 0 then
    monster_triggered_start(self);
end;

procedure swimmonster_start(self: Pedict_t);
begin
  self^.flags := self^.flags OR FL_SWIM;
  self^.think := swimmonster_start_go;
  monster_start(self);
end;

end.

⌨️ 快捷键说明

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