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

📄 g_combat.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
//100%
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): g_combat.c                                                        }
{ Content:                                                                   }
{                                                                            }
{ Initial conversion by : ???                                                }
{ Initial conversion on : ???                                                }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ This program is free software; you can redistribute it and/or              }
{ modify it under the terms of the GNU General Public License                }
{ as published by the Free Software Foundation; either version 2             }
{ of the License, or (at your option) any later version.                     }
{                                                                            }
{ This program is distributed in the hope that it will be useful,            }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of             }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       }
{                                                                            }
{ See the GNU General Public License for more details.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Updated on :  2003-Sept-18                                                 }
{ Updated by :  Scott Price (scott.price@totalise.co.uk)                     }
{ Updated on :  2002-Sept-25                                                 }
{ Updated by :  FAB (Fabrizio Rossini)                                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Notes:                                                                     }
{ - Review this code and assure we have not missed some Assignments in IF    }
{   statements, and accidentally interpretted them as Comparasons            }
{----------------------------------------------------------------------------}

unit g_combat;


interface

uses
  q_shared,
  q_shared_add,
  g_local,
  g_local_add;

function CanDamage(targ, inflictor: edict_p): qboolean;
procedure Killed(targ, inflictor, attacker: edict_p; damage: Integer; const point: vec3_t);
procedure SpawnDamage(dmgtype: Integer; const origin, normal: vec3_t; damage: Integer);
procedure M_ReactToDamage(targ, attacker: edict_p);
function CheckTeamDamage(targ, attacker: edict_p): qboolean;
procedure T_Damage(targ, inflictor, attacker: edict_p; var dir, point, normal: vec3_t; damage, knockback, dflags, mofd: Integer);
procedure T_RadiusDamage(inflictor, attacker: edict_p; damage: Single; ignore: edict_p; radius: Single; mofd: Integer);



implementation

uses
  GameUnit,
  g_main,
  cpas,
  g_monster,
  g_items,
  g_ai,
  g_cmds,
  g_utils;   // added by FAB

(* ============
CanDamage

Returns true if the inflictor can directly damage the target.  Used for
explosions and melee attacks.
============ *)
function CanDamage(targ, inflictor: edict_p): qboolean;
var
  dest: vec3_t;
  trace: trace_t;
begin
{ Following line originally commented out }
// bmodels need special checking because their origin is 0,0,0
  if (targ^.movetype = MOVETYPE_PUSH) then
  begin
    VectorAdd(targ^.absmin, targ^.absmax, dest);
    VectorScale(dest, 0.5, dest);
    trace := gi.trace(@inflictor^.s.origin, @vec3_origin, @vec3_origin, @dest, inflictor, MASK_SOLID);

    if (trace.fraction = 1.0) then
    begin
      Result := True;
      Exit;
    end;

    if (trace.ent = targ) then
    begin
      Result := True;
      Exit;
    end;

    Result := False;
    Exit;
  end;

  trace := gi.trace (@inflictor^.s.origin, @vec3_origin, @vec3_origin, @targ^.s.origin, inflictor, MASK_SOLID);
  if (trace.fraction = 1.0) then
  begin
    Result := True;
    Exit;
  end;

  VectorCopy(targ^.s.origin, dest);
  dest[0] := dest[0] + 15.0;
  dest[1] := dest[1] + 15.0;
  trace := gi.trace(@inflictor^.s.origin, @vec3_origin, @vec3_origin, @dest, inflictor, MASK_SOLID);
  if (trace.fraction = 1.0) then
  begin
    Result := True;
    Exit;
  end;

  VectorCopy(targ^.s.origin, dest);
  dest[0] := dest[0] + 15.0;
  dest[1] := dest[1] - 15.0;
  trace := gi.trace(@inflictor^.s.origin, @vec3_origin, @vec3_origin, @dest, inflictor, MASK_SOLID);
  if (trace.fraction = 1.0) then
  begin
    Result := True;
    Exit;
  end;

  VectorCopy(targ^.s.origin, dest);
  dest[0] := dest[0] - 15.0;
  dest[1] := dest[1] + 15.0;
  trace := gi.trace(@inflictor^.s.origin, @vec3_origin, @vec3_origin, @dest, inflictor, MASK_SOLID);
  if (trace.fraction = 1.0) then
  begin
    Result := True;
    Exit;
  end;

  VectorCopy(targ^.s.origin, dest);
  dest[0] := dest[0] - 15.0;
  dest[1] := dest[1] - 15.0;
  trace := gi.trace(@inflictor^.s.origin, @vec3_origin, @vec3_origin, @dest, inflictor, MASK_SOLID);
  if (trace.fraction = 1.0) then
  begin
    Result := True;
    Exit;
  end;

  Result := False;
end;

