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

📄 g_monster.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  ent^.s.origin[2] := ent^.s.origin[2] + 1;
  VectorCopy(ent^.s.origin, end_);
  end_[2] := end_[2] - 256;

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

  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: edict_p);
begin
  ent^.s.effects := ent^.s.effects and (not (EF_COLOR_SHELL or EF_POWERSCREEN));
  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: edict_p);
var
  move: mmove_p;
  index: integer;
begin
  move := self^.monsterinfo.currentmove;
  self^.nextthink := level.time + FRAMETIME;

  if ((self^.monsterinfo.nextframe <> 0) 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
      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 (@mframe_a(move^.frame)[index].aifunc)<> nil then
    if (self^.monsterinfo.aiflags and AI_HOLD_FRAME) = 0 then
      mframe_a(move^.frame)[index].aifunc (self , mframe_a(move^.frame)[index].dist * self^.monsterinfo.scale)
    else
      mframe_a(move^.frame)[index].aifunc(self, 0);

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

procedure monster_think(self: edict_p);
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: edict_p);
begin
  if (self^.enemy <> nil)then
    Exit;
  if (self^.health <= 0)then
    Exit;
  if (activator^.flags and FL_NOTARGET) <> 0 then
    Exit;
  if (activator^.client = nil) 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: edict_p);
begin
  self^.s.origin[2] := self^.s.origin[2] + 1;
  KillBox(self);

  self^.solid := SOLID_BBOX;
  self^.movetype := MOVETYPE_STEP;
  self^.svflags := self^.svflags and (NOT SVF_NOCLIENT);
  self^.air_finished := level.time + 12;
  gi.linkentity(self);

  monster_start_go(self);

  if (self^.enemy <> nil) and ((self^.spawnflags and 1) = 0) and ((self^.enemy^.flags and FL_NOTARGET) = 0) then
  begin
    FoundTarget(self)
  end
  else
  begin
    self^.enemy := Nil;
  end;
end;

procedure monster_triggered_spawn_use(self, other, activator: edict_p);
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: edict_p);
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 : edict_p);
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 <> nil)then
    self^.target := self^.deathtarget;

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

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

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

function monster_start(self: edict_p): qboolean;
begin
  if (deathmatch^.value <> 0) then
  begin
    G_FreeEdict(self);
    Result := false;
    Exit;
  end;

  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) = 0 then
    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 = nil) then
    self^.monsterinfo.checkattack := M_CheckAttack;

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

  if (st.item <> nil) then
  begin
    self^.item := FindItemByClassname(st.item);
    if (self^.item = nil) 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 <> nil) then
    self^.s.frame := self^.monsterinfo.currentmove^.firstframe +
                      (rand() mod (self^.monsterinfo.currentmove^.lastframe
                      - self^.monsterinfo.currentmove^.firstframe + 1));

  Result := True;
end;

procedure monster_start_go(self: edict_p);
var
  v: vec3_t;
  notcombat, fixup: qboolean;
  target: edict_p;
begin
  if (self^.health <= 0) then
    Exit;

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

    { NOTE(SP):  Removed the TRY..FINALLY block that ensured the next call to
                 G_Find occured, due to possible performance issues with
                 try blocks. }
    target := G_Find(target, FOFS_targetname, self^.target);
    while (target <> Nil) do
    begin
      if (strcmp(target^.classname, 'point_combat') = 0) then
      begin
        self^.combattarget := self^.target;
        fixup := True;
      end
      else
        notcombat := True;

      target := G_Find(target, FOFS_targetname, self^.target);
    end;
    if notcombat AND (self^.combattarget <> nil) 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 <> nil) then
  begin
    target := Nil;
    { NOTE(SP):  Removed the TRY..FINALLY block that ensured the next call to
                 G_Find occured, due to possible performance issues with
                 try blocks. }
    target := G_Find(target, FOFS_targetname , self^.combattarget);
    while (target <> Nil) do
    begin
      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, Trunc(self^.s.origin[0]), Trunc(self^.s.origin[1]), Trunc(self^.s.origin[2]),
          self^.combattarget, target^.classname, Trunc(target^.s.origin[0]), Trunc(target^.s.origin[1]),
          Trunc(target^.s.origin[2]));
      end;

      target := G_Find(target, FOFS_targetname , self^.combattarget);
    end;
  end;

  if (self^.target <> nil) then
  begin
    self^.movetarget := G_PickTarget(self^.target);
    self^.goalentity := self^.movetarget;
    if (self^.movetarget = nil) 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: edict_p);
begin
  if ((self^.spawnflags AND 2) = 0) AND (level.time < 1) then
  begin
    M_droptofloor(self);

    if (self^.groundentity <> nil) then
      if not (M_walkmove(self, 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: edict_p);
begin
  self^.think := walkmonster_start_go;
  monster_start(self);
end;

procedure flymonster_start_go(self: edict_p);
begin
  if not(M_walkmove(self, 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: edict_p);
begin
  self^.flags := self^.flags OR FL_FLY;
  self^.think := flymonster_start_go;
  monster_start(self);
end;

procedure swimmonster_start_go(self: edict_p);
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: edict_p);
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 + -