From 08ccf2d0a82022f810caa1892d9e02ddc850fe4d Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 30 Apr 2020 14:33:58 +0000 Subject: [PATCH] Fix up some netquake initiak angle quirk, and related quirks. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5688 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_main.c | 4 +- engine/client/cl_parse.c | 4 +- engine/common/fs.c | 23 ++++++---- engine/server/server.h | 7 +++ engine/server/sv_phys.c | 2 +- engine/server/sv_send.c | 92 ++++++++++++++++++++++++---------------- engine/server/sv_user.c | 82 ++++++----------------------------- 7 files changed, 94 insertions(+), 120 deletions(-) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a29acd919..5effe424f 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -894,13 +894,13 @@ void CL_CheckForResend (void) connectinfo.subprotocol = CPNQ_DP7; } else if (!strcmp(lbp, "qss") || - (progstype != PROG_QW && progstype != PROG_H2 && sv.state!=ss_clustermode)) //h2 depends on various extensions and doesn't really match either protocol, but we go for qw because that gives us all sorts of extensions. + (progstype != PROG_QW && progstype != PROG_H2 && sv.state!=ss_clustermode && cl_splitscreen.ival <= 0)) //h2 depends on various extensions and doesn't really match either protocol, but we go for qw because that gives us all sorts of extensions. { connectinfo.protocol = CP_NETQUAKE; connectinfo.subprotocol = CPNQ_FITZ666; connectinfo.fteext1 = Net_PextMask(PROTOCOL_VERSION_FTE1, true); connectinfo.fteext2 = Net_PextMask(PROTOCOL_VERSION_FTE2, true); - connectinfo.ezext1 = Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, false) & EZPEXT1_CLIENTADVERTISE; + connectinfo.ezext1 = Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, true) & EZPEXT1_CLIENTADVERTISE; } #endif else diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 47299e789..1fe0d3cca 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -8085,11 +8085,11 @@ void CLNQ_ParseServerMessage (void) //fixme: move this stuff to a common place // cl.playerview[destsplit].oldfixangle = cl.playerview[destsplit].fixangle; // VectorCopy(cl.playerview[destsplit].fixangles, cl.playerview[destsplit].oldfixangles); -// cl.playerview[destsplit].fixangle = false; +// cl.playerview[destsplit].fixangle = FIXANGLE_NO; if (cls.demoplayback) { // extern vec3_t demoangles; -// cl.playerview[destsplit].fixangle = true; +// cl.playerview[destsplit].fixangle = FIXANGLE_FIXED; // VectorCopy(demoangles, cl.playerview[destsplit].fixangles); } diff --git a/engine/common/fs.c b/engine/common/fs.c index 48954b893..4bdc2b744 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -3489,7 +3489,10 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths) #define QUAKESPASMSUCKS "set mod_h2holey_bugged 1\n" #define QCFG "set v_gammainverted 1\nset con_stayhidden 0\nset com_parseutf8 0\nset allow_download_pakcontents 1\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QRPCOMPAT QUAKESPASMSUCKS /*NetQuake reconfiguration, to make certain people feel more at home...*/ -#define NQCFG "//disablehomedir 1\n//mainconfig ftenq\ncfg_save_auto 1\n" QCFG "set sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\n" +#define NQCFG "//disablehomedir 1\n//mainconfig ftenq\ncfg_save_auto 1\n" QCFG "set sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\nset cl_demoreel 1\n" +#define SPASMCFG NQCFG "fps_preset builtin_spasm\nset cl_demoreel 0\n" +#define FITZCFG NQCFG "fps_preset builtin_spasm\n" +#define TENEBRAECFG NQCFG "fps_preset builtin_tenebrae\n" //nehahra has to be weird with its extra cvars, and buggy fullbrights. #define NEHCFG QCFG "set nospr32 0\nset cutscene 1\nalias startmap_sp \"map nehstart\"\nr_fb_bmodels 0\nr_fb_models 0\n" /*stuff that makes dp-only mods work a bit better*/ @@ -3513,6 +3516,8 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths) #define UPDATEURL(g) NULL #endif +#define QUAKEPROT "FTE-Quake DarkPlaces-Quake" + typedef struct { const char *argname; //used if this was used as a parameter. const char *exename; //used if the exe name contains this @@ -3558,17 +3563,17 @@ const gamemode_info_t gamemode_info[] = { #ifdef HAVE_LEGACY //cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name //standard quake - {"-quake", "q1", "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},QCFG,{"id1", "qw", "*fte"}, "Quake", UPDATEURL(Q1) /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/}, + {"-quake", "q1", QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", UPDATEURL(Q1)}, //alternative name, because fmf file install names are messy when a single name is used for registry install path. - {"-afterquake", NULL, "FTE-Quake",{"id1/pak0.pak", "id1/quake.rc"}, QCFG,{"id1", "qw", "*fte"}, "AfterQuake", UPDATEURL(Q1) /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/}, + {"-afterquake", NULL, "FTE-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "AfterQuake", UPDATEURL(Q1)}, //netquake-specific quake that avoids qw/ with its nquake fuckups, and disables nqisms - {"-netquake", NULL, "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},NQCFG,{"id1"}, "NetQuake", UPDATEURL(Q1) /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/}, - //blurgh - {"-spasm", NULL, "FTE-Quake DarkPlaces-Quake",{"quakespasm.pak"}, NQCFG"fps_preset builtin_spasm\nset cl_demoreel 0\n",{"/id1"}, "FauxSpasm", UPDATEURL(Q1) /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/}, + {"-netquake", NULL, QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},NQCFG, {"id1"}, "NetQuake", UPDATEURL(Q1)}, + //common variant of fitzquake that includes its own special pak file in the basedir + {"-spasm", NULL, QUAKEPROT, {"quakespasm.pak"}, SPASMCFG,{"/id1"}, "FauxSpasm", UPDATEURL(Q1)}, //because we can. 'fps_preset spasm' is hopefully close enough... - {"-fitz", "nq", "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},NQCFG"fps_preset builtin_spasm\n",{"id1"}, "FauxFitz", UPDATEURL(Q1) /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/}, + {"-fitz", "nq", QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},FITZCFG,{"id1"}, "FauxFitz", UPDATEURL(Q1)}, //because we can - {"-tenebrae", NULL, "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},NQCFG"fps_preset builtin_tenebrae\n",{"id1","tenebrae"},"FauxTenebrae", UPDATEURL(Q1) /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/}, + {"-tenebrae", NULL, QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},TENEBRAECFG,{"id1", "tenebrae"}, "FauxTenebrae", UPDATEURL(Q1)}, //quake's mission packs should not be favoured over the base game nor autodetected //third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content. @@ -3582,7 +3587,7 @@ const gamemode_info_t gamemode_info[] = { {"-quoth", "quoth", "FTE-Quake", {"id1/pak0.pak","id1/quake.rc"},QCFG, {"id1", "qw", "quoth", "*fte"}, "Quake: Quoth", UPDATEURL(Q1)}, {"-nehahra", "nehahra", "FTE-Quake", {"id1/pak0.pak","id1/quake.rc"},NEHCFG, {"id1", "qw", "nehahra", "*fte"}, "Quake: Seal Of Nehahra", UPDATEURL(Q1)}, //various quake-based standalone mods. - {"-nexuiz", "nexuiz", "Nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "*ftedata"},"Nexuiz"}, +// {"-nexuiz", "nexuiz", "Nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "*ftedata"},"Nexuiz"}, // {"-xonotic", "xonotic", "Xonotic", {"data/xonotic-data.pk3dir", // "data/xonotic-*data*.pk3"}, XONCFG, {"data", "*ftedata"},"Xonotic", UPDATEURL(Xonotic)}, // {"-spark", "spark", "Spark", {"base/src/progs.src", diff --git a/engine/server/server.h b/engine/server/server.h index 56efcc8d6..2301bff2f 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -454,6 +454,11 @@ enum #define STUFFCMD_BROADCAST ( 1<<2) // everyone sees it. #define STUFFCMD_UNRELIABLE ( 1<<3) // someone might not see it. oh well. +#define FIXANGLE_NO 0 //don't override anything +#define FIXANGLE_AUTO 1 //guess (initial=fixed, spammed=fixed, sporadic=relative) +#define FIXANGLE_DELTA 2 //send a relative change +#define FIXANGLE_FIXED 3 //send a absolute angle. + enum serverprotocols_e { SCP_BAD, //don't send (a bot) @@ -712,6 +717,7 @@ typedef struct client_s struct client_s *controller; /*first in splitscreen chain, NULL=nosplitscreen*/ struct client_s *controlled; /*next in splitscreen chain*/ + qbyte seat; /*these are the current rates*/ float ratetime; @@ -1321,6 +1327,7 @@ void VARGS SV_BroadcastTPrintf (int level, translation_t fmt, ...); void VARGS SV_BroadcastCommand (const char *fmt, ...) LIKEPRINTF(1); void SV_SendMessagesToAll (void); void SV_FindModelNumbers (void); +void SV_SendFixAngle(client_t *client, sizebuf_t *msg, int fixtype, qboolean roll); void SV_BroadcastUserinfoChange(client_t *about, qboolean isbasic, const char *key, const char *newval); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index eafc5141c..039efd3e8 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -2169,7 +2169,7 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent) if (svs.clients[ent->entnum-1].protocol == SCP_BAD) - svent->v->fixangle = 0; //bots never get fixangle cleared otherwise + svent->v->fixangle = FIXANGLE_NO; //bots never get fixangle cleared otherwise host_client = &svs.clients[ent->entnum-1]; SV_ClientThink(); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 4da4ea022..4eef313da 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1624,19 +1624,66 @@ void SV_FindModelNumbers (void) } } +void SV_SendFixAngle(client_t *client, sizebuf_t *msg, int fixtype, qboolean roll) +{ + unsigned i; + client_t *controller = client->controller?client->controller:client; + edict_t *ent = client->edict; + float *ang; + if (!ent || client->protocol == SCP_QUAKE2) + return; + ang = ent->v->fixangle?ent->v->angles:ent->v->v_angle; //angles is just WEIRD for mdls, but then quake sucks. + if (ent->v->movetype == MOVETYPE_6DOF) + roll = true; + + if (fixtype == FIXANGLE_AUTO) + { + if (!client->lockangles && controller->delta_sequence != -1 && !client->viewent) + fixtype = FIXANGLE_DELTA; + else + fixtype = FIXANGLE_FIXED; + } + if (fixtype == FIXANGLE_DELTA && !(controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) + fixtype = FIXANGLE_FIXED; //sorry, can't do it. + + if (!client->lockangles && controller->netchan.message.cursize < controller->netchan.message.maxsize/2) + msg = NULL; //try to keep them vaugely reliable, where feasable. + if (!msg) + msg = ClientReliable_StartWrite(client, 10); + + if (client->seat) + { + MSG_WriteByte(msg, svcfte_choosesplitclient); + MSG_WriteByte(msg, client->seat); + } + if (fixtype == FIXANGLE_DELTA && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) + { + MSG_WriteByte (msg, svcfte_setangledelta); + for (i=0 ; i < 3 ; i++) + { + int newa = ang[i] - SHORT2ANGLE(client->lastcmd.angles[i]); + MSG_WriteAngle16 (msg, newa); + client->lastcmd.angles[i] = ANGLE2SHORT(ang[i]); + } + } + else + { + MSG_WriteByte (msg, svc_setangle); + if (host_client->ezprotocolextensions1 & EZPEXT1_SETANGLEREASON) + MSG_WriteByte (&host_client->netchan.message, (fixtype == FIXANGLE_DELTA)?2:0); //shitty backwards incompatible protocol extension that breaks from writebytes. + for (i=0 ; i < 3 ; i++) + MSG_WriteAngle (msg, (i==2&&!roll)?0:ang[i]); + } + client->lockangles = true; //so that spammed fixangles use absolute values, locking the camera in place. +} + void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum) { edict_t *other; edict_t *ent; int i; - float newa; - client_t *controller; ent = client->edict; - if (client->controller) - controller = client->controller; - else - controller = client; if (!ent) return; @@ -1674,37 +1721,8 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum) } else if (ent->v->fixangle) { - int fix = ent->v->fixangle; - if (!client->lockangles) - { - //try to keep them vaugely reliable. - if (controller->netchan.message.cursize < controller->netchan.message.maxsize/2) - msg = &controller->netchan.message; - } - - if (pnum) - { - MSG_WriteByte(msg, svcfte_choosesplitclient); - MSG_WriteByte(msg, pnum); - } - if (((!client->lockangles && fix!=3) || fix==2) && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && controller->delta_sequence != -1 && !client->viewent) - { - MSG_WriteByte (msg, svcfte_setangledelta); - for (i=0 ; i < 3 ; i++) - { - newa = ent->v->angles[i] - SHORT2ANGLE(client->lastcmd.angles[i]); - MSG_WriteAngle16 (msg, newa); - client->lastcmd.angles[i] = ANGLE2SHORT(ent->v->angles[i]); - } - } - else - { - MSG_WriteByte (msg, svc_setangle); - for (i=0 ; i < 3 ; i++) - MSG_WriteAngle (msg, ent->v->angles[i]); - } - ent->v->fixangle = 0; - client->lockangles = true; + SV_SendFixAngle(client, msg, ent->v->fixangle, true); + ent->v->fixangle = FIXANGLE_NO; } else client->lockangles = false; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 799f18744..516b56753 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -55,6 +55,8 @@ extern cvar_t cl_rollangle; #endif cvar_t sv_spectalk = CVAR("sv_spectalk", "1"); +#define nqcompat_spawnbeforeready 1 + cvar_t sv_mapcheck = CVAR("sv_mapcheck", "1"); cvar_t sv_fullredirect = CVARD("sv_fullredirect", "", "This is the ip:port to redirect players to when the server is full"); @@ -2063,12 +2065,8 @@ void SV_Begin_Core(client_t *split) PR_ExecuteProgram (svprogfuncs, f); } - ClientReliableWrite_Begin(split, svc_setangle, 8); - if (host_client->ezprotocolextensions1 & EZPEXT1_SETANGLEREASON) - ClientReliableWrite_Byte (host_client, 0); - ClientReliableWrite_Angle (host_client, split->edict->v->v_angle[0]); - ClientReliableWrite_Angle (host_client, split->edict->v->v_angle[1]); - ClientReliableWrite_Angle (host_client, 0); //roll angle is messy with cl_roll. we don't want to be stuck rolling. + SV_SendFixAngle(split, NULL, FIXANGLE_FIXED, false); + split->edict->v->fixangle = FIXANGLE_NO; //no point doing it again return; } split->spawned = true; @@ -2247,6 +2245,9 @@ void SV_Begin_Core(client_t *split) split->dp_pl = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping_packetloss", ev_float, NULL); } #endif + + SV_SendFixAngle(split, NULL, FIXANGLE_FIXED, false); + split->edict->v->fixangle = FIXANGLE_NO; //no point doing it again } /* @@ -2258,7 +2259,6 @@ void SV_Begin_f (void) { client_t *split; unsigned pmodel = 0, emodel = 0; - qboolean sendangles=false; if (!SV_CheckRealIP(host_client, true)) { @@ -2284,12 +2284,6 @@ void SV_Begin_f (void) return; } - if (host_client->istobeloaded) - sendangles = true; - if (host_client->protocol == SCP_QUAKE2) - sendangles = false; - - for (split = host_client; split; split = split->controlled) { //tell the gamecode they're ready SV_Begin_Core(split); @@ -2312,22 +2306,6 @@ void SV_Begin_f (void) SV_BroadcastTPrintf (PRINT_HIGH, "warning: %s eyes or player model does not match\n", host_client->name); } - if (sendangles) - { -// -// send a fixangle over the reliable channel to make sure it gets there -// Never send a roll angle, because savegames can catch the server -// in a state where it is expecting the client to correct the angle -// and it won't happen if the game was just loaded, so you wind up -// with a permanent head tilt - MSG_WriteByte (&host_client->netchan.message, svc_setangle); - if (host_client->ezprotocolextensions1 & EZPEXT1_SETANGLEREASON) - MSG_WriteByte (&host_client->netchan.message, 0); - MSG_WriteAngle (&host_client->netchan.message, 0 ); - MSG_WriteAngle (&host_client->netchan.message, host_client->edict->v->angles[1] ); - MSG_WriteAngle (&host_client->netchan.message, 0 ); - } - #ifdef MVD_RECORDING SV_MVD_AutoRecord(); #endif @@ -4295,27 +4273,8 @@ static void SV_UpdateSeats(client_t *controller) for (curclients = 0, cl = controller; cl; cl = cl->controlled, curclients++) { -// send a fixangle over the reliable channel to make sure it gets there -// Never send a roll angle, because savegames can catch the server -// in a state where it is expecting the client to correct the angle -// and it won't happen if the game was just loaded, so you wind up -// with a permanent head tilt - ClientReliableWrite_Begin(controller, svcfte_choosesplitclient, 2+curclients); - ClientReliableWrite_Byte (controller, curclients); - ClientReliableWrite_Byte (controller, svc_setangle); - if (cl->edict->v->fixangle) - { - ClientReliableWrite_Angle(controller, cl->edict->v->angles[0]); - ClientReliableWrite_Angle(controller, cl->edict->v->angles[1]); - ClientReliableWrite_Angle(controller, 0);//cl->edict->v->angles[2]); - cl->edict->v->fixangle = 0; - } - else - { - ClientReliableWrite_Angle(controller, cl->edict->v->v_angle[0]); - ClientReliableWrite_Angle(controller, cl->edict->v->v_angle[1]); - ClientReliableWrite_Angle(controller, 0);//cl->edict->v->v_angle[2]); - } + SV_SendFixAngle(cl, NULL, FIXANGLE_FIXED, false); + cl->edict->v->fixangle = FIXANGLE_NO; //no point doing it again } } @@ -5192,7 +5151,7 @@ void Cmd_SetPos_f(void) sv_player->v->angles[0] = atof(Cmd_Argv(4)); sv_player->v->angles[1] = atof(Cmd_Argv(5)); sv_player->v->angles[2] = atof(Cmd_Argv(6)); - sv_player->v->fixangle = true; + sv_player->v->fixangle = FIXANGLE_FIXED; } } @@ -5779,8 +5738,7 @@ static void SVNQ_Spawn_f (void) //qw servers hold off until the last possible moment. //so qw servers prevent the player from getting shot too early. //while nq ensures that reliables sent in ClientConnect are actually flushed before unreliables/entities start to arrive. -// if (nqcompat_spawnbeforeready.ival) - SV_Begin_Core(host_client); + SV_Begin_Core(host_client); ClientReliableWrite_Begin (host_client, svcnq_signonnum, 2); ClientReliableWrite_Byte (host_client, 3); @@ -5790,14 +5748,14 @@ static void SVNQ_Spawn_f (void) static void SVNQ_Begin_f (void) { unsigned pmodel = 0, emodel = 0; - qboolean sendangles=false; if (host_client->state == cs_spawned) return; // don't begin again host_client->state = cs_spawned; - SV_Begin_Core(host_client); + //while qw spawns player entity in the 'begin' stage, nq spawns in the 'spawn' stage rather than here. +// SV_Begin_Core(host_client); // clear the net statistics, because connecting gives a bogus picture host_client->netchan.frame_latency = 0; @@ -5817,20 +5775,6 @@ static void SVNQ_Begin_f (void) SV_BroadcastTPrintf (PRINT_HIGH, "warning: %s eyes or player model not verified\n", host_client->name); } - if (sendangles) - { -// -// send a fixangle over the reliable channel to make sure it gets there -// Never send a roll angle, because savegames can catch the server -// in a state where it is expecting the client to correct the angle -// and it won't happen if the game was just loaded, so you wind up -// with a permanent head tilt - MSG_WriteByte (&host_client->netchan.message, svc_setangle); - MSG_WriteAngle (&host_client->netchan.message, 0 ); - MSG_WriteAngle (&host_client->netchan.message, host_client->edict->v->angles[1] ); - MSG_WriteAngle (&host_client->netchan.message, 0 ); - } - // MSG_WriteByte (&host_client->netchan.message, svc_signonnum); // MSG_WriteByte (&host_client->netchan.message, 4);