(* ============
Killed
============ *)
procedure Killed(targ, inflictor, attacker: edict_p; damage: Integer; const point: vec3_t);
begin
  if (targ^.health < -999) then
    targ^.health := -999;

  targ^.enemy := attacker;

  if (((targ^.svflags AND SVF_MONSTER) <> 0) AND (targ^.deadflag <> DEAD_DEAD)) then
  begin
{ Following line originally commented out }
//		targ->svflags |= SVF_DEADMONSTER;	// now treat as a different content type
    if ((targ^.monsterinfo.aiflags AND AI_GOOD_GUY) = 0) then
    begin
      Inc(level.killed_monsters);
      if (coop^.value <> 0) AND (attacker^.client <> nil) then
        Inc(attacker^.client^.resp.score);
      // medics won't heal monsters that they kill themselves
      if (strcmp(attacker^.classname, 'monster_medic') = 0) then
        targ^.owner := attacker;
    end;
  end;

  if ((targ^.movetype = MOVETYPE_PUSH) OR (targ^.movetype = MOVETYPE_STOP) OR (targ^.movetype = MOVETYPE_NONE)) then
  begin	// doors, triggers, etc
    targ^.die(targ, inflictor, attacker, damage, point);
    Exit;
  end;

  if (((targ^.svflags AND SVF_MONSTER) <> 0) AND (targ^.deadflag <> DEAD_DEAD)) then
  begin
    targ^.touch := Nil;
    monster_death_use(targ);
  end;

  targ^.die(targ, inflictor, attacker, damage, point);
end;


(* ================
SpawnDamage
================ *)
procedure SpawnDamage(dmgtype: Integer; const origin, normal: vec3_t; damage: Integer);
begin
  if (damage > 255) then
    damage := 255;
  gi.WriteByte(svc_temp_entity);
  gi.WriteByte(dmgtype);
{ Following line originally commented out }
//	gi.WriteByte (damage);
  gi.WritePosition(origin);
  gi.WriteDir(normal);
  gi.multicast(@origin, MULTICAST_PVS);
end;

{ This Routine is only visible in-side this unit }
(* ============
T_Damage

targ		entity that is being damaged
inflictor	entity that is causing the damage
attacker	entity that caused the inflictor to damage targ
	example: targ=monster, inflictor=rocket, attacker=player

dir			direction of the attack
point		point at which the damage is being inflicted
normal		normal vector from that point
damage		amount of damage being inflicted
knockback	force to be applied against targ as a result of the damage

dflags		these flags are used to control how T_Damage works
	DAMAGE_RADIUS			damage was indirect (from a nearby explosion)
	DAMAGE_NO_ARMOR			armor does not protect from this damage
	DAMAGE_ENERGY			damage is from an energy based weapon
	DAMAGE_NO_KNOCKBACK		do not affect velocity, just view angles
	DAMAGE_BULLET			damage is from a bullet (used for ricochets)
	DAMAGE_NO_PROTECTION	kills godmode, armor, everything
============ *)
function CheckPowerArmor(ent: edict_p; const point, normal: vec3_t; damage, dflags: Integer): Integer;
var
  client: gclient_p;
  save, power_armor_type, index, damagePerCell, pa_te_type, power, power_used: Integer;
  vec, forward_: vec3_t;
  dot: Single;
begin
  if (damage = 0) then
  begin
    Result := 0;
    Exit;
  end;

  client := ent^.client;

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

  if (client <> Nil) then
  begin
    power_armor_type := PowerArmorType(ent);
    if (power_armor_type <> POWER_ARMOR_NONE) then
    begin
      index := ITEM_INDEX(FindItem('Cells'));
      power := client^.pers.inventory[index];
    end
  end
  else if (ent^.svflags AND SVF_MONSTER) <> 0 then
  begin
    power_armor_type := ent^.monsterinfo.power_armor_type;
    power := ent^.monsterinfo.power_armor_power;
  end
  else
  begin
    Result := 0;
    Exit;
  end;

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

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

  if (power_armor_type = POWER_ARMOR_SCREEN) then
  begin
    // only works if damage point is in front
    AngleVectors(ent^.s.angles, @forward_, Nil, Nil);
    VectorSubtract(point, ent^.s.origin, vec);
    VectorNormalize(vec);
    dot := DotProduct(vec, forward_);
    if (dot <= 0.3) then
    begin
      Result := 0;
      Exit;
    end;

    damagePerCell := 1;
    pa_te_type := Ord(TE_SCREEN_SPARKS);  // Check this typecast ...by FAB
    damage := damage div 3;
  end
  else
  begin
    damagePerCell := 2;
    pa_te_type := Ord(TE_SHIELD_SPARKS);   // Check this typecast ...by FAB
    damage := (2 * damage) div 3;
  end;

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

  if (save > damage) then
    save := damage;

  SpawnDamage(pa_te_type, point, normal, save);
  ent^.powerarmor_time := level.time + 0.2;

  //power_used := save / damagePerCell;
  power_used := save mod damagePerCell;

  if (client <> Nil) then
    client^.pers.inventory[index] := client^.pers.inventory[index] - power_used
  else
    ent^.monsterinfo.power_armor_power := ent^.monsterinfo.power_armor_power - power_used;

  Result := save;
end;

{ This Routine is only visible in-side this unit }
function CheckArmor(ent: edict_p; const point, normal: vec3_t; damage, te_sparks, dflags: Integer): Integer;
var
  client: gclient_p;
  save, index: Integer;
  armor: gitem_p;
begin
  if (damage = 0) then
  begin
    Result := 0;
    Exit;
  end;

  client := ent^.client;

  if (client = Nil) then
  begin

⌨️ 快捷键说明

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