📄 p_client.pas
字号:
playerdistance := VectorLength (v);
if (playerdistance < bestplayerdistance) then
bestplayerdistance := playerdistance;
end;
Result := bestplayerdistance;
end;//procedure (GAME=CTF)
{*
================
SelectRandomDeathmatchSpawnPoint
go to a random point, but NOT the two points closest
to other players
================
*}
// (GAME=CTF)
function SelectRandomDeathmatchSpawnPoint : edict_t;
var
edict_t *spot, *spot1, *spot2;
int count = 0;
selection : integer;
range, range1, range2 : float;
begin
spot = NULL;
// range1 = range2 = 99999;
range2 := 99999;
range1 := range2;
spot1 = spot2 = NULL;
// while ((spot = G_Find (spot, FOFS(classname), 'info_player_deathmatch')) != NULL)
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;
end;
if (!count) then
begin
Result := Nil;
Exit;
end;
if (count <= 2)
then begin
spot1 = spot2 = NULL;
end
else
Dec (count, 2);
// selection = rand() % count;
selection := random(count);
spot = NULL;
(* do
{
spot = G_Find (spot, FOFS(classname), 'info_player_deathmatch');
if (spot = spot1) OR (spot = spot2) then
selection++;
} while(selection--);
*)
repeat
spot := G_Find (spot, FOFS(classname), 'info_player_deathmatch');
if (spot = spot1) OR (spot = spot2) then
Inc(selection);
Dec(selection);
until selection=0; //C2Pas ???
Result := spot;
end;//procedure (GAME=CTF)
{*
================
SelectFarthestDeathmatchSpawnPoint
================
*}
// (GAME=CTF)
function SelectFarthestDeathmatchSpawnPoint : edict_t;
var
edict_t *bestspot;
bestdistance,
bestplayerdistance : float;
edict_t *spot;
begin
spot = NULL;
bestspot = NULL;
bestdistance := 0;
// while ((spot = G_Find (spot, FOFS(classname), 'info_player_deathmatch')) != NULL)
spot := G_Find (spot, FOFS(classname), 'info_player_deathmatch'));
while (spot <> NULL) do
begin
bestplayerdistance := PlayersRangeFromSpot (spot);
if (bestplayerdistance > bestdistance) then
begin
bestspot := spot;
bestdistance := bestplayerdistance;
end;
end;
if (bestspot) 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 (NULL, FOFS(classname), 'info_player_deathmatch');
Result := spot;
end;//procedure (GAME=CTF)
// (GAME=CTF)
function SelectDeathmatchSpawnPoint : edict_t;
begin
if ( (int)(dmflags->value) & DF_SPAWN_FARTHEST)
then Result := SelectFarthestDeathmatchSpawnPoint ()
else Result := SelectRandomDeathmatchSpawnPoint ();
end;//procedure (GAME=CTF)
// (GAME=CTF)
function SelectCoopSpawnPoint (edict_t *ent) : edict_t;
var
index : integer;
edict_t *spot = NULL;
char *target;
begin
index := ent.client - game.clients;
// player 0 starts in normal player spawn point
if (!index) then
begin
Result := NULL;
Exit;
end;
spot = NULL;
// assume there are four coop spots at each spawnpoint
while (1)
begin
spot := G_Find (spot, FOFS(classname), 'info_player_coop');
if (!spot) then
begin
Result := NULL; // we didn't have enough...
Exit;
end;
target := spot.targetname;
if (!target) 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) then
begin
Result := spot; // this is it
Exit;
end;
end;
end;
Result := spot;
end;//procedure (GAME=CTF)
{*
===========
SelectSpawnPoint
Chooses a player start, deathmatch start, coop start, etc
============
*}
// (GAME <> CTF)
procedure SelectSpawnPoint (edict_t *ent, vec3_t origin, vec3_t angles);
begin
edict_t *spot = NULL;
if (deathmatch.value)
{$IFDEF CTF}
//ZOID
then
if (ctf.value)
then spot := SelectCTFSpawnPoint(ent)
else spot := SelectDeathmatchSpawnPoint ();
//ZOID
{$ELSE}
then spot := SelectDeathmatchSpawnPoint ()
{$ENDIF}
else
if (coop.value) then
spot := SelectCoopSpawnPoint (ent);
// find a single player start spot
if (!spot) then
begin
// while ((spot = G_Find (spot, FOFS(classname), 'info_player_start')) != NULL)
spot := G_Find (spot, FOFS(classname), 'info_player_start');
while (spot <> Nil) do
begin
if (!game.spawnpoint[0]) AND (!spot.targetname) then
Break;
if (!game.spawnpoint[0]) OR (!spot.targetname) then
Continue;
if (Q_stricmp(game.spawnpoint, spot.targetname) = 0) then
Break;
end;
if (!spot) then
begin
if (!game.spawnpoint[0]) then
// there wasn't a spawnpoint without a target, so use any
spot := G_Find (spot, FOFS(classname), 'info_player_start');
if (!spot) then
gi.error ('Couldn"t find spawn point %s\n', game.spawnpoint);
end;
end;
VectorCopy (spot.s.origin, origin);
origin[2] := origin[2] +9;
VectorCopy (spot.s.angles, angles);
end;//procedure (GAME <> CTF)
//======================================================================
// (GAME=CTF)
procedure InitBodyQue;
var
i : integer;
edict_t *ent;
begin
level.body_que = 0;
for i:=0 to BODY_QUEUE_SIZE-1 do
begin
ent := G_Spawn();
ent.classname := 'bodyque';
end;
end;//procedure (GAME=CTF)
// (GAME=CTF)
procedure body_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
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 (GAME=CTF)
// (GAME=CTF)
procedure CopyToBodyQue (edict_t *ent);
var
edict_t *body;
begin
// grab a body que and cycle to the next one
body = &g_edicts[(int)maxclients->value + level.body_que + 1];
level.body_que := (level.body_que + 1) MOD BODY_QUEUE_SIZE;
// FIXME: send an effect on the removed body
gi.unlinkentity (ent);
gi.unlinkentity (body);
body.s := ent.s;
body.s.number := body - g_edicts;
body.svflags := ent.svflags;
VectorCopy (ent.mins, body.mins);
VectorCopy (ent.maxs, body.maxs);
VectorCopy (ent.absmin, body.absmin);
VectorCopy (ent.absmax, body.absmax);
VectorCopy (ent.size, body.size);
body.solid := ent.solid;
body.clipmask := ent.clipmask;
body.owner := ent.owner;
body.movetype := ent.movetype;
body.die := body_die;
body.takedamage := DAMAGE_YES;
gi.linkentity (body);
end;//procedure (GAME=CTF)
// (GAME <> CTF)
procedure respawn (edict_t *self);
begin
if (deathmatch.value OR coop.value) then
begin
{$IFDEF CTF}
//Y: none comments
{$ELSE}
// spectator's don't leave bodies
{$ENDIF}
if (self.movetype <> MOVETYPE_NOCLIP) then
CopyToBodyQue (self);
self.svflags := self.svflags AND (NOT SVF_NOCLIENT);
PutClientInServer (self);
// add a teleportation effect
self.s.event := EV_PLAYER_TELEPORT;
// hold in place briefly
self.client.ps.pmove.pm_flags := PMF_TIME_TELEPORT;
self.client.ps.pmove.pm_time := 14;
self.client.respawn_time := level.time;
Exit;
end;
// restart the entire server
gi.AddCommandString ('menu_loadgame\n');
end;//procedure (GAME <> CTF)
{$IFNDEF CTF} //onlyGAME (noneCTF)
{*
* only called when pers.spectator changes
* note that resp.spectator should be the opposite of pers.spectator here
*}
// (GAME <> CTF)
procedure spectator_respawn (edict_t *ent);
var
i, numspec : integer;
begin
// if the user wants to become a spectator, make sure he doesn't
// exceed max_spectators
if (ent.client.pers.spectator)
then begin
char *value := Info_ValueForKey (ent.client.pers.userinfo, 'spectator');
if ( *spectator_password.string AND
strcmp(spectator_password.string, 'none') AND
strcmp(spectator_password.string, value) ) then
begin
gi.cprintf(ent, PRINT_HIGH, 'Spectator password incorrect.\n');
ent.client.pers.spectator := false;
gi.WriteByte (svc_stufftext);
gi.WriteString ('spectator 0\n');
gi.unicast(ent, true);
Exit;
end;
// count spectators
// for (i = 1, numspec = 0; i <= maxclients->value; i++)
numspec := 0;
for i:=1 to maxclients.value do
if (g_edicts[i].inuse) AND (g_edicts[i].client.pers.spectator) then
Inc(numspec);
if (numspec >= maxspectators.value) then
begin
gi.cprintf(ent, PRINT_HIGH, 'Server spectator limit is full.');
ent.client.pers.spectator := false;
// reset his spectator var
gi.WriteByte (svc_stufftext);
gi.WriteString ('spectator 0\n');
gi.unicast(ent, true);
Exit;
end;
end
else begin
// he was a spectator and wants to join the game
// he must have the right password
char *value := Info_ValueForKey (ent->client->pers.userinfo, "password");
if ( *password.string AND
strcmp(password.string, 'none') AND
strcmp(password.string, value) ) then
begin
gi.cprintf(ent, PRINT_HIGH, 'Password incorrect.\n');
ent.client.pers.spectator := true;
gi.WriteByte (svc_stufftext);
gi.WriteString ('spectator 1\n');
gi.unicast(ent, true);
Exit;
end;
end;
// clear score on respawn
// ent->client->pers.score = ent->client->resp.score = 0;
ent.client.resp.score := 0;
ent.client.pers.score := ent.client.resp.score;
ent.svflags := ent.svflags AND (NOT SVF_NOCLIENT);
PutClientInServer (ent);
// add a teleportation effect
if (!ent.client.pers.spectator) then
begin
// send effect
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_LOGIN);
gi.multicast (ent.s.origin, MULTICAST_PVS);
// hold in place briefly
ent.client.ps.pmove.pm_flags := PMF_TIME_TELEPORT;
ent.client.ps.pmove.pm_time := 14;
end;
ent.client.respawn_time := level.time;
if (ent.client.pers.spectator)
then gi.bprintf (PRINT_HIGH, '%s has moved to the sidelines\n', ent.client.pers.netname)
else gi.bprintf (PRINT_HIGH, '%s joined the game\n', ent.client.pers.netname);
end;//procedure (GAME <> CTF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -