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

📄 p_client.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 4 页
字号:
    self^.client^.killer_yaw := self^.s.angles[YAW];
    Exit;
  end;

  if (dir[0] <> 0) then
    self^.client^.killer_yaw := 180/M_PI  * arctan2(dir[1], dir[0])
  else
  begin
    self^.client^.killer_yaw := 0;
    if (dir[1] > 0) then
      self^.client^.killer_yaw := 90
    else if (dir[1] < 0) then
      self^.client^.killer_yaw := -90;
  end;
  if (self^.client^.killer_yaw < 0) then
    self^.client^.killer_yaw := self^.client^.killer_yaw + 360;
end;


{*
==================
player_die
==================
*}
var
  i : integer = 0;

procedure player_die (self, inflictor, attacker : edict_p; damage : integer; const point : vec3_t); //a few files
var
  n : integer;
begin
  VectorClear (self^.avelocity);

  self^.takedamage := DAMAGE_YES;
  self^.movetype := MOVETYPE_TOSS;

  self^.s.modelindex2 := 0;	// remove linked weapon model

  self^.s.angles[0] := 0;
  self^.s.angles[2] := 0;

  self^.s.sound := 0;
  self^.client^.weapon_sound := 0;

  self^.maxs[2] := -8;

//idsoft	self->solid = SOLID_NOT;
  self^.svflags := self^.svflags OR SVF_DEADMONSTER;

  if (self^.deadflag = 0) then
  begin
    self^.client^.respawn_time := level.time + 1.0;
    LookAtKiller (self, inflictor, attacker);
    self^.client^.ps.pmove.pm_type := PM_DEAD;
    ClientObituary (self, inflictor, attacker);

    TossClientWeapon (self);

    if (deathmatch^.value <> 0) then
      Cmd_Help_f (self);		// show scores

    // clear inventory
    // this is kind of ugly, but it's how we want to handle keys in coop
    for n := 0 to game.num_items-1 do
    begin
      if (coop^.value <> 0) AND ((itemlist[n].flags AND IT_KEY) <> 0) then
        self^.client^.resp.coop_respawn.inventory[n] := self^.client^.pers.inventory[n];
      self^.client^.pers.inventory[n] := 0;
    end;
  end;

  // remove powerups
  self^.client^.quad_framenum := 0;
  self^.client^.invincible_framenum := 0;
  self^.client^.breather_framenum := 0;
  self^.client^.enviro_framenum := 0;
  self^.flags := self^.flags AND (NOT FL_POWER_ARMOR);

  if (self^.health < -40) then
  begin
    // gib
    gi.sound (self, CHAN_BODY, gi.soundindex ('misc/udeath.wav'), 1, ATTN_NORM, 0);
    for n := 0 to 3 do
      ThrowGib (self, 'models/objects/gibs/sm_meat/tris.md2', damage, GIB_ORGANIC);
    ThrowClientHead (self, damage);

    self^.takedamage := DAMAGE_NO;
  end
  else
  begin  // normal death
    if (self^.deadflag = 0) then
    begin
      i := (i+1) MOD 3;
      // start a death animation
      self^.client^.anim_priority := ANIM_DEATH;
      if (self^.client^.ps.pmove.pm_flags AND PMF_DUCKED) <> 0 then
      begin
        self^.s.frame := FRAME_crdeath1-1;
        self^.client^.anim_end := FRAME_crdeath5;
      end
      else
      begin
        Case i of
          0: begin
               self^.s.frame := FRAME_death101-1;
               self^.client^.anim_end := FRAME_death106;
             end;
          1: begin
               self^.s.frame := FRAME_death201-1;
               self^.client^.anim_end := FRAME_death206;
             end;
          2: begin
               self^.s.frame := FRAME_death301-1;
               self^.client^.anim_end := FRAME_death308;
             end;
        end;
      end;
      gi.sound (self, CHAN_VOICE,
                gi.soundindex(va('*death%i.wav', [(rand() mod 4)+1])),
                1, ATTN_NORM, 0);
    end;
  end;

  self^.deadflag := DEAD_DEAD;

  gi.linkentity (self);
end;


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

{*
==============
InitClientPersistant

This is only called when the game first initializes in single player,
but is called after each death and level change in deathmatch
==============
*}
procedure InitClientPersistant (client : gclient_p);
var
  item : gitem_p;
begin
  FillChar(client^.pers, SizeOf(client^.pers), 0);

  item := FindItem('Blaster');
  client^.pers.selected_item := ITEM_INDEX(item);
  client^.pers.inventory[client^.pers.selected_item] := 1;

  client^.pers.weapon := item;

  client^.pers.health	   := 100;
  client^.pers.max_health   := 100;

  client^.pers.max_bullets  := 200;
  client^.pers.max_shells   := 100;
  client^.pers.max_rockets  := 50;
  client^.pers.max_grenades := 50;
  client^.pers.max_cells    := 200;
  client^.pers.max_slugs    := 50;

  client^.pers.connected := true;
