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

📄 g_combat.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
    Result := 0;
    Exit;
  end;

  if (dflags AND DAMAGE_NO_ARMOR) <> 0 then
  begin
    Result := 0;
    Exit;
  end;

  index := ArmorIndex(ent);
  if (index = 0) then
  begin
    Result := 0;
    Exit;
  end;

  armor := GetItemByIndex(index);

  { NOTE:  2003-09-18-Scott Price:
           Commented out FAB's conversion, and corrected the original which was
           almost correct - I hope :) }
  if (dflags AND DAMAGE_ENERGY) <> 0 then
    save := ceil(gitem_armor_p(armor^.info)^.energy_protection * damage)
    { save := ceil((gitem_armor_p(armor)^.energy_protection * damage)) //check this by FAB .. }
  else
    save := ceil(gitem_armor_p(armor^.info)^.normal_protection * damage);
    { save := ceil((gitem_armor_p(armor)^.normal_protection * damage)); //check this by FAB .. }

  if (save >= client^.pers.inventory[index]) then
    save := client^.pers.inventory[index];

  if (save = 0) then
  begin
    Result := 0;
    Exit;
  end;

  client^.pers.inventory[index] := client^.pers.inventory[index] - save;
  SpawnDamage(te_sparks, point, normal, save);

  Result := save;
end;

procedure M_ReactToDamage(targ, attacker: edict_p);
begin
  if (attacker^.client = Nil) AND ((attacker^.svflags AND SVF_MONSTER) = 0) then
    Exit;

  if (attacker = targ) OR (attacker = targ^.enemy) then
    Exit;

  // if we are a good guy monster and our attacker is a player
  // or another good guy, do not get mad at them
  if (targ^.monsterinfo.aiflags AND AI_GOOD_GUY) <> 0 then
  begin
    if (attacker^.client <> Nil) OR ((attacker^.monsterinfo.aiflags AND AI_GOOD_GUY) <> 0) then
      Exit;
  end;

  // we now know that we are not both good guys

  // if attacker is a client, get mad at them because he's good and we're not
  if (attacker^.client <> Nil) then
  begin
    targ^.monsterinfo.aiflags := targ^.monsterinfo.aiflags AND (NOT AI_SOUND_TARGET);

    // this can only happen in coop (both new and old enemies are clients)
    // only switch if can't see the current enemy
    if (targ^.enemy <> Nil) AND (targ^.enemy^.client <> Nil) then
    begin
      if (visible(targ, targ^.enemy)) then
      begin
        targ^.oldenemy := attacker;
        Exit;
      end;
      targ^.oldenemy := targ^.enemy;
    end;

    targ^.enemy := attacker;
    if ((targ^.monsterinfo.aiflags AND AI_DUCKED) = 0) then
      FoundTarget(targ);

    Exit;
  end;

  // it's the same base (walk/swim/fly) type and a different classname and it's not a tank
  // (they spray too much), get mad at them
  if (((targ^.flags AND (FL_FLY OR FL_SWIM)) = (attacker^.flags AND (FL_FLY OR FL_SWIM))) AND
           (strcmp(targ^.classname, attacker^.classname) <> 0) AND
           (strcmp(attacker^.classname, 'monster_tank') <> 0) AND
           (strcmp(attacker^.classname, 'monster_supertank') <> 0) AND
           (strcmp(attacker^.classname, 'monster_makron') <> 0) AND
           (strcmp(attacker^.classname, 'monster_jorg') <> 0) ) then
  begin
    if (targ^.enemy <> Nil) AND (targ^.enemy^.client <> Nil) then
      targ^.oldenemy := targ^.enemy;

    targ^.enemy := attacker;

    if ((targ^.monsterinfo.aiflags AND AI_DUCKED) = 0) then
      FoundTarget(targ);
  end
  // if they *meant* to shoot us, then shoot back
  else if (attacker^.enemy = targ) then
  begin
    if (targ^.enemy <> Nil) AND (targ^.enemy^.client <> Nil) then
      targ^.oldenemy := targ^.enemy;

    targ^.enemy := attacker;

    if ((targ^.monsterinfo.aiflags AND AI_DUCKED) = 0) then
      FoundTarget(targ);
  end
  // otherwise get mad at whoever they are mad at (help our buddy) unless it is us!
  else if (attacker^.enemy <> Nil) AND (attacker^.enemy <> targ) then
  begin
    if (targ^.enemy <> Nil) AND (targ^.enemy^.client <> Nil) then
      targ^.oldenemy := targ^.enemy;

    targ^.enemy := attacker^.enemy;
    if ((targ^.monsterinfo.aiflags AND AI_DUCKED) = 0) then
      FoundTarget(targ);
  end;
end;

function CheckTeamDamage(targ, attacker: edict_p): qboolean;
begin
   // these 2 lines originally commented
  //FIXME make the next line real and uncomment this block
  // if ((ability to damage a teammate == OFF) && (targ's team == attacker's team))
  Result := False;
end;

procedure T_Damage(targ, inflictor, attacker: edict_p; var dir, point, normal: vec3_t; damage, knockback, dflags, mofd: Integer);
var
  client: gclient_p;
  take, save, asave, psave, te_sparks_: Integer;
  kvel: vec3_t;
  mass: Single;
begin
  if (targ^.takedamage = DAMAGE_NO) then    // check this .. by FAB
    Exit;

  // friendly fire avoidance
  // if enabled you can't hurt teammates (but you can hurt yourself)
  // knockback still occurs
  //
  //if ((targ != attacker) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value))

  { NOTE:  2003-09-18:  Scott Price
           I think the original works something like the following:

   (<first expression> AND (<second expression> AND <third expression>) OR <fourth expression>) }
  if ((targ <> attacker) and (((deathmatch^.value <> 0) and ((trunc(dmflags^.value) AND (DF_MODELTEAMS OR DF_SKINTEAMS)) <> 0))) or (coop^.value <> 0)) then
  begin
    if (OnSameTeam(targ, attacker)) then
    begin
      if (trunc(dmflags^.value) AND DF_NO_FRIENDLY_FIRE) <> 0 then
        damage := 0
      else
        mofd := mofd OR MOD_FRIENDLY_FIRE;
    end;
  end;
  meansOfDeath := mofd;

  // easy mode takes half damage
  if (skill^.value = 0) AND (deathmatch^.value = 0) AND (targ^.client <> Nil) then
  begin
    //damage := damage * 0.5;
    damage := damage div 2; // Check this ...by FAB   // SP:  Should be ok
    if (damage = 0) then
      damage := 1;
  end;

  client := targ^.client;

  if (dflags AND DAMAGE_BULLET) <> 0 then
    te_sparks_ := Ord(TE_BULLET_SPARKS) // Check this typecast ...by FAB
  else
    te_sparks_ := Ord(TE_SPARKS);       // Check this typecast ...by FAB

  VectorNormalize(dir);

// bonus damage for suprising a monster
  if ((dflags AND DAMAGE_RADIUS) = 0) AND ((targ^.svflags AND SVF_MONSTER) <> 0) AND (attacker^.client <> Nil) AND (targ^.enemy = Nil) AND (targ^.health > 0) then
    damage := damage * 2;

  if (targ^.flags AND FL_NO_KNOCKBACK) <> 0 then
    knockback := 0;

// figure momentum add
  if ((dflags AND DAMAGE_NO_KNOCKBACK) = 0) then
  begin
    //if ((knockback) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP))
    if (knockback <> 0) AND (targ^.movetype <> MOVETYPE_NONE) AND (targ^.movetype <> MOVETYPE_BOUNCE) AND (targ^.movetype <> MOVETYPE_PUSH) AND (targ^.movetype <> MOVETYPE_STOP) then
    begin
      if (targ^.mass < 50) then
        mass := 50
      else
        mass := targ^.mass;

      if (targ^.client <> Nil) AND (attacker = targ) then
        VectorScale(dir, 1600.0 * knockback / mass, kvel)	// the rocket jump hack...
      else
        VectorScale(dir, 500.0 * knockback / mass, kvel);

      VectorAdd(targ^.velocity, kvel, targ^.velocity);
    end;
  end;

  take := damage;
  save := 0;

  // check for godmode
  if ((targ^.flags AND FL_GODMODE) <> 0) AND ((dflags AND DAMAGE_NO_PROTECTION) = 0) then
  begin
    take := 0;
    save := damage;
    SpawnDamage(te_sparks_, point, normal, save);
  end;

  // check for invincibility
  if ((client <> Nil) AND (client^.invincible_framenum > level.framenum))  AND ((dflags AND DAMAGE_NO_PROTECTION) = 0) then
  begin
    if (targ^.pain_debounce_time < level.time) then
    begin
      gi.sound(targ, CHAN_ITEM, gi.soundindex('items/protect4.wav'), 1, ATTN_NORM, 0);
      targ^.pain_debounce_time := level.time + 2;
    end;
    take := 0;
    save := damage;
  end;

  psave := CheckPowerArmor(targ, point, normal, take, dflags);
  take := take - psave;

  asave := CheckArmor(targ, point, normal, take, te_sparks_, dflags);
  take := take - asave;

  //treat cheat/powerup savings the same as armor
  asave := asave + save;

  // team damage avoidance
  if ((dflags AND DAMAGE_NO_PROTECTION) = 0) AND CheckTeamDamage(targ, attacker) then
    Exit;

// do the damage
  if (take <> 0) then
  begin
    if ((targ^.svflags AND SVF_MONSTER) <> 0) OR (client <> Nil) then
      SpawnDamage(Ord(TE_BLOOD), point, normal, take)
    else
      SpawnDamage(te_sparks_, point, normal, take);

    targ^.health := targ^.health - take;

    if (targ^.health <= 0) then
    begin
      if ((targ^.svflags AND SVF_MONSTER) <> 0) OR (client <> Nil) then
        targ^.flags := targ^.flags OR FL_NO_KNOCKBACK;
      Killed(targ, inflictor, attacker, take, point);
      Exit;
    end;
  end;

  if (targ^.svflags AND SVF_MONSTER) <> 0 then
  begin
    M_ReactToDamage(targ, attacker);
    if ((targ^.monsterinfo.aiflags AND AI_DUCKED) = 0) AND (take <> 0) then
    begin
      targ^.pain(targ, attacker, knockback, take);
      // nightmare mode monsters don't go into pain frames often
      if (skill^.value = 3) then
        targ^.pain_debounce_time := level.time + 5;
    end;
  end
  else if (client <> Nil) then
  begin
    if ((targ^.flags AND FL_GODMODE) = 0) AND (take <> 0) then
      targ^.pain(targ, attacker, knockback, take);
  end
  else if (take <> 0) then
  begin
    if (@targ^.pain <> Nil) then
      targ^.pain(targ, attacker, knockback, take);
  end;

  // add to the damage inflicted on a player this frame
  // the total will be turned into screen blends and view angle kicks
  // at the end of the frame
  if (client <> Nil) then
  begin
    client^.damage_parmor := client^.damage_parmor + psave;
    client^.damage_armor := client^.damage_armor + asave;
    client^.damage_blood := client^.damage_blood + take;
    client^.damage_knockback := client^.damage_knockback + knockback;
    VectorCopy(point, client^.damage_from);
  end;
end;

{  |  |                                        |  |   }
{  V  V   ToDo:  Scott to continue from Here   V  V   }


(* ============
T_RadiusDamage
============ *)
procedure T_RadiusDamage(inflictor, attacker: edict_p; damage: Single; ignore: edict_p; radius: Single; mofd: Integer);
var
  points: Single;
  ent: edict_p;
  v, dir: vec3_t;
label
  __Continue;
begin
  ent := Nil;

  { NOTE:  Original Code here used a WHILE loop to perform this operation, but
           made an assignment in the Logical Test, so I have altered to be a
           initally called, and then a TRY..FINALLY block to perform the
           operation again prior to the end of the Loop and ReTest - Scott Price }
  ent := findradius(ent, inflictor^.s.origin, radius);
  while (ent <> Nil) do
  begin
    if (ent = ignore) then
      goto __Continue;
    if (ent^.takedamage = DAMAGE_NO) then    // check this ...by FAB
      goto __Continue;

    VectorAdd(ent^.mins, ent^.maxs, v);
    VectorMA(ent^.s.origin, 0.5, v, v);
    VectorSubtract(inflictor^.s.origin, v, v);
    points := damage - 0.5 * VectorLength(v);

    if (ent = attacker) then
      points := points * 0.5;
    if (points > 0) then
    begin
      if CanDamage(ent, inflictor) then
      begin
        VectorSubtract(ent^.s.origin, inflictor^.s.origin, dir);
        T_Damage(ent, inflictor, attacker, dir, inflictor^.s.origin, vec3_origin, Trunc(points), Trunc(points), DAMAGE_RADIUS, mofd);
      end;
    end;

  __Continue:
    { NOTE:  ADDED THIS LINE TO COMPENSATE }
    ent := findradius(ent, inflictor^.s.origin, radius);
  end;
end;

end.

⌨️ 快捷键说明

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