📄 p_client.pas
字号:
{$ENDIF}
//==============================================================
{*
===========
PutClientInServer
Called when a player connects to a server or respawns in
a deathmatch.
============
*}
// (GAME <> CTF)
procedure PutClientInServer (edict_t *ent);
const
mins : vec3_t = (-16, -16, -24);
maxs : vec3_t = ( 16, 16, 32);
var
{Y} index : integer;
spawn_origin,
spawn_angles : vec3_t;
gclient_t *client;
i, n : integer;
client_persistant_t saved;
client_respawn_t resp;
char userinfo[MAX_INFO_STRING];
begin
// find a spawn point
// do it before setting health back up, so farthest
// ranging doesn't count this client
SelectSpawnPoint (ent, spawn_origin, spawn_angles);
{Y} index := ent-g_edicts-1;
client := ent.client;
// deathmatch wipes most client data every spawn
if (deathmatch.value)
then begin
resp := client.resp;
memcpy (userinfo, client->pers.userinfo, sizeof(userinfo));
InitClientPersistant (client);
ClientUserinfoChanged (ent, userinfo);
end
else
if (coop.value)
then begin
resp := client.resp;
memcpy (userinfo, client->pers.userinfo, sizeof(userinfo));
{$IFDEF CTF}
for n:=0 to MAX_ITEMS-1 do
if (itemlist[n].flags & IT_KEY) then
resp.coop_respawn.inventory[n] := client.pers.inventory[n];
{$ELSE}
// this is kind of ugly, but it's how we want to handle keys in coop
(*idsoft
// for (n = 0; n < game.num_items; n++)
// {
// if (itemlist[n].flags & IT_KEY)
// resp.coop_respawn.inventory[n] = client->pers.inventory[n];
// }
*)
resp.coop_respawn.game_helpchanged := client.pers.game_helpchanged;
resp.coop_respawn.helpchanged := client.pers.helpchanged;
{$ENDIF}
client.pers := resp.coop_respawn;
ClientUserinfoChanged (ent, userinfo);
if (resp.score > client.pers.score) then
client.pers.score := resp.score;
end
else
memset (&resp, 0, sizeof(resp));
// clear everything but the persistant data
saved := client.pers;
memset (client, 0, sizeof( *client));
client.pers := saved;
if (client.pers.health <= 0) then
InitClientPersistant(client);
client.resp := resp;
// copy some data from the client to the entity
FetchClientEntData (ent);
// clear entity values
ent.groundentity = NULL;
ent.client = &game.clients[index];
ent.takedamage := DAMAGE_AIM;
ent.movetype := MOVETYPE_WALK;
ent.viewheight := 22;
ent.inuse := true;
ent.classname = 'player';
ent.mass := 200;
ent.solid := SOLID_BBOX;
ent.deadflag := DEAD_NO;
ent.air_finished := level.time + 12;
ent.clipmask := MASK_PLAYERSOLID;
ent.model := 'players/male/tris.md2';
ent.pain := player_pain;
ent.die := player_die;
ent.waterlevel := 0;
ent.watertype := 0;
ent.flags := ent.flags AND (NOT FL_NO_KNOCKBACK);
ent.svflags := ent.svflags AND (NOT SVF_DEADMONSTER);
VectorCopy (mins, ent.mins);
VectorCopy (maxs, ent.maxs);
VectorClear (ent.velocity);
// clear playerstate values
memset (&ent->client->ps, 0, sizeof(client->ps));
client.ps.pmove.origin[0] := spawn_origin[0]*8;
client.ps.pmove.origin[1] := spawn_origin[1]*8;
client.ps.pmove.origin[2] := spawn_origin[2]*8;
{$IFDEF CTF} //onlyCTF
//ZOID
client.ps.pmove.pm_flags := client.ps.pmove.pm_flags AND (NOT PMF_NO_PREDICTION);
//ZOID
{$ENDIF}
if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV))
then client.ps.fov := 90
else begin
client.ps.fov := atoi(Info_ValueForKey(client.pers.userinfo, 'fov'));
if (client.ps.fov < 1)
then client.ps.fov := 90
else
if (client.ps.fov > 160) then
client.ps.fov := 160;
end;
client.ps.gunindex := gi.modelindex(client.pers.weapon.view_model);
// clear entity state values
ent.s.effects := 0;
{$IFDEF CTF} //onlyCTF
ent.s.skinnum := ent - g_edicts - 1;
{$ENDIF}
ent.s.modelindex := 255; // will use the skin specified model
ent.s.modelindex2 := 255; // custom gun model
// sknum is player num and weapon number
// weapon number will be added in changeweapon
ent.s.skinnum := ent - g_edicts - 1;
ent.s.frame := 0;
VectorCopy (spawn_origin, ent.s.origin);
ent.s.origin[2] := ent.s.origin[2] +1; // make sure off ground
VectorCopy (ent.s.origin, ent.s.old_origin);
// set the delta angle
for i:=0 to 2 do
client.ps.pmove.delta_angles[i] := ANGLE2SHORT(spawn_angles[i] - client.resp.cmd_angles[i]);
ent.s.angles[PITCH] := 0;
ent.s.angles[YAW] := spawn_angles[YAW];
ent.s.angles[ROLL] := 0;
VectorCopy (ent.s.angles, client.ps.viewangles);
VectorCopy (ent.s.angles, client.v_angle);
{$IFDEF CTF}
//ZOID
if (CTFStartClient(ent)) then
Exit;
//ZOID
{$ELSE}
// spawn a spectator
if (client.pers.spectator)
then begin
client.chase_target := NULL;
client.resp.spectator := true;
ent.movetype := MOVETYPE_NOCLIP;
ent.solid := SOLID_NOT;
ent.svflags := ent.svflags OR SVF_NOCLIENT;
ent.client.ps.gunindex := 0;
gi.linkentity (ent);
Exit;
else
client.resp.spectator := false;
{$ENDIF}
if (!KillBox (ent))
{ // could't spawn in?
}
gi.linkentity (ent);
// force the current weapon up
client.newweapon := client.pers.weapon;
ChangeWeapon (ent);
end;//procedure (GAME <> CTF)
{*
=====================
ClientBeginDeathmatch
A client has just connected to the server in
deathmatch mode, so clear everything out before starting them.
=====================
*}
// (GAME=CTF)
procedure ClientBeginDeathmatch (edict_t *ent)
begin
G_InitEdict (ent);
InitClientResp (ent.client);
// locate ent at a spawn point
PutClientInServer (ent);
// send effect
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_LOGIN);
gi.multicast (ent.s.origin, MULTICAST_PVS);
gi.bprintf (PRINT_HIGH, '%s entered the game\n', ent.client.pers.netname);
// make sure all view stuff is valid
ClientEndServerFrame (ent);
end;//procedure (GAME=CTF)
{*
===========
ClientBegin
called when a client has finished connecting, and is ready
to be placed into the game. This will happen every level load.
============
*}
// (GAME=CTF)
procedure ClientBegin (edict_t *ent)
var
i : integer;
begin
ent.client := game.clients + (ent - g_edicts - 1);
if (deathmatch.value) then
begin
ClientBeginDeathmatch (ent);
Exit;
end;
// if there is already a body waiting for us (a loadgame), just
// take it, otherwise spawn one from scratch
if (ent.inuse = true)
then begin
// the client has cleared the client side viewangles upon
// connecting to the server, which is different than the
// state when the game is saved, so we need to compensate
// with deltaangles
for i:=0 to 2 do
ent.client.ps.pmove.delta_angles[i] := ANGLE2SHORT(ent.client.ps.viewangles[i]);
end
else begin
// a spawn point will completely reinitialize the entity
// except for the persistant data that was initialized at
// ClientConnect() time
G_InitEdict (ent);
ent.classname := 'player';
InitClientResp (ent.client);
PutClientInServer (ent);
end;
if (level.intermissiontime)
then MoveClientToIntermission (ent)
else
// send effect if in a multiplayer game
if (game.maxclients > 1) then
begin
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_LOGIN);
gi.multicast (ent.s.origin, MULTICAST_PVS);
gi.bprintf (PRINT_HIGH, '%s entered the game\n', ent.client.pers.netname);
end;
// make sure all view stuff is valid
ClientEndServerFrame (ent);
end;//procedure (GAME=CTF)
{*
===========
ClientUserInfoChanged
called whenever the player updates a userinfo variable.
The game can override any of the settings in place
(forcing skins or names, etc) before copying it off.
============
*}
// (GAME <> CTF)
procedure ClientUserinfoChanged (edict_t *ent, char *userinfo);
var
char *s;
{Y} playernum : integer;
begin
// check for malformed or illegal info strings
if (!Info_Validate(userinfo)) then
strcpy (userinfo, '\\name\\badinfo\\skin\\male/grunt');
// set name
s := Info_ValueForKey (userinfo, 'name');
strncpy (ent->client->pers.netname, s, sizeof(ent->client->pers.netname)-1);
{$IFNDEF CTF} //onlyGAME (noneCTF)
// set spectator
s := Info_ValueForKey (userinfo, 'spectator');
// spectators are only supported in deathmatch
if (deathmatch->value && *s && strcmp(s, '0'))
then ent.client.pers.spectator := true;
else ent.client.pers.spectator := false;
{$ENDIF}
// set skin
s := Info_ValueForKey (userinfo, 'skin');
{Y} playernum := ent-g_edicts-1;
// combine name and skin into a configstring
{$IFDEF CTF} //onlyCTF
//ZOID
if (ctf.value)
then CTFAssignSkin(ent, s)
else
//ZOID
{$ENDIF}
gi.configstring (CS_PLAYERSKINS+playernum, va('%s\\%s', ent.client.pers.netname, s));
// fov
if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV))
then ent.client.ps.fov := 90
else begin
ent.client.ps.fov := atoi(Info_ValueForKey(userinfo, 'fov'));
if (ent.client.ps.fov < 1)
then ent.client.ps.fov := 90;
else
if (ent.client.ps.fov > 160) then
ent.client.ps.fov := 160;
end;
// handedness
s := Info_ValueForKey (userinfo, 'hand');
if (strlen(s)) then
ent.client.pers.hand := atoi(s);
// save off the userinfo in case we want to check something later
strncpy (ent->client->pers.userinfo, userinfo, sizeof(ent->client->pers.userinfo)-1);
end;//procedure (GAME <> CTF)
{*
===========
ClientConnect
Called when a player begins connecting to the server.
The game can refuse entrance to a client by returning false.
If the client is allowed, the connection process will continue
and eventually get to ClientBegin()
Changing levels will NOT cause this to be called again, but
loadgames will.
============
*}
// (GAME <> CTF)
function ClientConnect (edict_t *ent, char *userinfo) : qboolean;
var
char *value;
int i, numspec;
begin
// check to see if they are on the banned IP list
value := Info_ValueForKey (userinfo, 'ip');
{$IF褼EF CTF} //onlyGAME (noneCTF)
if (SV_FilterPacket(value))
then begin
Info_SetValueForKey (userinfo, 'rejmsg', 'Banned.');
Result := false;
Exit;
end;
// check for a spectator
value := Info_ValueForKey (userinfo, 'spectator');
if (deathmatch->value && *value && strcmp(value, '0'))
then begin
if ( *spectator_password.string AND
strcmp(spectator_password.string, 'none') AND
strcmp(spectator_password.string, value))
then begin
Info_SetValueForKey(userinfo, 'rejmsg', 'Spectator password required or incorrect.');
Result := false;
Exit;
end;
// count spectators
// for (i = numspec = 0; i < maxclients->value; i++)
numspec := 0;
for i:=0 to maxclients.value-1 do
if (g_edicts[i+1].inuse) AND (g_edicts[i+1].client.pers.spectator) then
Inc(numspec);
if (numspec >= maxspectators.value) then
begin
Info_SetValueForKey(userinfo, 'rejmsg', 'Server spectator limit is full.');
Result := false;
Exit;
end;
end
else begin
{$ENDIF}
// check for a password
value := Info_ValueForKey (userinfo, 'password');
if ( *password.string AND
strcmp(password.string, 'none') AND
strcmp(password.string, value))
then begin
Info_SetValueForKey(userinfo, 'rejmsg', 'Password required or incorrect.');
Result := false;
Exit;
end;
//耢铗痂 篑腩忤
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -