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
This commit is contained in:
Spoike 2020-04-30 14:33:58 +00:00
parent 813c8c54ff
commit 08ccf2d0a8
7 changed files with 94 additions and 120 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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",

View file

@ -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);

View file

@ -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();

View file

@ -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;

View file

@ -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);