end;

procedure InitClientResp (client : gclient_p);
begin
  FillChar(client^.resp, SizeOf(client^.resp), 0);

  client^.resp.enterframe := level.framenum;
  client^.resp.coop_respawn := client^.pers;
end;


{*
==================
SaveClientData

Some information that should be persistant, like health,
is still stored in the edict structure, so it needs to
be mirrored out to the client structure before all the
edicts are wiped.
==================
*}
procedure SaveClientData; //a few files
var
  i : integer;
  ent :	edict_p;
begin
  for i := 0 to game.maxclients-1 do
  begin
    ent := @g_edicts^[1+i];
    if (NOT ent^.inuse) then
      Continue;
    gclient_a(game.clients)[i].pers.health := ent^.health;
    gclient_a(game.clients)[i].pers.max_health := ent^.max_health;

    gclient_a(game.clients)[i].pers.savedFlags := (ent^.flags AND (FL_GODMODE OR FL_NOTARGET OR FL_POWER_ARMOR));

    if (coop^.Value <> 0) then
      gclient_a(game.clients)[i].pers.score := ent^.client^.resp.score;
  end;
end;

procedure FetchClientEntData (ent : edict_p);
begin
  ent^.health := ent^.client^.pers.health;
  ent^.max_health := ent^.client^.pers.max_health;

  ent^.flags := ent^.flags OR ent^.client^.pers.savedFlags;

  if (coop^.value <> 0) then
    ent^.client^.resp.score := ent^.client^.pers.score;
end;


{*
=======================================================================

  SelectSpawnPoint

=======================================================================
*}

{*
================
PlayersRangeFromSpot

Returns the distance to the nearest player from the given spot
================
*}
function PlayersRangeFromSpot (spot : edict_p) : Single;
var
  player              : edict_p;
  bestplayerdistance,
  playerdistance      : Single;
  v                   : vec3_t;
  n                   : integer;
begin
  bestplayerdistance := 9999999;

  for n := 1 to trunc(maxclients^.Value) do
  begin
    player := @g_edicts^[n];

    if (NOT player^.inuse) then
      Continue;

    if (player^.health <= 0) then
      Continue;

    VectorSubtract (spot^.s.origin, player^.s.origin, v);
    playerdistance := VectorLength (v);

    if (playerdistance < bestplayerdistance) then
      bestplayerdistance := playerdistance;
  end;

  Result := bestplayerdistance;
end;

{*
================
SelectRandomDeathmatchSpawnPoint

go to a random point, but NOT the two points closest
to other players
================
*}
function SelectionTest(var iSelection: Integer): Boolean;
begin
  Result := (iSelection = 0);
  Dec(iSelection);
end;

function SelectRandomDeathmatchSpawnPoint : edict_p;
var
  spot, spot1, spot2 : edict_p;
  selection : integer;
  range, range1, range2 : Single;
  count : integer;
begin
  count := 0;

  spot := Nil;
  range2 := 99999;
  range1 := range2;
  spot2 := Nil;
  spot1 := spot2;

  spot := G_Find (spot, FOFS_classname, 'info_player_deathmatch');
  while (spot <> Nil) do
  begin
    Inc(count);
    range := PlayersRangeFromSpot(spot);
    if (range < range1)
    then
    begin
      range1 := range;
      spot1 := spot;
    end
    else if (range < range2) then
    begin
      range2 := range;
      spot2 := spot;
    end;
    spot := G_Find (spot, FOFS_classname, 'info_player_deathmatch')
  end;

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

  if (count <= 2) then
  begin
    spot2 := Nil;
    spot1 := spot2;
  end
  else
    Dec (count, 2);

  selection := rand() mod count;

  spot := Nil;

  { NOTE:  Changed this section to react to exactly the C code, which actually
           would decrement the selection After the evaluation of the code, which
           meant that the Dec(selection) before hand was incorrect }
  repeat
    spot := G_Find (spot, FOFS_classname, 'info_player_deathmatch');
    if (spot = spot1) OR (spot = spot2) then
      Inc(selection);
  until SelectionTest(selection);

  Result := spot;
end;


{*
================
SelectFarthestDeathmatchSpawnPoint

================
*}
function SelectFarthestDeathmatchSpawnPoint : edict_p;
var
  bestspot,  spot    : edict_p;
  bestdistance,
  bestplayerdistance : single;
begin
  spot := Nil;
  bestspot := Nil;
  bestdistance := 0;
  spot := G_Find (spot, FOFS_classname, 'info_player_deathmatch');
  while (spot <> Nil) do
  begin
    bestplayerdistance := PlayersRangeFromSpot (spot);

    if (bestplayerdistance > bestdistance) then
    begin
      bestspot := spot;
      bestdistance := bestplayerdistance;
    end;
    spot := G_Find (spot, FOFS_classname, 'info_player_deathmatch');
  end;

  if (bestspot <> Nil) then
  begin
    Result := bestspot;
    Exit;
  end;

  // if there is a player just spawned on each and every start spot
  // we have no choice to turn one into a telefrag meltdown
  spot := G_Find (nil, FOFS_classname, 'info_player_deathmatch');

  Result := spot;
end;

function SelectDeathmatchSpawnPoint : edict_p;
begin
  if (Trunc(dmflags^.value) AND DF_SPAWN_FARTHEST) <> 0 then
    Result := SelectFarthestDeathmatchSpawnPoint ()
  else
    Result := SelectRandomDeathmatchSpawnPoint ();
end;


function SelectCoopSpawnPoint (ent : edict_p) : edict_p;
var
  index  : integer;
  target : PChar;
  spot   : edict_p;
begin
//  spot := nil;

  index := (Cardinal(ent^.client) - Cardinal(game.clients)) div SizeOf(edict_t);

  // player 0 starts in normal player spawn point
  if (index = 0) then
  begin
    Result := Nil;
    Exit;
  end;

  spot := nil;

  // assume there are four coop spots at each spawnpoint
  while True do
  begin
    spot := G_Find (spot, FOFS_classname, 'info_player_coop');
    if (spot = Nil) then
    begin
      Result := Nil;  // we didn't have enough...
      Exit;
    end;

    target := spot^.targetname;
    if (target = nil) then
      target := '';
    if (Q_stricmp(game.spawnpoint, target) = 0) then
    begin
      // this is a coop spawn point for one of the clients here
      Dec(index);
      if (index = 0) then
      begin
        Result := spot;	 // this is it
        Exit;
      end;
    end;
  end;

  Result := spot;
end;


{*
===========
SelectSpawnPoint

Chooses a player start, deathmatch start, coop start, etc
============
*}
procedure SelectSpawnPoint (ent : edict_p; var origin, angles : vec3_t);
var
  spot : edict_p;
label
  continue_;
begin
  spot := Nil;

  if (deathmatch^.value <> 0) then
    spot := SelectDeathmatchSpawnPoint ()
  else if (coop^.value <> 0) then
    spot := SelectCoopSpawnPoint (ent);

  // find a single player start spot
  if (spot = Nil) then
  begin
      spot := G_Find (spot, FOFS_classname, 'info_player_start');
      while (spot <> Nil) do
      begin
        if (game.spawnpoint[0] = #0) AND (spot^.targetname = nil) then
          Break;

        if (game.spawnpoint[0] = #0) OR (spot^.targetname = nil) then
          goto continue_;

        if (Q_stricmp(game.spawnpoint, spot^.targetname) = 0) then
          Break;

      continue_:
        spot := G_Find (spot, FOFS_classname, 'info_player_start');
      end;

      if (spot = Nil) then
      begin
        if (game.spawnpoint[0] = #0) then
          // there wasn't a spawnpoint without a target, so use any
          spot := G_Find (spot, FOFS_classname, 'info_player_start');
        if (spot = Nil) then
          gi.error ('Couldn''t find spawn point %s'#10, game.spawnpoint);
      end;
  end;

  VectorCopy (spot^.s.origin, origin);
  origin[2] := origin[2] + 9;
  VectorCopy (spot^.s.angles, angles);
end;


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


procedure InitBodyQue; //g_spawn
var
  i   : integer;
  ent : edict_p;
begin
  level.body_que := 0;
  for i := 0 to BODY_QUEUE_SIZE-1 do
  begin
    ent := G_Spawn();
    ent^.classname := 'bodyque';
  end;
end;

procedure body_die (self, inflictor, attacker : edict_p; damage : integer; const point : vec3_t); cdecl;
var
  n : integer;
begin
  if (self^.health < -40) then
  begin
    gi.sound (self, CHAN_BODY, gi.soundindex ('misc/udeath.wav'), 1, ATTN_NORM, 0);
    for n := 0 to 3 do
      ThrowGib (self, 'models/objects/gibs/sm_meat/tris.md2', damage, GIB_ORGANIC);
    self^.s.origin[2] := self^.s.origin[2] -48;
    ThrowClientHead (self, damage);
    self^.takedamage := DAMAGE_NO;
  end;
end;

procedure CopyToBodyQue (ent : edict_p);
var
  body : edict_p;

⌨️ 快捷键说明

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