added qccgui icon (courtesy of shpuld)

isolated transfers a little.
added preliminary support for r1q2 and q2pro protocols (no zlib).
fixed some missing q2 hud configstrings.
fixed models attached to particles not appearing the first time around.
fixed halos appearing on {foo fullbright textures.
fix particle crash bug from missing particlecubes.
implement r_converteffectinfo (instead of r_importeffectinfo with r_exportalleffects) for convenience. also now more complete and more accurate.
loadfont no longer auto-allocates slot 0.
fix issues with r_dynamic -1
don't restart audio on vid_reload (only reload it). this fixes audio issues with capturedemo with gamedir changes.
fix possible crash from loading sounds during an audio reload/restart.
now listens on both ports 27500 and 26000 when running quake, by default. sv_port or -port args will override.
work around surfedge corruption in some instance of the slide4 map that dimman found.
attempt to nudge players to travel at at least 200qu when travelling vertically through portals. this should help alieviate gravity-induced stuttering issues.
fix nested function types used in conjunction with op_state. now assumes static within the parent.
optimise array indexes slightly.
fix issue with ptr[float].foo
fix some qcc bugs to do with implicit type conversions
fix a portal / angle protocol extension issue, so legacy clients can use portals, they just can't see the other side (nor predict them).
fix q2 victory.pcx issue at the end of the game.
use abort/sigabort instead of sigsegv on linux sys_errors. this should help get people to report stuff better.
reformat the nq server advertising to be more helpful.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4996 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-12-28 17:41:39 +00:00
parent b1d2179394
commit e996609c73
54 changed files with 1615 additions and 537 deletions

View file

@ -1368,7 +1368,8 @@ endif
# This is for linking the FTE icon to the MinGW target
$(OUT_DIR)/resources.o : winquake.rc
@$(WINDRES) $(BRANDFLAGS) -I$(CLIENT_DIR) -O coff $< $@
$(OUT_DIR)/fteqcc.o : fteqcc.rc
@$(WINDRES) $(BRANDFLAGS) -I$(PROGS_DIR) -O coff $< $@
#npAPI stuff requires some extra resources
$(OUT_DIR)/npplug.o : ftequake/npplug.rc
@$(WINDRES) $(BRANDFLAGS) -I$(CLIENT_DIR) -O coff $< $@
@ -1553,11 +1554,11 @@ _qcc-tmp: $(REQDIR)
qcc-rel:
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqcc" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qcctui.o"
qccgui-rel:
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqccgui" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qccgui.o qccguistuff.o" LDFLAGS="$(LDFLAGS) -lole32 -lcomdlg32 -lcomctl32 -lshlwapi -mwindows"
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqccgui" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qccgui.o qccguistuff.o fteqcc.o" LDFLAGS="$(LDFLAGS) -lole32 -lcomdlg32 -lcomctl32 -lshlwapi -mwindows"
qcc-dbg:
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqcc" OUT_DIR="$(DEBUG_DIR)/qcc" SOBJS="qcctui.o"
qccgui-dbg:
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqccgui" OUT_DIR="$(DEBUG_DIR)/qcc" SOBJS="qccgui.o qccguistuff.o" LDFLAGS="$(LDFLAGS) -lole32 -lcomdlg32 -lcomctl32 -lshlwapi -mwindows"
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqccgui" OUT_DIR="$(DEBUG_DIR)/qcc" SOBJS="qccgui.o qccguistuff.o fteqcc.o" LDFLAGS="$(LDFLAGS) -lole32 -lcomdlg32 -lcomctl32 -lshlwapi -mwindows"
#scintilla is messy as fuck when building statically. but at least we can strip out the lexers we don't use this way.

View file

@ -1456,8 +1456,13 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
MSG_WriteByte (buf, clcq2_move);
// save the position for a checksum qbyte
checksumIndex = buf->cursize;
MSG_WriteByte (buf, 0);
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
checksumIndex = -1;
else
{
checksumIndex = buf->cursize;
MSG_WriteByte (buf, 0);
}
if (!cl.q2frame.valid || cl_nodelta.ival)
MSG_WriteLong (buf, -1); // no compression
@ -1484,11 +1489,14 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
// calculate a checksum over the move commands
dontdrop = CL_WriteDeltas(0, buf);
buf->data[checksumIndex] = Q2COM_BlockSequenceCRCByte(
buf->data + checksumIndex + 1, buf->cursize - checksumIndex - 1,
seq_hash);
if (checksumIndex >= 0)
{
buf->data[checksumIndex] = Q2COM_BlockSequenceCRCByte(
buf->data + checksumIndex + 1, buf->cursize - checksumIndex - 1,
seq_hash);
}
if (cl.sendprespawn)
if (cl.sendprespawn || !cls.protocol_q2)
buf->cursize = 0; //tastyspleen.net is alergic.
return dontdrop;

View file

@ -242,7 +242,11 @@ static struct
netadr_t adr; //address that we're trying to transfer to.
int mtu;
unsigned int compresscrc;
int protocol; //tracked as part of guesswork based upon what replies we get.
int protocol; //nq/qw/q2/q3. guessed based upon server replies
int subprotocol; //the monkeys are trying to eat me.
unsigned int fteext1;
unsigned int fteext2;
int qport;
int challenge; //tracked as part of guesswork based upon what replies we get.
double time; //for connection retransmits
int defaultport;
@ -541,8 +545,8 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
fteprotextsupported = 0;
#endif
cls.fteprotocolextensions = fteprotextsupported;
cls.fteprotocolextensions2 = fteprotextsupported2;
connectinfo.fteext1 = fteprotextsupported;
connectinfo.fteext2 = fteprotextsupported2;
#endif
t1 = Sys_DoubleTime ();
@ -574,8 +578,12 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
connectinfo.time = realtime+t2-t1; // for retransmit requests
cls.qport = qport.value;
Cvar_SetValue(&qport, (cls.qport+1)&0xffff);
//fixme: we shouldn't cycle these so much
connectinfo.qport = qport.value;
Cvar_SetValue(&qport, (connectinfo.qport+1)&0xffff);
if (connectinfo.protocol == CP_QUAKE2 && (connectinfo.subprotocol == PROTOCOL_VERSION_R1Q2 || connectinfo.subprotocol == PROTOCOL_VERSION_Q2PRO))
connectinfo.qport &= 0xff;
// Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), MAX_INFO_STRING);
@ -601,8 +609,7 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
#ifdef Q3CLIENT
if (connectinfo.protocol == CP_QUAKE3)
{ //q3 requires some very strange things.
cls.challenge = connectinfo.challenge;
CLQ3_SendConnectPacket(to);
CLQ3_SendConnectPacket(to, connectinfo.challenge, connectinfo.qport);
return;
}
#endif
@ -612,15 +619,7 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
if (clients>1) //splitscreen 'connect' command specifies the number of userinfos sent.
Q_strncatz(data, va("%i", clients), sizeof(data));
#ifdef Q2CLIENT
if (connectinfo.protocol == CP_QUAKE2)
Q_strncatz(data, va(" %i", PROTOCOL_VERSION_Q2), sizeof(data));
else
#endif
Q_strncatz(data, va(" %i", PROTOCOL_VERSION_QW), sizeof(data));
Q_strncatz(data, va(" %i %i", cls.qport, connectinfo.challenge), sizeof(data));
Q_strncatz(data, va(" %i %i %i", connectinfo.subprotocol, connectinfo.qport, connectinfo.challenge), sizeof(data));
//userinfo0 has some twiddles for extensions from other qw engines.
Q_strncatz(data, " \"", sizeof(data));
@ -638,9 +637,12 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
Q_strncatz(data, "\"", sizeof(data));
for (c = 1; c < clients; c++)
{
Q_strncatz(data, va(" \"%s\"", cls.userinfo[c]), sizeof(data));
}
if (connectinfo.protocol == CP_QUAKE2 && connectinfo.subprotocol == PROTOCOL_VERSION_R1Q2)
Q_strncatz(data, va(" %d %d", mtu, 1905), sizeof(data)); //mti, sub-sub-version
else if (connectinfo.protocol == CP_QUAKE2 && connectinfo.subprotocol == PROTOCOL_VERSION_Q2PRO)
Q_strncatz(data, va(" %d 0 0 %d", mtu, 1021), sizeof(data)); //mtu, netchan-fragmentation, zlib, sub-sub-version
Q_strncatz(data, "\n", sizeof(data));
@ -681,8 +683,6 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
Q_strncatz(data, va("0x%x \"%s\"\n", PROTOCOL_INFO_GUID, info), sizeof(data));
NET_SendPacket (NS_CLIENT, strlen(data), data, to);
cl.splitclients = 0;
}
char *CL_TryingToConnect(void)
@ -718,9 +718,7 @@ void CL_CheckForResend (void)
if (!cls.state && (!connectinfo.trying || sv.state != ss_clustermode) && sv.state)
{
extern cvar_t dpcompat_nopreparse;
unsigned int pext1, pext2;
pext1 = 0;
pext2 = 0;
memset(&connectinfo, 0, sizeof(connectinfo));
connectinfo.trying = true;
connectinfo.istransfer = false;
@ -735,28 +733,29 @@ void CL_CheckForResend (void)
{
#ifdef Q3CLIENT
case GT_QUAKE3:
pext1 = 0;
pext2 = 0;
cls.protocol = CP_QUAKE3;
connectinfo.protocol = CP_QUAKE3;
break;
#endif
#ifdef Q2CLIENT
case GT_QUAKE2:
pext1 = 0;
pext2 = 0;
cls.protocol = CP_QUAKE2;
connectinfo.protocol = CP_QUAKE2;
connectinfo.subprotocol = PROTOCOL_VERSION_Q2;
break;
#endif
default:
cl.movesequence = 0;
if (!strcmp(cl_loopbackprotocol.string, "qw"))
{ //qw with all supported extensions -default
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
cls.protocol = CP_QUAKEWORLD;
connectinfo.fteext1 = Net_PextMask(1, false);
connectinfo.fteext2 = Net_PextMask(2, false);
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
}
else if (!strcmp(cl_loopbackprotocol.string, "qwid") || !strcmp(cl_loopbackprotocol.string, "idqw"))
cls.protocol = CP_QUAKEWORLD;
{
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
}
#ifdef Q3CLIENT
else if (!strcmp(cl_loopbackprotocol.string, "q3"))
cls.protocol = CP_QUAKE3;
@ -766,53 +765,55 @@ void CL_CheckForResend (void)
{ //for debugging.
if (rand() & 1)
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_FITZ666;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_FITZ666;
}
else
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
connectinfo.fteext1 = Net_PextMask(1, false);
connectinfo.fteext2 = Net_PextMask(2, false);
}
}
else if (!strcmp(cl_loopbackprotocol.string, "fitz") || !strcmp(cl_loopbackprotocol.string, "666") || !strcmp(cl_loopbackprotocol.string, "999"))
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_FITZ666;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_FITZ666;
}
else if (!strcmp(cl_loopbackprotocol.string, "nq")) //actually proquake, because we might as well use the extra angles
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_PROQUAKE3_4;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_PROQUAKE3_4;
}
else if (!strcmp(cl_loopbackprotocol.string, "nqid") || !strcmp(cl_loopbackprotocol.string, "idnq"))
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_ID;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_ID;
}
else if (!strcmp(cl_loopbackprotocol.string, "dp6") || !strcmp(cl_loopbackprotocol.string, "dpp6"))
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_DP6;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_DP6;
}
else if (!strcmp(cl_loopbackprotocol.string, "dp7") || !strcmp(cl_loopbackprotocol.string, "dpp7"))
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_DP7;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_DP7;
}
else if (progstype != PROG_QW && progstype != PROG_H2) //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.
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_FITZ666;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_FITZ666;
//FIXME: pext
}
#endif
else
{ //protocol wasn't recognised, and we didn't take the nq fallback, so that must mean we're going for qw.
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
connectinfo.fteext1 = Net_PextMask(1, false);
connectinfo.fteext2 = Net_PextMask(2, false);
}
#ifdef NETPREPARSE
@ -824,28 +825,30 @@ void CL_CheckForResend (void)
Con_Printf("dpcompat_nopreparse is unsupported with hexen2\n");
else if (progstype == PROG_QW && cls.protocol != CP_QUAKEWORLD)
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
connectinfo.fteext1 = Net_PextMask(1, false);
connectinfo.fteext2 = Net_PextMask(2, false);
}
else if (progstype != PROG_QW && cls.protocol == CP_QUAKEWORLD)
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_DP7; //dpcompat_nopreparse is only really needed for DP mods that send unknowable svc_tempentity messages to the client.
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_DP7; //dpcompat_nopreparse is only really needed for DP mods that send unknowable svc_tempentity messages to the client.
}
}
//make sure the protocol within demos is actually correct/sane
if (cls.demorecording == 1 && cls.protocol != CP_QUAKEWORLD)
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
connectinfo.fteext1 = Net_PextMask(1, false);
connectinfo.fteext2 = Net_PextMask(2, false);
}
else if (cls.demorecording == 2 && cls.protocol != CP_NETQUAKE)
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_FITZ666;
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_FITZ666;
//FIXME: use pext.
}
break;
@ -853,7 +856,6 @@ void CL_CheckForResend (void)
CL_FlushClientCommands(); //clear away all client->server clientcommands.
connectinfo.protocol = cls.protocol;
#ifdef NQPROT
if (connectinfo.protocol == CP_NETQUAKE)
{
@ -873,21 +875,21 @@ void CL_CheckForResend (void)
net_message.packing = SZ_RAWBYTES;
net_message.cursize = 0;
if (cls.protocol_nq == CPNQ_ID)
if (connectinfo.subprotocol == CPNQ_ID)
{
net_from = connectinfo.adr;
Cmd_TokenizeString (va("connect %i %i %i \"\\name\\unconnected\"", NQ_NETCHAN_VERSION, 0, SV_NewChallenge()), false, false);
SVC_DirectConnect();
}
else if (cls.protocol_nq == CPNQ_FITZ666)
else if (connectinfo.subprotocol == CPNQ_FITZ666)
{
net_from = connectinfo.adr;
Cmd_TokenizeString (va("connect %i %i %i \"\\name\\unconnected\\mod\\666\"", NQ_NETCHAN_VERSION, 0, SV_NewChallenge()), false, false);
SVC_DirectConnect();
}
else if (cls.protocol_nq == CPNQ_PROQUAKE3_4)
else if (connectinfo.subprotocol == CPNQ_PROQUAKE3_4)
{
net_from = connectinfo.adr;
Cmd_TokenizeString (va("connect %i %i %i \"\\name\\unconnected\\mod\\1\"", NQ_NETCHAN_VERSION, 0, SV_NewChallenge()), false, false);
@ -903,8 +905,7 @@ void CL_CheckForResend (void)
{
if (!connectinfo.challenge)
connectinfo.challenge = rand();
cls.challenge = connectinfo.challenge;
CL_SendConnectPacket (NULL, 8192-16, pext1, pext2, false);
CL_SendConnectPacket (NULL, 8192-16, connectinfo.fteext1, connectinfo.fteext2, false);
}
return;
}
@ -2797,7 +2798,10 @@ void CL_ConnectionlessPacket (void)
#ifdef Q2CLIENT
if (connectinfo.protocol == CP_QUAKE2 || connectinfo.protocol == CP_UNKNOWN)
{
connectinfo.protocol = CP_QUAKE2;
connectinfo.subprotocol = PROTOCOL_VERSION_Q2;
}
else
{
Con_Printf("\nChallenge from another protocol, ignoring Q2 challenge\n");
@ -2812,7 +2816,10 @@ void CL_ConnectionlessPacket (void)
/*no idea, assume a QuakeWorld challenge response ('c' packet)*/
else if (connectinfo.protocol == CP_QUAKEWORLD || connectinfo.protocol == CP_UNKNOWN)
{
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
}
else
{
Con_Printf("\nChallenge from another protocol, ignoring QW challenge\n");
@ -2825,7 +2832,30 @@ void CL_ConnectionlessPacket (void)
lasttime = curtime;
lastadr = net_from;
connectinfo.challenge = atoi(s);
s = COM_Parse(s);
connectinfo.challenge = atoi(com_token);
while((s = COM_Parse(s)))
{
if (connectinfo.protocol == CP_QUAKE2 && !strncmp(com_token, "p=", 2))
{
char *p = com_token+2;
do
{
switch(strtoul(p, &p, 0))
{
case PROTOCOL_VERSION_R1Q2:
if (connectinfo.subprotocol < PROTOCOL_VERSION_R1Q2)
connectinfo.subprotocol = PROTOCOL_VERSION_R1Q2;
break;
case PROTOCOL_VERSION_Q2PRO:
if (connectinfo.subprotocol < PROTOCOL_VERSION_Q2PRO)
connectinfo.subprotocol = PROTOCOL_VERSION_Q2PRO;
break;
}
} while (*p++ == ',');
}
}
for(;;)
{
@ -2917,7 +2947,7 @@ void CL_ConnectionlessPacket (void)
{
Con_Printf ("accept\n");
Validation_Apply_Ruleset();
Netchan_Setup(NS_CLIENT, &cls.netchan, &net_from, cls.qport);
Netchan_Setup(NS_CLIENT, &cls.netchan, &net_from, connectinfo.qport);
CL_ParseEstablished();
Con_DPrintf ("CL_EstablishConnection: connected to %s\n", cls.servername);
@ -2986,6 +3016,7 @@ void CL_ConnectionlessPacket (void)
if (c == S2C_CONNECTION)
{
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
#if defined(Q2CLIENT) || defined(Q3CLIENT)
client_connect: //fixme: make function
#endif
@ -3018,9 +3049,18 @@ client_connect: //fixme: make function
}
}
connectinfo.trying = false;
cl.splitclients = 0;
cls.protocol = connectinfo.protocol;
cls.fteprotocolextensions = connectinfo.fteext1;
cls.fteprotocolextensions2 = connectinfo.fteext2;
cls.challenge = connectinfo.challenge;
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, cls.qport);
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, connectinfo.qport);
if (cls.protocol == CP_QUAKE2)
{
cls.protocol_q2 = connectinfo.subprotocol;
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
cls.netchan.qportsize = 1;
}
cls.netchan.fragmentsize = connectinfo.mtu;
if (connectinfo.mtu >= 64)
cls.netchan.message.maxsize = sizeof(cls.netchan.message_buf);
@ -3184,7 +3224,9 @@ void CLNQ_ConnectionlessPacket(void)
Validation_Apply_Ruleset();
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, cls.qport);
cls.fteprotocolextensions = connectinfo.fteext1;
cls.fteprotocolextensions2 = connectinfo.fteext2;
Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, connectinfo.qport);
CL_ParseEstablished();
cls.netchan.isnqprotocol = true;
cls.netchan.compresstable = NULL;

View file

@ -3102,9 +3102,9 @@ void CLQ2_ParseServerData (void)
int svcnt;
// int cflag;
memset(&cls.netchan.netprim, 0, sizeof(cls.netchan.netprim));
cls.netchan.netprim.coordsize = 2;
cls.netchan.netprim.anglesize = 1;
MSG_ChangePrimitives(cls.netchan.netprim);
Con_DPrintf ("Serverdata packet received.\n");
//
@ -3119,8 +3119,12 @@ void CLQ2_ParseServerData (void)
i = MSG_ReadLong ();
cls.protocol_q2 = i;
if (i > PROTOCOL_VERSION_Q2 || i < (cls.demoplayback?PROTOCOL_VERSION_Q2_DEMO_MIN:PROTOCOL_VERSION_Q2_MIN))
Host_EndGame ("Server returned version %i, not %i", i, PROTOCOL_VERSION_Q2);
if (i == PROTOCOL_VERSION_R1Q2)
Con_DPrintf("Using R1Q2 protocol\n");
else if (i == PROTOCOL_VERSION_Q2PRO)
Con_DPrintf("Using Q2PRO protocol\n");
else if (i > PROTOCOL_VERSION_Q2 || i < (cls.demoplayback?PROTOCOL_VERSION_Q2_DEMO_MIN:PROTOCOL_VERSION_Q2_MIN))
Host_EndGame ("Q2 Server returned version %i, not %i", i, PROTOCOL_VERSION_Q2);
svcnt = MSG_ReadLong ();
/*cl.attractloop =*/ MSG_ReadByte ();
@ -3160,6 +3164,40 @@ void CLQ2_ParseServerData (void)
str = MSG_ReadString ();
Q_strncpyz (cl.levelname, str, sizeof(cl.levelname));
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2)
{
unsigned short r1q2ver;
qboolean isenhanced = MSG_ReadByte();
if (isenhanced)
Host_EndGame ("R1Q2 server is running an unsupported mod");
r1q2ver = MSG_ReadShort(); //protocol version... limit... yeah, buggy.
if (r1q2ver < 1903 || r1q2ver > 1905)
Host_EndGame ("R1Q2 server version %i not supported", r1q2ver);
MSG_ReadByte(); //'used to be advanced deltas'
MSG_ReadByte(); //strafejump hack
if (r1q2ver >= 1905)
cls.netchan.netprim.q2flags |= NPQ2_SIZE32;
}
else if (cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
{
unsigned short q2prover = MSG_ReadShort(); //q2pro protocol version
if (q2prover < 1011 || q2prover > 1021)
Host_EndGame ("Q2PRO server version %i not supported", q2prover);
MSG_ReadByte(); //server state (ie: demo playback vs actual game)
MSG_ReadByte(); //strafejump hack
MSG_ReadByte(); //q2pro qw-mode. kinda silly for us tbh.
if (q2prover >= 1014)
cls.netchan.netprim.q2flags |= NPQ2_SIZE32;
if (q2prover >= 1018)
cls.netchan.netprim.q2flags |= NPQ2_ANG16;
if (q2prover >= 1015)
MSG_ReadByte(); //some kind of waterjump hack enable
}
MSG_ChangePrimitives(cls.netchan.netprim);
if (cl.playerview[0].playernum == -1)
{ // playing a cinematic or showing a pic, not a level
SCR_EndLoadingPlaque();
@ -3801,6 +3839,9 @@ void CLQ2_ParseClientinfo(int i, char *s)
player_info_t *player;
//s contains "name\model/skin"
if (i >= MAX_CLIENTS)
return;
player = &cl.players[i];
*player->userinfo = '\0';
@ -3857,7 +3898,11 @@ void CLQ2_ParseConfigString (void)
// do something apropriate
if (i == Q2CS_SKY)
if (i == Q2CS_NAME)
{
Q_strncpyz (cl.levelname, s, sizeof(cl.levelname));
}
else if (i == Q2CS_SKY)
{
Q_strncpyz (cl.skyname, s, sizeof(cl.skyname));
}
@ -3921,9 +3966,16 @@ void CLQ2_ParseConfigString (void)
Z_Free(cl.item_name[i-Q2CS_ITEMS]);
cl.item_name[i-Q2CS_ITEMS] = Z_StrDup(s);
}
else if (i >= Q2CS_GENERAL && i < Q2CS_GENERAL+Q2MAX_GENERAL)
{
Z_Free(cl.configstring_general[i-Q2CS_PLAYERSKINS]);
cl.configstring_general[i-Q2CS_PLAYERSKINS] = Z_StrDup(s);
}
else if (i >= Q2CS_PLAYERSKINS && i < Q2CS_PLAYERSKINS+Q2MAX_CLIENTS)
{
CLQ2_ParseClientinfo (i-Q2CS_PLAYERSKINS, s);
Z_Free(cl.configstring_general[i-Q2CS_PLAYERSKINS]);
cl.configstring_general[i-Q2CS_PLAYERSKINS] = Z_StrDup(s);
}
else if (i == Q2CS_MAPCHECKSUM)
{
@ -6715,6 +6767,19 @@ void CLQ2_ParseServerMessage (void)
switch (cmd)
{
default:
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
{
switch(cmd & 0x1f)
{
case svcq2_frame: //20 (the bastard to implement.)
CLQ2_ParseFrame(cmd>>5);
break;
default:
Host_EndGame ("CLQ2_ParseServerMessage: Illegible server message (%i)", cmd);
return;
}
break;
}
Host_EndGame ("CLQ2_ParseServerMessage: Illegible server message (%i)", cmd);
return;
@ -6750,10 +6815,16 @@ void CLQ2_ParseServerMessage (void)
else
Host_EndGame ("Server disconnected");
return;
case svcq2_reconnect: //8
case svcq2_reconnect: //8. this is actually kinda weird to have
Con_TPrintf ("reconnecting...\n");
#if 1
CL_Disconnect();
CL_BeginServerReconnect();
return;
#else
CL_SendClientCommand(true, "new");
break;
#endif
case svcq2_sound: //9 // <see code>
CLQ2_ParseStartSoundPacket();
break;
@ -6804,7 +6875,7 @@ void CLQ2_ParseServerMessage (void)
Host_EndGame ("CL_ParseServerMessage: svcq2_deltapacketentities not as part of svcq2_frame");
return;
case svcq2_frame: //20 (the bastard to implement.)
CLQ2_ParseFrame();
CLQ2_ParseFrame(0);
break;
}
}

View file

@ -130,9 +130,18 @@ void CLQ2_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t en
}
else
{ // encoded bbox
x = 8*(ent->solid & 31);
zd = 8*((ent->solid>>5) & 31);
zu = 8*((ent->solid>>10) & 63) - 32;
if (cls.netchan.netprim.q2flags & NPQ2_SIZE32)
{
x = ent->solid & 255;
zd = (ent->solid >> 8) & 255;
zu = ((ent->solid >> 16) & 65535) - 32768;
}
else
{
x = 8*(ent->solid & 31);
zd = 8*((ent->solid>>5) & 31);
zu = 8*((ent->solid>>10) & 63) - 32;
}
bmins[0] = bmins[1] = -x;
bmaxs[0] = bmaxs[1] = x;

View file

@ -2562,8 +2562,7 @@ void CLQ2_ParseTEnt (void)
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
//FIXME: should use q2's vertical puff thing
P_RunParticleEffect (pos, dir, color, cnt);
P_RunParticleEffectPalette("q2part.TEQ2_LASER_SPARKS", pos, dir, color, cnt);
break;
/*
@ -3660,15 +3659,29 @@ void CL_UpdateExplosions (void)
for (i=0, ex=cl_explosions; i < explosions_running; i++, ex++)
{
if (!ex->model && !ex->flags)
if (!ex->model && !(ex->flags&Q2RF_BEAM))
continue;
lastrunningexplosion = i;
if (ex->model->loadstate == MLS_LOADING)
continue;
if (ex->model->loadstate != MLS_LOADED)
{
ex->model = NULL;
ex->flags = 0;
P_DelinkTrailstate(&(ex->trailstate));
continue;
}
f = ex->framerate*(cl.time - ex->start);
if (ex->firstframe >= 0)
{
firstframe = ex->firstframe;
numframes = ex->numframes;
if (!numframes)
numframes = ex->model->numframes - firstframe;
}
else
{

View file

@ -470,8 +470,6 @@ typedef struct
char servername[MAX_OSPATH]; // name of server from original connect
int qport;
struct ftenet_connections_s *sockets;
qdownload_t *download;
@ -797,6 +795,7 @@ typedef struct
char sound_name[MAX_PRECACHE_SOUNDS][MAX_QPATH];
char *particle_ssname[MAX_SSPARTICLESPRE];
#ifdef Q2CLIENT
char *configstring_general[Q2MAX_CLIENTS|Q2MAX_GENERAL];
char *image_name[Q2MAX_IMAGES];
char *item_name[Q2MAX_ITEMS];
short inventory[Q2MAX_ITEMS];
@ -1288,7 +1287,7 @@ qboolean CL_MayLerp(void);
#ifdef Q3CLIENT
void VARGS CLQ3_SendClientCommand(const char *fmt, ...) LIKEPRINTF(1);
void CLQ3_SendAuthPacket(netadr_t *gameserver);
void CLQ3_SendConnectPacket(netadr_t *to);
void CLQ3_SendConnectPacket(netadr_t *to, int challenge, int qport);
void CLQ3_SendCmd(usercmd_t *cmd);
qboolean CLQ3_Netchan_Process(void);
void CLQ3_ParseServerMessage (void);
@ -1475,7 +1474,7 @@ void CLQ2_ParseTEnt (void);
void CLQ2_AddEntities (void);
void CLQ2_ParseBaseline (void);
void CLQ2_ClearParticleState(void);
void CLQ2_ParseFrame (void);
void CLQ2_ParseFrame (int extrabits);
void CLQ2_RunMuzzleFlash2 (int ent, int flash_number);
int CLQ2_RegisterTEntModels (void);
#endif

View file

@ -708,13 +708,25 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
to->origin[1] = MSG_ReadCoord ();
if (bits & Q2U_ORIGIN3)
to->origin[2] = MSG_ReadCoord ();
if (bits & Q2U_ANGLE1)
to->angles[0] = MSG_ReadAngle();
if (bits & Q2U_ANGLE2)
to->angles[1] = MSG_ReadAngle();
if (bits & Q2U_ANGLE3)
to->angles[2] = MSG_ReadAngle();
if ((bits & Q2UX_ANGLE16) && (net_message.prim.q2flags & NPQ2_ANG16))
{
if (bits & Q2U_ANGLE1)
to->angles[0] = MSG_ReadAngle16();
if (bits & Q2U_ANGLE2)
to->angles[1] = MSG_ReadAngle16();
if (bits & Q2U_ANGLE3)
to->angles[2] = MSG_ReadAngle16();
}
else
{
if (bits & Q2U_ANGLE1)
to->angles[0] = MSG_ReadAngle();
if (bits & Q2U_ANGLE2)
to->angles[1] = MSG_ReadAngle();
if (bits & Q2U_ANGLE3)
to->angles[2] = MSG_ReadAngle();
}
if (bits & Q2U_OLDORIGIN)
MSG_ReadPos (to->u.q2.old_origin);
@ -728,7 +740,12 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
to->u.q2.event = 0;
if (bits & Q2U_SOLID)
to->solid = MSG_ReadShort ();
{
if (net_message.prim.q2flags & NPQ2_SIZE32)
to->solid = MSG_ReadLong();
else
to->solid = MSG_ReadShort ();
}
}
void CLQ2_ClearParticleState(void)
@ -956,7 +973,7 @@ void CLQ2_ParseBaseline (void)
CL_ParsePlayerstate
===================
*/
void CLQ2_ParsePlayerstate (q2frame_t *oldframe, q2frame_t *newframe)
void CLQ2_ParsePlayerstate (q2frame_t *oldframe, q2frame_t *newframe, int extflags)
{
int flags;
q2player_state_t *state;
@ -983,15 +1000,21 @@ void CLQ2_ParsePlayerstate (q2frame_t *oldframe, q2frame_t *newframe)
{
state->pmove.origin[0] = MSG_ReadShort ();
state->pmove.origin[1] = MSG_ReadShort ();
state->pmove.origin[2] = MSG_ReadShort ();
if (extflags & Q2PSX_OLD)
state->pmove.origin[2] = MSG_ReadShort ();
}
if (extflags & Q2PSX_M_ORIGIN2)
state->pmove.origin[2] = MSG_ReadShort ();
if (flags & Q2PS_M_VELOCITY)
{
state->pmove.velocity[0] = MSG_ReadShort ();
state->pmove.velocity[1] = MSG_ReadShort ();
state->pmove.velocity[2] = MSG_ReadShort ();
if (extflags & Q2PSX_OLD)
state->pmove.velocity[2] = MSG_ReadShort ();
}
if (extflags & Q2PSX_M_VELOCITY2)
state->pmove.velocity[2] = MSG_ReadShort ();
if (flags & Q2PS_M_TIME)
state->pmove.pm_time = MSG_ReadByte ();
@ -1026,8 +1049,11 @@ void CLQ2_ParsePlayerstate (q2frame_t *oldframe, q2frame_t *newframe)
{
state->viewangles[0] = MSG_ReadAngle16 ();
state->viewangles[1] = MSG_ReadAngle16 ();
state->viewangles[2] = MSG_ReadAngle16 ();
if (extflags & Q2PSX_OLD)
state->viewangles[2] = MSG_ReadAngle16 ();
}
if (extflags & Q2PSX_VIEWANGLE2)
state->viewangles[2] = MSG_ReadAngle16 ();
if (flags & Q2PS_KICKANGLES)
{
@ -1044,9 +1070,24 @@ void CLQ2_ParsePlayerstate (q2frame_t *oldframe, q2frame_t *newframe)
if (flags & Q2PS_WEAPONFRAME)
{
state->gunframe = MSG_ReadByte ();
if (extflags & Q2PSX_OLD)
{
state->gunoffset[0] = MSG_ReadChar ()*0.25;
state->gunoffset[1] = MSG_ReadChar ()*0.25;
state->gunoffset[2] = MSG_ReadChar ()*0.25;
state->gunangles[0] = MSG_ReadChar ()*0.25;
state->gunangles[1] = MSG_ReadChar ()*0.25;
state->gunangles[2] = MSG_ReadChar ()*0.25;
}
}
if (extflags & Q2PSX_GUNOFFSET)
{
state->gunoffset[0] = MSG_ReadChar ()*0.25;
state->gunoffset[1] = MSG_ReadChar ()*0.25;
state->gunoffset[2] = MSG_ReadChar ()*0.25;
}
if (extflags & Q2PSX_GUNANGLES)
{
state->gunangles[0] = MSG_ReadChar ()*0.25;
state->gunangles[1] = MSG_ReadChar ()*0.25;
state->gunangles[2] = MSG_ReadChar ()*0.25;
@ -1067,10 +1108,19 @@ void CLQ2_ParsePlayerstate (q2frame_t *oldframe, q2frame_t *newframe)
state->rdflags = MSG_ReadByte ();
// parse stats
statbits = MSG_ReadLong ();
for (i=0 ; i<Q2MAX_STATS ; i++)
if (statbits & (1<<i) )
state->stats[i] = MSG_ReadShort();
if (extflags & (Q2PSX_OLD|Q2PSX_STATS))
statbits = MSG_ReadLong ();
else
statbits = 0;
if (statbits)
{
for (i=0 ; i<Q2MAX_STATS ; i++)
if (statbits & (1<<i) )
state->stats[i] = MSG_ReadShort();
}
if (extflags & Q2PSX_CLIENTNUM)
/*state->viewent =*/ MSG_ReadByte();
}
@ -1104,12 +1154,12 @@ void CLQ2_FireEntityEvents (q2frame_t *frame)
CL_ParseFrame
================
*/
void CLQ2_ParseFrame (void)
void CLQ2_ParseFrame (int extrabits)
{
int cmd;
int len;
q2frame_t *old;
int i,j;
int i,j, chokecount;
memset (&cl.q2frame, 0, sizeof(cl.q2frame));
@ -1117,8 +1167,31 @@ void CLQ2_ParseFrame (void)
CLQ2_ClearProjectiles(); // clear projectiles for new frame
#endif
cl.q2frame.serverframe = MSG_ReadLong ();
cl.q2frame.deltaframe = MSG_ReadLong ();
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
{
unsigned int bits = MSG_ReadLong();
cl.q2frame.serverframe = bits & 0x07ffffff;
i = bits >> 27;
if (i == 31)
cl.q2frame.deltaframe = -1;
else
cl.q2frame.deltaframe = cl.q2frame.serverframe - i;
bits = MSG_ReadByte();
chokecount = bits & 0xf;
extrabits = (extrabits<<4) | (bits>>4);
}
else
{
cl.q2frame.serverframe = MSG_ReadLong ();
cl.q2frame.deltaframe = MSG_ReadLong ();
if (cls.protocol_q2 > 26)
chokecount = MSG_ReadByte ();
else
chokecount = 0;
extrabits = Q2PSX_OLD;
}
cl.q2frame.servertime = cl.q2frame.serverframe*100;
cl.oldgametime = cl.gametime;
@ -1126,12 +1199,8 @@ void CLQ2_ParseFrame (void)
cl.gametime = cl.q2frame.servertime/1000.f;
cl.gametimemark = realtime;
if (cls.protocol_q2 > 26)
{
i = MSG_ReadByte ();
for (j=0 ; j<i ; j++)
cl.outframes[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].latency = -2;
}
for (j=0 ; j<chokecount ; j++)
cl.outframes[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].latency = -2;
if (cl_shownet.value == 3)
Con_Printf (" frame:%i delta:%i\n", cl.q2frame.serverframe, cl.q2frame.deltaframe);
@ -1179,17 +1248,23 @@ void CLQ2_ParseFrame (void)
MSG_ReadData (&cl.q2frame.areabits, len);
// read playerinfo
cmd = MSG_ReadByte ();
// SHOWNET(svc_strings[cmd]);
if (cmd != svcq2_playerinfo)
Host_EndGame ("CL_ParseFrame: not playerinfo");
CLQ2_ParsePlayerstate (old, &cl.q2frame);
if (cls.protocol_q2 != PROTOCOL_VERSION_R1Q2 && cls.protocol_q2 != PROTOCOL_VERSION_Q2PRO)
{
cmd = MSG_ReadByte ();
// SHOWNET(svc_strings[cmd]);
if (cmd != svcq2_playerinfo)
Host_EndGame ("CL_ParseFrame: not playerinfo");
}
CLQ2_ParsePlayerstate (old, &cl.q2frame, extrabits);
// read packet entities
cmd = MSG_ReadByte ();
if (cls.protocol_q2 != PROTOCOL_VERSION_R1Q2 && cls.protocol_q2 != PROTOCOL_VERSION_Q2PRO)
{
cmd = MSG_ReadByte ();
// SHOWNET(svc_strings[cmd]);
if (cmd != svcq2_packetentities)
Host_EndGame ("CL_ParseFrame: not packetentities");
if (cmd != svcq2_packetentities)
Host_EndGame ("CL_ParseFrame: not packetentities");
}
CLQ2_ParsePacketEntities (old, &cl.q2frame);
// save the frame off in the backup array for later delta comparisons
@ -1742,8 +1817,10 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
if (effects & Q2EF_TRACKER) // lame... problematic?
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL2], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xd0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0, 0.2, 0);
V_AddLight (ent.keynum, ent.origin, 200, 0, 0.2, 0);
}
}
else
{

View file

@ -1042,7 +1042,7 @@ void CLQ3_SendAuthPacket(netadr_t *gameserver)
}
}
void CLQ3_SendConnectPacket(netadr_t *to)
void CLQ3_SendConnectPacket(netadr_t *to, int challenge, int qport)
{
char data[2048];
char adrbuf[MAX_ADR_SIZE];
@ -1056,7 +1056,7 @@ void CLQ3_SendConnectPacket(netadr_t *to)
msg.overflowed = msg.allowoverflow = 0;
msg.maxsize = sizeof(data);
MSG_WriteLong(&msg, -1);
MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", cls.challenge, cls.qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), &net_local_cl_ipadr), cls.userinfo[0]));
MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", challenge, qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), &net_local_cl_ipadr), cls.userinfo[0]));
#ifdef HUFFNETWORK
Huff_EncryptPacket(&msg, 12);
if (!Huff_CompressionCRC(HUFFCRC_QUAKE3))

View file

@ -3616,7 +3616,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
rgbadata = BZ_Malloc(imgwidth * imgheight*4);
for (i = 0, valid = false; i < imgwidth * imgheight; i++)
{
if (((qbyte*)rawdata)[i] < 256-vid.fullbright)
if (((qbyte*)rawdata)[i] == 255 || ((qbyte*)rawdata)[i] < 256-vid.fullbright)
rgbadata[i] = 0;
else
{

View file

@ -1110,7 +1110,10 @@ static void PClassic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int c
{
Classic_RunParticleEffect(org, dir, color, count);
}
static void PClassic_RunParticleEffectPalette (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count)
{
Classic_RunParticleEffect(org, dir, color, count);
}
particleengine_t pe_classic =
{
@ -1129,6 +1132,7 @@ particleengine_t pe_classic =
PClassic_RunParticleEffect2,
PClassic_RunParticleEffect3,
PClassic_RunParticleEffect4,
PClassic_RunParticleEffectPalette,
PClassic_ParticleTrailIndex,
PClassic_EmitSkyEffectTris,

View file

@ -20,6 +20,7 @@ static void PNULL_RunParticleEffect (vec3_t org, vec3_t dir, int color, int coun
static void PNULL_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count){}
static void PNULL_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int effect, int count){}
static void PNULL_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count){}
static void PNULL_RunParticleEffectPalette (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count){}
static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk){}
static void PNULL_EmitSkyEffectTris(model_t *mod, msurface_t *fa, int ptype){}
@ -65,6 +66,7 @@ particleengine_t pe_null =
PNULL_RunParticleEffect2,
PNULL_RunParticleEffect3,
PNULL_RunParticleEffect4,
PNULL_RunParticleEffectPalette,
PNULL_ParticleTrailIndex,
PNULL_EmitSkyEffectTris,

File diff suppressed because it is too large Load diff

View file

@ -4593,24 +4593,24 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s *
G_FLOAT(OFS_RETURN) = es->skinnum;
break;
case GE_MINS:
G_FLOAT(OFS_RETURN+0) = -(es->solid & 31);
G_FLOAT(OFS_RETURN+1) = -(es->solid & 31);
G_FLOAT(OFS_RETURN+2) = -((es->solid>>5) & 31);
G_FLOAT(OFS_RETURN+0) = -(int)(es->solid & 31);
G_FLOAT(OFS_RETURN+1) = -(int)(es->solid & 31);
G_FLOAT(OFS_RETURN+2) = -(int)((es->solid>>5) & 31);
break;
case GE_MAXS:
G_FLOAT(OFS_RETURN+0) = (es->solid & 31);
G_FLOAT(OFS_RETURN+1) = (es->solid & 31);
G_FLOAT(OFS_RETURN+1) = ((es->solid>>10) & 63) - 32;
G_FLOAT(OFS_RETURN+2) = ((es->solid>>10) & 63) - 32;
break;
case GE_ABSMIN:
G_FLOAT(OFS_RETURN+0) = le->origin[0] + -(es->solid & 31);
G_FLOAT(OFS_RETURN+1) = le->origin[1] + -(es->solid & 31);
G_FLOAT(OFS_RETURN+2) = le->origin[2] + -((es->solid>>5) & 31);
G_FLOAT(OFS_RETURN+0) = le->origin[0] + -(int)(es->solid & 31);
G_FLOAT(OFS_RETURN+1) = le->origin[1] + -(int)(es->solid & 31);
G_FLOAT(OFS_RETURN+2) = le->origin[2] + -(int)((es->solid>>5) & 31);
break;
case GE_ABSMAX:
G_FLOAT(OFS_RETURN+0) = le->origin[0] + (es->solid & 31);
G_FLOAT(OFS_RETURN+1) = le->origin[1] + (es->solid & 31);
G_FLOAT(OFS_RETURN+1) = le->origin[2] + ((es->solid>>10) & 63) - 32;
G_FLOAT(OFS_RETURN+2) = le->origin[2] + ((es->solid>>10) & 63) - 32;
break;
case GE_ORIGINANDVECTORS:
VectorCopy(le->origin, G_VECTOR(OFS_RETURN));
@ -5408,7 +5408,7 @@ static struct {
{"setmodelindex", PF_cs_SetModelIndex, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
{"modelnameforindex", PF_cs_ModelnameForIndex, 334}, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
{"particleeffectnum", PF_cs_particleeffectnum, 335}, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
{"particleeffectnum", PF_cs_particleeffectnum, 335}, // #335 float(string effectname) particleeffectnum (EXT_CSQC)
{"trailparticles", PF_cs_trailparticles, 336}, // #336 void(float effectnum, entity ent, vector start, vector end) trailparticles (EXT_CSQC),
{"trailparticles_dp", PF_cs_trailparticles, 336}, // #336 DP sucks
{"pointparticles", PF_cs_pointparticles, 337}, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)

View file

@ -83,7 +83,7 @@ void QCBUILTIN PF_CL_drawresetcliparea (pubprogfuncs_t *prinst, struct globalvar
G_FLOAT(OFS_RETURN) = 1;
}
#define FONT_SLOTS 16
#define FONT_SLOTS 32
#define FONT_SIZES 16
struct {
unsigned int owner; //kdm_foo. whoever has an interest in this font. font is purged when this becomes 0.
@ -153,6 +153,17 @@ int PR_findnamedfont(const char *name, qboolean isslotname)
}
return -1;
}
int PR_findunusedfont(void)
{
int i;
//don't find slot 0.
for (i = FONT_SLOTS; i-- > 1; )
{
if (!*fontslot[i].slotname && !*fontslot[i].facename)
return i;
}
return -1;
}
//purgeowner is the bitmask of owners that are getting freed.
//if purgeowner is 0, fonts will get purged
void PR_ReleaseFonts(unsigned int purgeowner)
@ -232,7 +243,7 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
else if (slotnum < 0)
slotnum = PR_findnamedfont(facename, false);
if (slotnum < 0)
slotnum = PR_findnamedfont("", true);
slotnum = PR_findunusedfont();
if (slotnum < 0)
return; //eep.

View file

@ -3442,6 +3442,21 @@ char *particle_set_q2part =
"scalefactor 0.8\n"
"}\n"
"r_part TEQ2_LASER_SPARKS\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part te_splashsparks\n"
"{\n"
"texture \"classicparticle\"\n"
@ -3692,7 +3707,7 @@ char *particle_set_q2part =
"lightradius 150\n"
"lightradiusfade 400\n"
"lightrgb 1 1 0\n"
"lightshadows 0\n"
"lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part teq2_blaster2\n"
@ -3714,7 +3729,7 @@ char *particle_set_q2part =
"lightradius 150\n"
"lightradiusfade 400\n"
"lightrgb 0.05 1.0 0.05\n"
"lightshadows 0\n"
"lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part TR_BLASTERTRAIL\n"
@ -3729,6 +3744,10 @@ char *particle_set_q2part =
"randomvel 5\n"
"die 0.3 0.5\n"
"colorindex 0xe0\n"
"lightradius 200\n"
"lightradiusfade 400\n"
"lightrgb 1.0 1.0 0.0\n"
"lightshadows 1\n"
"}\n"
//green version
@ -3744,6 +3763,10 @@ char *particle_set_q2part =
"randomvel 5\n"
"die 0.3 0.5\n"
"colorindex 0xd0\n"
"lightradius 200\n"
"lightradiusfade 400\n"
"lightrgb 0.0 1.0 0.0\n"
"lightshadows 1\n"
"}\n"
@ -3914,12 +3937,25 @@ char *particle_set_q2part =
"}\n"
"r_part trq2_gib\n"
"{\n"
"assoc tr_gib\n"
"texture \"particles/quake\"\n"
"step 3\n"
"scale 4\n"
"die 1.0 1.4\n"
"colorindex 0xe8 7\n"
"spawnorg 1\n"
"spawnvel 5\n"
"gravity -20\n"
"}\n"
//FIXME: implement
"r_part trq2_greengib\n"
"{\n"
"assoc tr_gib\n"
"texture \"particles/quake\"\n"
"step 3\n"
"scale 4\n"
"die 1.0 1.4\n"
"colorindex 0xdb 7\n"
"spawnorg 1\n"
"spawnvel 5\n"
"gravity -20\n"
"}\n"
"r_part TR_PLASMA\n"
@ -3951,6 +3987,14 @@ char *particle_set_q2part =
"lightrgb 1.0 1.0 0.0\n"
"}\n"
//FIXME: add particles
"r_part tr_trap\n"
"{\n"
"lighttime 0\n"
"lightradius 100 200\n"
"lightrgb 1.0 0.8 0.25\n"
"}\n"
//flags do NOT use coronas, because it obscures the holding player's skin colour
"r_part tr_flag1\n"
"{\n"
@ -3989,15 +4033,6 @@ char *particle_set_q2part =
"lightrgb 0.25 0.25 1.0\n"
"}\n"
//FIXME: add particles
"r_part tr_trap\n"
"{\n"
"lighttime 0\n"
"lightradius 100 200\n"
"lightrgb 1.0 0.8 0.25\n"
"}\n"
"r_part EF_FLIES\n"
"{\n"
"texture \"classicparticle\"\n"
@ -4095,6 +4130,28 @@ char *particle_set_q2part =
"sound \"weapons/xpld_wat.wav\" 1 1 0 0\n"
"model \"sprites/s_bfg2.sp2\" framestart=0 frameend=4 alpha=0.3 transparent fullbright noshadow\n"
"}\n"
//31qu cylinder, 8-98 high
//should look like its sucked up into some thingie above
"r_part TEQ2_BOSSTPORT\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 800\n"
"scale 1\n"
"alpha 1\n"
"die 0.5 0.8\n"
"orgadd 8 -98\n"
"veladd 100 200\n"
"spawnmode circle\n"
"spawnorg 48 0\n"
"spawnvel -50 30\n"
"randomvel 32 31\n"
"gravity -800\n"
"rgbf 1 1 1\n"
"scalefactor 0.8\n"
"}\n"
;
#endif

View file

@ -2683,10 +2683,12 @@ void R_GeneratedWorldEBO(void *ctx, void *data, size_t a_, size_t b_)
webogeneratingstate = 0;
mod = webostate->wmodel;
GL_DeselectVAO();
qglGenBuffersARB(1, &webostate->ebo);
for (i = 0, idxcount = 0; i < webostate->numbatches; i++)
idxcount += webostate->batches[i].numidx;
qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, webostate->ebo);
GL_SelectEBO(webostate->ebo);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, idxcount*sizeof(index_t), NULL, GL_STATIC_DRAW_ARB);
for (i = 0, idxcount = 0; i < webostate->numbatches; i++)
{
@ -2755,7 +2757,7 @@ static void Surf_SimpleWorld(struct webostate_s *es, qbyte *pvs)
{
//FIXME: pre-allocate
// continue;
eb->maxidx = eb->numidx + surf->mesh->numindexes;
eb->maxidx = eb->numidx + surf->mesh->numindexes + 512;
eb->idxbuffer = BZ_Realloc(eb->idxbuffer, eb->maxidx * sizeof(index_t));
}
for (i = 0; i < mesh->numindexes; i++)

View file

@ -1025,7 +1025,7 @@ void D3DSucks(void)
Sys_Error("Failed to reload content after mode switch\n");
}
void R_ShutdownRenderer(qboolean videotoo)
void R_ShutdownRenderer(qboolean devicetoo)
{
//make sure the worker isn't still loading stuff
COM_WorkerFullSync();
@ -1048,7 +1048,7 @@ void R_ShutdownRenderer(qboolean videotoo)
if (Draw_Shutdown)
Draw_Shutdown();
if (VID_DeInit && videotoo)
if (VID_DeInit && devicetoo)
{
TRACE(("dbg: R_ApplyRenderer: VID_DeInit\n"));
VID_DeInit();
@ -1070,7 +1070,10 @@ void R_ShutdownRenderer(qboolean videotoo)
RQ_Shutdown();
S_Shutdown(false);
if (devicetoo)
S_Shutdown(false);
else
S_StopAllSounds (true);
}
void R_GenPaletteLookup(void)
@ -1363,7 +1366,7 @@ TRACE(("dbg: R_ApplyRenderer: starting on client state\n"));
TRACE(("dbg: R_ApplyRenderer: S_Restart_f\n"));
if (!isDedicated)
S_DoRestart();
S_DoRestart(true);
#ifdef Q3SERVER
if (svs.gametype == GT_QUAKE3)

View file

@ -335,6 +335,8 @@ char *Get_Q2ConfigString(int i)
return cl.item_name[i-Q2CS_ITEMS]?cl.item_name[i-Q2CS_ITEMS]:"";
if (i == Q2CS_STATUSBAR)
return cl.q2statusbar;
if (i == Q2CS_NAME)
return cl.levelname;
if (i >= Q2CS_MODELS && i < Q2CS_MODELS + Q2MAX_MODELS)
return cl.model_name [i-Q2CS_MODELS];
@ -342,6 +344,8 @@ char *Get_Q2ConfigString(int i)
return cl.model_name [i-Q2CS_SOUNDS];
if (i == Q2CS_AIRACCEL)
return "4";
if (i >= Q2CS_PLAYERSKINS && i < Q2CS_GENERAL+Q2MAX_GENERAL)
return cl.configstring_general[i-Q2CS_PLAYERSKINS]?cl.configstring_general[i-Q2CS_PLAYERSKINS]:"";
//#define Q2CS_LIGHTS (Q2CS_IMAGES +Q2MAX_IMAGES)
//#define Q2CS_ITEMS (Q2CS_LIGHTS +Q2MAX_LIGHTSTYLES)
//#define Q2CS_PLAYERSKINS (Q2CS_ITEMS +Q2MAX_ITEMS)
@ -763,6 +767,10 @@ void Sbar_ShowScores (void)
void Sbar_Hexen2InvLeft_f(void)
{
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invprev");
@ -786,6 +794,10 @@ void Sbar_Hexen2InvLeft_f(void)
}
void Sbar_Hexen2InvRight_f(void)
{
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invnext");
@ -809,6 +821,11 @@ void Sbar_Hexen2InvRight_f(void)
}
void Sbar_Hexen2InvUse_f(void)
{
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
if (cls.protocol == CP_QUAKE2)
{
CL_SendClientCommand(true, "invuse");
@ -823,21 +840,37 @@ void Sbar_Hexen2InvUse_f(void)
void Sbar_Hexen2ShowInfo_f(void)
{
playerview_t *pv = &cl.playerview[CL_TargettedSplit(false)];
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
pv->sb_hexen2_extra_info = true;
}
void Sbar_Hexen2DontShowInfo_f(void)
{
playerview_t *pv = &cl.playerview[CL_TargettedSplit(false)];
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
pv->sb_hexen2_extra_info = false;
}
void Sbar_Hexen2PInfoPlaque_f(void)
{
playerview_t *pv = &cl.playerview[CL_TargettedSplit(false)];
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
pv->sb_hexen2_infoplaque = true;
}
void Sbar_Hexen2MInfoPlaque_f(void)
{
playerview_t *pv = &cl.playerview[CL_TargettedSplit(false)];
#ifdef CSQC_DAT
if (CSQC_ConsoleCommand(Cmd_Argv(0)))
return;
#endif
pv->sb_hexen2_infoplaque = false;
}
@ -2326,7 +2359,7 @@ static void Sbar_Hexen2DrawExtra (playerview_t *pv)
pclass = cl.players[pv->playernum].h2playerclass;
if (pclass >= sizeof(pclassname)/sizeof(pclassname[0]))
pclass = sizeof(pclassname)/sizeof(pclassname[0]) - 1;
pclass = 0;
//adjust it so there's space

View file

@ -1785,9 +1785,11 @@ void S_Startup (void)
//why isn't this part of S_Restart_f anymore?
//so that the video code can call it directly without flushing the models it's just loaded.
void S_DoRestart (void)
void S_DoRestart (qboolean onlyifneeded)
{
int i;
if (onlyifneeded && sound_started)
return; //don't need to if its already running.
S_StopAllSounds (true);
S_Shutdown(false);
@ -1810,7 +1812,7 @@ void S_DoRestart (void)
void S_Restart_f (void)
{
S_DoRestart();
S_DoRestart(false);
}
void S_Control_f (void)
@ -2114,7 +2116,14 @@ void S_Purge(qboolean retaintouched)
sfx = &known_sfx[i];
/*don't hurt sounds if they're being processed by a worker thread*/
if (sfx->loadstate == SLS_LOADING)
continue;
{
if (retaintouched)
continue; //don't bother waiting
//trying to shut down or something.
//make sure there's no worker about to write to sfx after the memory is freed
COM_WorkerPartialSync(sfx, &sfx->loadstate, SLS_LOADING);
}
/*don't purge the file if its still relevent*/
if (retaintouched && sfx->touched)

View file

@ -890,7 +890,6 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
{
if (AudioInputPlugins[i](s, data, filesize, snd_speed))
{
s->loadstate = SLS_LOADED;
//wake up the main thread in case it decided to wait for us.
COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_LOADED, 0);
BZ_Free(data);

View file

@ -194,7 +194,7 @@ void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch);
void SND_ResampleStream (void *in, int inrate, int inwidth, int inchannels, int insamps, void *out, int outrate, int outwidth, int outchannels, int resampstyle);
// restart entire sound subsystem (doesn't flush old sounds, so make sure that happens)
void S_DoRestart (void);
void S_DoRestart (qboolean onlyifneeded);
void S_Restart_f (void);

View file

@ -786,7 +786,7 @@ STAT_H2_CNT_INVINCIBILITY, // changes stat bar
STAT_H2_ARTIFACT_ACTIVE,
STAT_H2_ARTIFACT_LOW,
STAT_H2_MOVETYPE,
STAT_H2_CAMERAMODE,
STAT_H2_CAMERAMODE, //entity
STAT_H2_HASTED,
STAT_H2_INVENTORY,
STAT_H2_RINGS_ACTIVE,
@ -800,21 +800,21 @@ STAT_H2_FLIGHT_T,
STAT_H2_WATER_T,
STAT_H2_TURNING_T,
STAT_H2_REGEN_T,
STAT_H2_PUZZLE1,
STAT_H2_PUZZLE2,
STAT_H2_PUZZLE3,
STAT_H2_PUZZLE4,
STAT_H2_PUZZLE5,
STAT_H2_PUZZLE6,
STAT_H2_PUZZLE7,
STAT_H2_PUZZLE8,
STAT_H2_PUZZLE1, //string
STAT_H2_PUZZLE2, //string
STAT_H2_PUZZLE3, //string
STAT_H2_PUZZLE4, //string
STAT_H2_PUZZLE5, //string
STAT_H2_PUZZLE6, //string
STAT_H2_PUZZLE7, //string
STAT_H2_PUZZLE8, //string
STAT_H2_MAXHEALTH,
STAT_H2_MAXMANA,
STAT_H2_FLAGS,
STAT_H2_PLAYERCLASS,
STAT_H2_OBJECTIVE1,
STAT_H2_OBJECTIVE2,
STAT_H2_OBJECTIVE1, //integer
STAT_H2_OBJECTIVE2, //integer
STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR = 220, // DP

View file

@ -1778,6 +1778,36 @@ void Cmd_RestrictCommand_f (void)
return;
}
void Cmd_EnumerateLevel(int level, char *buf, size_t bufsize)
{
cmdalias_t *a;
cmd_function_t *cmds;
int cmdlevel;
*buf = 0;
for (cmds = cmd_functions; cmds; cmds=cmds->next)
{
cmdlevel = cmds->restriction?cmds->restriction:rcon_level.ival;
if (level == cmdlevel)
{
if (*buf)
Q_strncatz(buf, "\t", bufsize);
Q_strncatz(buf, cmds->name, bufsize);
}
}
for (a=cmd_alias ; a ; a=a->next)
{
cmdlevel = a->restriction?a->restriction:rcon_level.ival;
if (level == cmdlevel)
{
if (*buf)
Q_strncatz(buf, "\t", bufsize);
Q_strncatz(buf, cmds->name, bufsize);
}
}
}
int Cmd_Level(char *name)
{
cmdalias_t *a;
@ -1793,7 +1823,7 @@ int Cmd_Level(char *name)
{
if (!strcmp(a->name, name))
{
return a->restriction?a->restriction:Cmd_ExecLevel;
return a->restriction?a->restriction:rcon_level.ival;
}
}
return -1;

View file

@ -73,6 +73,7 @@ then searches for a command or variable that matches the first token.
typedef void (*xcommand_t) (void);
int Cmd_Level(char *name);
void Cmd_EnumerateLevel(int level, char *buf, size_t bufsize);
void Cmd_Init (void);
void Cmd_Shutdown(void);

View file

@ -108,8 +108,12 @@ typedef enum {false, true} qboolean;
struct netprim_s
{
int coordsize;
int anglesize;
qbyte coordsize;
qbyte anglesize;
#define NPQ2_ANG16 (1<<0)
#define NPQ2_SIZE32 (1<<0)
qbyte q2flags;
qbyte pad;
};
//============================================================================

View file

@ -2631,7 +2631,7 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
FS_ChangeGame(man, cfg_reload_on_gamedir.ival, false);
}
#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n"
#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\nsv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n"
/*stuff that makes dp-only mods work a bit better*/
#define DPCOMPAT QCFG "set _cl_playermodel \"\"\n set dpcompat_set 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
/*nexuiz/xonotic has a few quirks/annoyances...*/

View file

@ -83,6 +83,7 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s)
mvertex_t *v;
mtexinfo_t *tex;
int bmins[2], bmaxs[2];
int idx;
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
@ -92,10 +93,13 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s)
for (i=0 ; i<s->numedges ; i++)
{
e = mod->surfedges[s->firstedge+i];
if (e >= 0)
v = &mod->vertexes[mod->edges[e].v[0]];
idx = e < 0;
if (idx)
e = -e;
if (e < 0 || e >= mod->numedges)
v = &mod->vertexes[0];
else
v = &mod->vertexes[mod->edges[-e].v[1]];
v = &mod->vertexes[mod->edges[e].v[idx]];
for (j=0 ; j<2 ; j++)
{

View file

@ -167,6 +167,7 @@ typedef struct
netadr_t remote_address;
netsrc_t sock;
int qport;
int qportsize;
// bandwidth estimator
double cleartime; // if realtime > nc->cleartime, free to go

View file

@ -342,6 +342,8 @@ void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t *adr, int qport)
chan->message.maxsize = MAX_QWMSGLEN;
chan->qport = qport;
chan->qportsize = 2;
}
@ -701,7 +703,12 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
// send the qport if we are a client
#ifndef SERVERONLY
if (chan->sock == NS_CLIENT)
MSG_WriteShort (&send, cls.qport);
{
if (chan->qportsize == 2)
MSG_WriteShort (&send, chan->qport);
else if (chan->qportsize == 1)
MSG_WriteByte (&send, chan->qport&0xff);
}
#endif
if (chan->fragmentsize)
@ -742,7 +749,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
if (!cls.demoplayback)
#endif
{
int hsz = 10 + ((chan->sock == NS_CLIENT)?2:0); /*header size, if fragmentation is in use*/
int hsz = 10 + ((chan->sock == NS_CLIENT)?chan->qportsize:0); /*header size, if fragmentation is in use*/
if ((!chan->fragmentsize) || send.cursize-hsz < ((chan->fragmentsize - hsz)&~7))
{
@ -778,7 +785,12 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
*(int*)&send.data[(offset) + 4] = LittleLong(w2);
#ifndef SERVERONLY
if (chan->sock == NS_CLIENT)
*(short*)&send.data[offset + hsz-4] = LittleShort(cls.qport);
{
if (chan->qportsize == 2)
*(short*)&send.data[offset + hsz-4] = LittleShort(chan->qport);
else if (chan->qportsize == 1)
*(qbyte*)&send.data[offset + hsz-3] = chan->qport&0xff;
}
#endif
*(short*)&send.data[offset + hsz-2] = LittleShort((offset>>2) | (more?1:0));

View file

@ -2089,60 +2089,86 @@ static qboolean FTENET_AddToCollection_Ptr(ftenet_connections_t *col, const char
}
return count > 0;
}
qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, const char *address, netadrtype_t addrtype, qboolean islisten)
qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, const char *addresslist, netadrtype_t addrtype, qboolean islisten)
{
ftenet_generic_connection_t *(*establish)(qboolean isserver, const char *address, netadr_t adr) = NULL;
netadr_t adr;
netadr_t adr[8];
ftenet_generic_connection_t *(*establish[countof(adr)])(qboolean isserver, const char *address, netadr_t adr);
char address[countof(adr)][256];
unsigned int i, j;
qboolean success;
//resolve the address to something sane so we can determine the address type and thus the connection type to use
if (!address || !*address)
adr.type = NA_INVALID;
else if (islisten)
NET_PortToAdr(addrtype, address, &adr);
else
NET_StringToAdr(address, 0, &adr);
if (strchr(name, ':'))
return false;
switch(adr.type)
for (i = 0; addresslist && *addresslist && i < countof(adr); i++)
{
default: establish = NULL; break;
addresslist = COM_ParseStringSet(addresslist, address[i], sizeof(address[i]));
//resolve the address to something sane so we can determine the address type and thus the connection type to use
if (!*address[i])
adr[i].type = NA_INVALID;
else if (islisten)
NET_PortToAdr(addrtype, address[i], &adr[i]);
else
NET_StringToAdr(address[i], 0, &adr[i]);
switch(adr[i].type)
{
default: establish[i] = NULL; break;
#ifdef HAVE_NATPMP
case NA_NATPMP: establish = FTENET_NATPMP_EstablishConnection; break;
case NA_NATPMP: establish[i] = FTENET_NATPMP_EstablishConnection; break;
#endif
#if !defined(CLIENTONLY) && !defined(SERVERONLY)
case NA_LOOPBACK: establish = FTENET_Loop_EstablishConnection; break;
case NA_LOOPBACK: establish[i] = FTENET_Loop_EstablishConnection; break;
#endif
#ifdef HAVE_IPV4
case NA_IP: establish = FTENET_UDP4_EstablishConnection; break;
case NA_IP: establish[i] = FTENET_UDP4_EstablishConnection; break;
#endif
#ifdef IPPROTO_IPV6
case NA_IPV6: establish = FTENET_UDP6_EstablishConnection; break;
case NA_IPV6: establish[i] = FTENET_UDP6_EstablishConnection; break;
#endif
#ifdef USEIPX
case NA_IPX: establish = FTENET_IPX_EstablishConnection; break;
case NA_IPX: establish[i] = FTENET_IPX_EstablishConnection; break;
#endif
case NA_WEBSOCKET:
case NA_WEBSOCKET:
#ifdef HAVE_WEBSOCKCL
if (!islisten)
establish = FTENET_WebSocket_EstablishConnection;
if (!islisten)
establish[i] = FTENET_WebSocket_EstablishConnection;
#endif
#ifdef TCPCONNECT
establish = FTENET_TCP4Connect_EstablishConnection;
establish[i] = FTENET_TCP4Connect_EstablishConnection;
#endif
break;
break;
#ifdef IRCCONNECT
case NA_IRC: establish = FTENET_IRCConnect_EstablishConnection; break;
case NA_IRC: establish[i] = FTENET_IRCConnect_EstablishConnection; break;
#endif
#ifdef TCPCONNECT
case NA_TCP: establish = FTENET_TCP4Connect_EstablishConnection; break;
case NA_TLSV4: establish = FTENET_TLS4Connect_EstablishConnection; break;
case NA_TCP: establish[i] = FTENET_TCP4Connect_EstablishConnection; break;
case NA_TLSV4: establish[i] = FTENET_TLS4Connect_EstablishConnection; break;
#endif
#if defined(TCPCONNECT) && defined(IPPROTO_IPV6)
case NA_TCPV6: establish = FTENET_TCP6Connect_EstablishConnection; break;
case NA_TLSV6: establish = FTENET_TLS6Connect_EstablishConnection; break;
case NA_TCPV6: establish[i] = FTENET_TCP6Connect_EstablishConnection; break;
case NA_TLSV6: establish[i] = FTENET_TLS6Connect_EstablishConnection; break;
#endif
}
}
return FTENET_AddToCollection_Ptr(col, name, establish, islisten, address, &adr);
if (i == 1)
{
success |= FTENET_AddToCollection_Ptr(col, name, establish[0], islisten, address[0], &adr[0]);
i = 0;
}
else
success |= FTENET_AddToCollection_Ptr(col, name, NULL, islisten, NULL, NULL);
for (j = 0; j < i; j++)
{
success |= FTENET_AddToCollection_Ptr(col, va("%s:%i", name, j), establish[j], islisten, address[j], &adr[j]);
}
for (; j < countof(adr); j++)
{
success |= FTENET_AddToCollection_Ptr(col, va("%s:%i", name, j), NULL, islisten, NULL, NULL);
}
return success;
}
void FTENET_CloseCollection(ftenet_connections_t *col)
@ -2589,7 +2615,11 @@ qboolean NET_PortToAdr (int adrfamily, const char *s, netadr_t *a)
char *e;
if (net_enabled.ival || adrfamily == NA_LOOPBACK)
{
int port = strtoul(s, &e, 10);
int port;
if (!strncmp(s, "natpmp:", 7))
return NET_StringToAdr2(s, 0, a, 1);
port = strtoul(s, &e, 10);
if (*e) //if *e then its not just a single number in there, so treat it as a proper address.
return NET_StringToAdr(s, 0, a);
else if (e != s) //if we actually read something (even a 0)

View file

@ -217,6 +217,7 @@ int P_FindParticleType(const char *efname);
#define P_RunParticleEffect2 pe->RunParticleEffect2
#define P_RunParticleEffect3 pe->RunParticleEffect3
#define P_RunParticleEffect4 pe->RunParticleEffect4
#define P_RunParticleEffectPalette pe->RunParticleEffectPalette
#define P_ParticleTrailIndex pe->ParticleTrailIndex
#define P_EmitSkyEffectTris pe->EmitSkyEffectTris
@ -241,6 +242,7 @@ typedef struct {
void (*RunParticleEffect2) (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count);
void (*RunParticleEffect3) (vec3_t org, vec3_t box, int color, int effect, int count);
void (*RunParticleEffect4) (vec3_t org, float radius, int color, int effect, int count);
void (*RunParticleEffectPalette) (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count);
void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk);
void (*EmitSkyEffectTris) (struct model_s *mod, struct msurface_s *fa, int ptype);

View file

@ -93,6 +93,7 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t
void *pr_globals = PR_globals(w->progs, PR_CURRENT);
int i;
int tmp;
float f;
*w->g.self = EDICT_TO_PROG(w->progs, portal);
//transform origin+velocity etc
@ -121,6 +122,16 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t
VectorCopy(w->g.v_right, move);
// VectorCopy(w->g.v_up, pmove.gravitydir);
//floor+floor, ish
if (DotProduct(w->g.v_up, pmove.gravitydir) < 0.7)
{
f = DotProduct(newvel, newvel);
if (f < 200*200)
{
VectorScale(newvel, 200 / sqrt(f), newvel);
}
}
//transform the angles too
VectorCopy(org, G_VECTOR(OFS_PARM0));

View file

@ -220,7 +220,7 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
VectorSubtract (end, origin, end_l);
// sweep the box through the model
if (model)
if (model && model->funcs.NativeTrace)
{
if (angles[0] || angles[1] || angles[2])
{

View file

@ -807,6 +807,8 @@ void QCBUILTIN PF_getsurfacenearpoint(pubprogfuncs_t *prinst, struct globalvars_
if (!model || model->type != mod_brush)
return;
bestdist = 256;
if (model->fromgame == fg_quake || model->fromgame == fg_quake2)
{
//all polies, we can skip parts. special case.
@ -5823,6 +5825,7 @@ lh_extension_t QSG_Extensions[] = {
// {"DP_ENT_COLORMOD"},
{"DP_ENT_CUSTOMCOLORMAP"},
{"DP_ENT_EXTERIORMODELTOCLIENT"},
{"DP_ENT_TRAILEFFECTNUM", 1, NULL, {"particleeffectnum"}, "self.traileffectnum=particleeffectnum(\"myeffectname\n\"); can be used to attach a particle trail to the given server entity. This is equivelent to calling trailparticles each frame."},
//only in dp6 currently {"DP_ENT_GLOW"},
{"DP_ENT_VIEWMODEL"},
{"DP_GECKO_SUPPORT", 7, NULL, {"gecko_create", "gecko_destroy", "gecko_navigate", "gecko_keyevent", "gecko_mousemove", "gecko_resize", "gecko_get_texture_extent"}},
@ -5832,6 +5835,7 @@ lh_extension_t QSG_Extensions[] = {
{"DP_HALFLIFE_MAP_CVAR"},
//to an extend {"DP_HALFLIFE_SPRITE"},
{"DP_INPUTBUTTONS"},
{"DP_LIGHTSTYLE_STATICVALUE"},
{"DP_LITSUPPORT"},
{"DP_MD3_TAGSINFO", 2, NULL, {"gettagindex", "gettaginfo"}},
{"DP_MONSTERWALK", 0, NULL, {NULL}, "MOVETYPE_WALK is valid on non-player entities. Note that only players receive acceleration etc in line with none/bounce/fly/noclip movetypes on the player, thus you will have to provide your own accelerations (incluing gravity) yourself."},
@ -5858,7 +5862,7 @@ lh_extension_t QSG_Extensions[] = {
{"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}},
{"DP_QC_MULTIPLETEMPSTRINGS", 0, NULL, {NULL}, "Superseded by DP_QC_UNLIMITEDTEMPSTRINGS. Functions that return a temporary string will not overwrite/destroy previous temporary strings until at least 16 strings are returned (or control returns to the engine)."},
{"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}},
{"DP_QC_RENDER_SCENE"}, //clear+addentity+setviewprop+renderscene+setmodel are available to menuqc.
{"DP_QC_RENDER_SCENE", 0, NULL, {NULL}, "clearscene+addentity+setviewprop+renderscene+setmodel are available to menuqc. WARNING: DP advertises this extension without actually supporting it, FTE does actually support it."},
{"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}},
{"DP_QC_STRFTIME", 1, NULL, {"strftime"}},
{"DP_QC_STRING_CASE_FUNCTIONS", 2, NULL, {"strtolower", "strtoupper"}},
@ -5871,7 +5875,7 @@ lh_extension_t QSG_Extensions[] = {
{"DP_QC_TRACE_MOVETYPE_HITMODEL"},
{"DP_QC_TRACE_MOVETYPE_WORLDONLY"},
{"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension...
{"DP_QC_UNLIMITEDTEMPSTRINGS", 0, NULL, {NULL}, "Supersedes DP_QC_MULTIPLETEMPSTRINGS, superseded by FTE_QC_PERSISTENTTEMPSTRINGS. All temp strings will be valid at least until the QCVM returns."},
{"DP_QC_UNLIMITEDTEMPSTRINGS", 0, NULL, {NULL}, "Supersedes DP_QC_MULTIPLETEMPSTRINGS, superseded by FTE_QC_PERSISTENTTEMPSTRINGS. Specifies that all temp strings will be valid at least until the QCVM returns."},
{"DP_QC_URI_ESCAPE", 2, NULL, {"uri_escape", "uri_unescape"}},
#ifdef WEBCLIENT
{"DP_QC_URI_GET", 1, NULL, {"uri_get"}},
@ -5889,23 +5893,23 @@ lh_extension_t QSG_Extensions[] = {
{"DP_SOLIDCORPSE"},
{"DP_SPRITE32"}, //hmm... is it legal to advertise this one?
{"DP_SV_BOTCLIENT", 2, NULL, {"spawnclient", "clienttype"}},
{"DP_SV_CLIENTCOLORS"},
{"DP_SV_CLIENTNAME"},
{"DP_SV_CLIENTCOLORS", 0, NULL, {NULL}, "Provided only for compatibility with DP."},
{"DP_SV_CLIENTNAME", 0, NULL, {NULL}, "Provided only for compatibility with DP."},
{"DP_SV_DRAWONLYTOCLIENT"},
{"DP_SV_DROPCLIENT", 1, NULL, {"dropclient"}},
{"DP_SV_DROPCLIENT", 1, NULL, {"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"},
{"DP_SV_EFFECT", 1, NULL, {"effect"}},
{"DP_SV_EXTERIORMODELFORCLIENT"},
{"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point.
{"DP_SV_PLAYERPHYSICS"},
//FTE cannot implement this one, because dp's arguments are the wrong way around. its otherwise implemented. {"DP_SV_POINTPARTICLES"},
{"DP_SV_PLAYERPHYSICS", 0, NULL, {NULL}, "Allows reworking parts of NQ player physics. USE AT OWN RISK - this necessitates NQ physics and is thus guarenteed to break prediction."},
{"DP_SV_POINTPARTICLES", 3, NULL, {"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that pointparticles (and trailparticles) exists in ssqc as well as csqc (and that dp's trailparticles argument fuckup will normally work). ssqc values can be passed to csqc for use, the reverse is not true. Does NOT mean that DP's effectinfo.txt is supported, only that ssqc has functionality equivelent to csqc."},
{"DP_SV_POINTSOUND", 1, NULL, {"pointsound"}},
{"DP_SV_PRECACHEANYTIME"},
{"DP_SV_PRECACHEANYTIME", 0, NULL, {NULL}, "Specifies that the various precache builtins can be called at any time. WARNING: precaches are sent reliably while sound events, modelindexes, and particle events are not. This can mean sounds and particles might not work the first time around, or models may take a while to appear (after the reliables are received and the model is loaded from disk). Always attempt to precache a little in advance in order to reduce these issues (preferably at the start of the map...)"},
{"DP_SV_SETCOLOR"},
{"DP_SV_SPAWNFUNC_PREFIX"},
{"DP_SV_WRITEPICTURE", 1, NULL, {"WritePicture"}},
{"DP_SV_WRITEUNTERMINATEDSTRING", 1, NULL, {"WriteUnterminatedString"}},
{"DP_TE_BLOOD", 1, NULL, {"te_blood"}},
{"DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}},
{"_DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}},
{"DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}},
{"DP_TE_EXPLOSIONRGB", 1, NULL, {"te_explosionrgb"}},
{"_DP_TE_FLAMEJET", 1, NULL, {"te_flamejet"}},
@ -5937,7 +5941,7 @@ lh_extension_t QSG_Extensions[] = {
"skel_get_bonerel", "skel_get_boneabs", "skel_set_bone", "skel_mul_bone", "skel_mul_bones", "skel_copybones",
"skel_delete", "frameforname", "frameduration"}},
{"FTE_CSQC_RENDERTARGETS_WIP", 0, NULL, {NULL}, "VF_DESTCOLOUR etc exist and are supported"},
{"FTE_ENT_SKIN_CONTENTS"}, //self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder.
{"FTE_ENT_SKIN_CONTENTS", 0, NULL, {NULL}, "self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder."},
{"FTE_ENT_UNIQUESPAWNID"},
{"FTE_EXTENDEDTEXTCODES"},
{"FTE_FORCESHADER", 1, NULL, {"shaderforname"}}, //I'd rename this to _CSQC_ but it does technically provide this builtin to menuqc too, not that the forceshader entity field exists there... but whatever.
@ -5946,9 +5950,11 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}, "Allows you to check if a client has too many reliable messages pending."},
{"FTE_MEMALLOC", 4, NULL, {"memalloc", "memfree", "memcpy", "memfill8"}, "Allows dynamically allocating memory. Use pointers to access this memory. Memory will not be saved into saved games."},
#ifndef NOMEDIA
{"FTE_MEDIA_AVI"}, //playfilm supports avi files.
{"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files.
{"FTE_MEDIA_ROQ"}, //playfilm command supports q3 roq files
#if defined(_WIN32) && !defined(WINRT)
{"FTE_MEDIA_AVI", 0, NULL, {NULL}, "playfilm command supports avi files."},
#endif
{"FTE_MEDIA_CIN", 0, NULL, {NULL}, "playfilm command supports q2 cin files."},
{"FTE_MEDIA_ROQ", 0, NULL, {NULL}, "playfilm command supports q3 roq files."},
#endif
{"FTE_MULTIPROGS", 5, NULL, {"externcall", "addprogs", "externvalue", "externset", "instr"}, "Multiple progs.dat files can be loaded inside the same qcvm."}, //multiprogs functions are available.
{"FTE_MULTITHREADED", 3, NULL, {"sleep", "fork", "abort"}},
@ -5958,7 +5964,7 @@ lh_extension_t QSG_Extensions[] = {
#ifdef SVCHAT
{"FTE_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested.
#endif
{"FTE_QC_CHECKCOMMAND", 1, NULL, {"checkcommand"}},
{"FTE_QC_CHECKCOMMAND", 1, NULL, {"checkcommand"}, "Provides a way to test if a console command exists, and whether its a command/alias/cvar. Does not say anything about the expected meanings of any arguments or values."},
{"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}},
{"FTE_QC_HARDWARECURSORS", 0, NULL, {NULL}, "setcursormode exists in both csqc+menuqc, and accepts additional arguments to specify a cursor image to use when this module has focus. If the image exceeds hardware limits, it will be emulated using regular draws - this at least still avoids conflicting cursors."},
{"FTE_QC_HASHTABLES", 6, NULL, {"hash_createtab", "hash_destroytab", "hash_add", "hash_get", "hash_delete", "hash_getkey"}},
@ -5971,6 +5977,18 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_QC_RAGDOLL_WIP", 1, NULL, {"ragupdate", "skel_set_bone_world", "skel_mmap"}},
{"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}}, //includes the SV_ParseConnectionlessPacket event.
{"FTE_QC_TRACETRIGGER"},
#ifdef Q2CLIENT
{"FTE_QUAKE2_CLIENT", 0, NULL, {NULL}, "This engine is able to act as a quake2 client"},
#endif
#ifdef Q2SERVER
{"FTE_QUAKE2_SERVER", 0, NULL, {NULL}, "This engine is able to act as a quake2 server"},
#endif
#ifdef Q3CLIENT
{"FTE_QUAKE3_CLIENT", 0, NULL, {NULL}, "This engine is able to act as a quake3 client"},
#endif
#ifdef Q3SERVER
{"FTE_QUAKE3_SERVER", 0, NULL, {NULL}, "This engine is able to act as a quake3 server"},
#endif
{"FTE_SOLID_LADDER"}, //Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS
#ifdef SQL
@ -5986,6 +6004,10 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_SV_REENTER"},
{"FTE_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash",
"te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}},
#ifdef TERRAIN
{"FTE_TERRAIN_MAP", 0, NULL, {NULL}, "This engine supports .hmp files, as well as terrain embedded within bsp files."},
{"FTE_RAW_MAP", 0, NULL, {NULL}, "This engine supports directly loading .map files, as well as realtime editing of the various brushes."},
#endif
{"KRIMZON_SV_PARSECLIENTCOMMAND", 3, NULL, {"clientcommand", "tokenize", "argv"}}, //very very similar to the mvdsv system.
{"NEH_CMD_PLAY2"},

View file

@ -105,10 +105,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PROTOCOL_INFO_GUID (('G'<<0) + ('U'<<8) + ('I'<<16) + ('D' << 24)) //globally 'unique' client id info.
#define PROTOCOL_VERSION_QW 28
#define PROTOCOL_VERSION_Q2_DEMO_MIN 26
#define PROTOCOL_VERSION_Q2_MIN 31
#define PROTOCOL_VERSION_Q2 34
#define PROTOCOL_VERSION_QW 28
#define PROTOCOL_VERSION_Q2_DEMO_MIN 26
#define PROTOCOL_VERSION_Q2_MIN 31
#define PROTOCOL_VERSION_Q2 34
#define PROTOCOL_VERSION_R1Q2 35
#define PROTOCOL_VERSION_Q2PRO 36
//=========================================
@ -392,7 +395,13 @@ enum svcq2_ops_e
svcq2_playerinfo, //17 // variable
svcq2_packetentities,//18 // [...]
svcq2_deltapacketentities,//19 // [...]
svcq2_frame //20 (the bastard to implement.)
svcq2_frame, //20 (the bastard to implement.)
svcr1q2_zpacket = 21,
svcr1q2_zdownload = 22,
svcq2pro_gamestate = 23, // q2pro specific, means svc_playerupdate in r1q2
svcq2pro_setting = 24,
};
enum clcq2_ops_e
@ -766,6 +775,7 @@ enum clcq2_ops_e
#define Q2U_ANGLE1 (1<<10)
#define Q2U_MODEL (1<<11)
#define Q2U_RENDERFX8 (1<<12) // fullbright, etc
#define Q2UX_ANGLE16 (1<<13)
#define Q2U_EFFECTS8 (1<<14) // autorotate, trails, etc
#define Q2U_MOREBITS2 (1<<15) // read one additional qbyte
@ -784,6 +794,12 @@ enum clcq2_ops_e
#define Q2U_SKIN16 (1<<25)
#define Q2U_SOUND (1<<26)
#define Q2U_SOLID (1<<27)
#define Q2UX_UNUSED4 (1<<28)
#define Q2UX_UNUSED3 (1<<29)
#define Q2UX_UNUSED2 (1<<30)
#define Q2UX_UNUSED1 (1<<31)
#define Q2UX_UNUSED (Q2UX_UNUSED1|Q2UX_UNUSED2|Q2UX_UNUSED3|Q2UX_UNUSED4)
//==============================================
@ -1009,6 +1025,7 @@ typedef struct entity_state_s
vec3_t predorg;
} q1;
} u;
unsigned short modelindex2; //q2/vweps
unsigned short frame;
@ -1031,13 +1048,13 @@ typedef struct entity_state_s
qbyte lightstyle;
qbyte lightpflags;
unsigned short solid;
unsigned short tagindex;
unsigned int tagentity;
unsigned int solid;
#define ES_SOLID_BSP 31
unsigned short light[4];
unsigned short tagentity;
unsigned short tagindex;
} entity_state_t;
extern entity_state_t nullentitystate;
@ -1178,6 +1195,14 @@ typedef struct q1usercmd_s
#define Q2PS_WEAPONFRAME (1<<13)
#define Q2PS_RDFLAGS (1<<14)
#define Q2PSX_GUNOFFSET (1<<0)
#define Q2PSX_GUNANGLES (1<<1)
#define Q2PSX_M_VELOCITY2 (1<<2)
#define Q2PSX_M_ORIGIN2 (1<<3)
#define Q2PSX_VIEWANGLE2 (1<<4)
#define Q2PSX_STATS (1<<5)
#define Q2PSX_CLIENTNUM (1<<6)
#define Q2PSX_OLD (1<<8) //not part of the protocol, just lazy handling.
// entity_state_t->renderfx flags

View file

@ -734,7 +734,7 @@ void Netchan_TransmitNextFragment( netchan_t *chan )
// Send the qport if we are a client
if( chan->sock == NS_CLIENT )
{
MSG_WriteShort( &send, cls.qport);
MSG_WriteShort( &send, chan->qport);
}
#endif
fragmentLength = chan->reliable_length - chan->reliable_start;
@ -833,7 +833,7 @@ void Netchan_TransmitQ3( netchan_t *chan, int length, const qbyte *data )
// Send the qport if we are a client
if( chan->sock == NS_CLIENT )
{
MSG_WriteShort( &send, cls.qport);
MSG_WriteShort( &send, chan->qport);
}
#endif
// Copy the message to the packet

View file

@ -2657,9 +2657,8 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *
void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *cookie)
{
unsigned int vertidx;
int i, lindex;
int i, lindex, edgevert;
mesh_t *mesh = surf->mesh;
medge_t *pedge;
float *vec;
float s, t, d;
int sty;
@ -2692,17 +2691,13 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
for (i=0 ; i<mesh->numvertexes ; i++)
{
lindex = mod->surfedges[surf->firstedge + i];
if (lindex > 0)
{
pedge = &mod->edges[lindex];
vertidx = pedge->v[0];
}
edgevert = lindex <= 0;
if (edgevert)
lindex = -lindex;
if (lindex < 0 || lindex >= mod->numedges)
vertidx = 0;
else
{
pedge = &mod->edges[-lindex];
vertidx = pedge->v[1];
}
vertidx = mod->edges[lindex].v[edgevert];
vec = mod->vertexes[vertidx].position;
s = DotProduct (vec, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3];
@ -2973,6 +2968,7 @@ static int Mod_Batches_Generate(model_t *mod)
mod->lightmaps.count /= merge;
mod->lightmaps.height *= merge;
mod->numbatches = 0;
//for each surface, find a suitable batch to insert it into.
//we use 'firstmesh' to avoid chucking out too many verts in a single vbo (gl2 hardware tends to have a 16bit limit)

View file

@ -2878,18 +2878,12 @@ void DumpGLState(void)
// qglGetPointerv(GL_FOG_COORD_ARRAY_POINTER, &ptr);
// Sys_Printf("GL_FOG_COORDINATE_ARRAY_EXT: %i (%lx)\n", (int) qglIsEnabled(GL_FOG_COORDINATE_ARRAY_EXT), (int) ptr);
// }
// if (qglIsEnabled(GL_INDEX_ARRAY))
{
if (qglBindBufferARB)
qglGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &rval);
else
rval = 0;
#ifndef GL_INDEX_ARRAY_POINTER
Sys_Printf("GL_ELEMENT_ARRAY_BUFFER_BINDING: %i:%p\n", rval, (void*)0);
#else
qglGetPointerv(GL_INDEX_ARRAY_POINTER, &ptr);
Sys_Printf("GL_INDEX_ARRAY: %s %i:%p\n", qglIsEnabled(GL_INDEX_ARRAY)?"en":"dis", rval, ptr);
#endif
}
if (qglIsEnabled(GL_NORMAL_ARRAY))
{

View file

@ -18,6 +18,21 @@ r_part pe_default
scalefactor 0.8
}
r_part TEQ2_LASER_SPARKS
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part te_splashsparks
{
texture "classicparticle"
@ -268,7 +283,7 @@ r_part teq2_blaster
lightradius 150
lightradiusfade 400
lightrgb 1 1 0
lightshadows 0
lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0
}
r_part teq2_blaster2
@ -290,7 +305,7 @@ r_part teq2_blaster2
lightradius 150
lightradiusfade 400
lightrgb 0.05 1.0 0.05
lightshadows 0
lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0
}
r_part TR_BLASTERTRAIL
@ -305,6 +320,10 @@ r_part TR_BLASTERTRAIL
randomvel 5
die 0.3 0.5
colorindex 0xe0
lightradius 200
lightradiusfade 400
lightrgb 1.0 1.0 0.0
lightshadows 1
}
//green version
@ -320,6 +339,10 @@ r_part TR_BLASTERTRAIL2
randomvel 5
die 0.3 0.5
colorindex 0xd0
lightradius 200
lightradiusfade 400
lightrgb 0.0 1.0 0.0
lightshadows 1
}
@ -490,12 +513,25 @@ r_part trq2_grenade
}
r_part trq2_gib
{
assoc tr_gib
texture "particles/quake"
step 3
scale 4
die 1.0 1.4
colorindex 0xe8 7
spawnorg 1
spawnvel 5
gravity -20
}
//FIXME: implement
r_part trq2_greengib
{
assoc tr_gib
texture "particles/quake"
step 3
scale 4
die 1.0 1.4
colorindex 0xdb 7
spawnorg 1
spawnvel 5
gravity -20
}
r_part TR_PLASMA
@ -527,6 +563,14 @@ r_part tr_tagtrail
lightrgb 1.0 1.0 0.0
}
//FIXME: add particles
r_part tr_trap
{
lighttime 0
lightradius 100 200
lightrgb 1.0 0.8 0.25
}
//flags do NOT use coronas, because it obscures the holding player's skin colour
r_part tr_flag1
{
@ -565,15 +609,6 @@ r_part tr_flag2
lightrgb 0.25 0.25 1.0
}
//FIXME: add particles
r_part tr_trap
{
lighttime 0
lightradius 100 200
lightrgb 1.0 0.8 0.25
}
r_part EF_FLIES
{
texture "classicparticle"
@ -670,4 +705,26 @@ r_part teq2_bfg_explosion
lightrgbfade 0.0 0.0 0.0
sound "weapons/xpld_wat.wav" 1 1 0 0
model "sprites/s_bfg2.sp2" framestart=0 frameend=4 alpha=0.3 transparent fullbright noshadow
}
}
//31qu cylinder, 8-98 high
//should look like its sucked up into some thingie above
r_part TEQ2_BOSSTPORT
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 800
scale 1
alpha 1
die 0.5 0.8
orgadd 8 -98
veladd 100 200
spawnmode circle
spawnorg 48 0
spawnvel -50 30
randomvel 32 31
gravity -800
rgbf 1 1 1
scalefactor 0.8
}

BIN
engine/qclib/byshpuld.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -1232,17 +1232,17 @@ reeval:
return s;
*/ }
break;
/* case OP_PUSH:
OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]);
pr_spushed += OPA->_int;
if (pr_spushed + localstack_used >= LOCALSTACK_SIZE)
case OP_PUSH:
OPC->_int = ENGINEPOINTER(&prinst.localstack[prinst.localstack_used+prinst.spushed]);
prinst.spushed += OPA->_int;
if (prinst.spushed + prinst.localstack_used >= LOCALSTACK_SIZE)
{
pr_spushed = 0;
prinst.spushed = 0;
pr_xstatement = st-pr_statements;
PR_RunError(progfuncs, "Progs pushed too much");
PR_RunError(&progfuncs->funcs, "Progs pushed too much");
}
break;
case OP_POP:
/* case OP_POP:
pr_spushed -= OPA->_int;
if (pr_spushed < 0)
{

1
engine/qclib/fteqcc.rc Normal file
View file

@ -0,0 +1 @@
101 ICON "byshpuld.ico"

View file

@ -464,6 +464,7 @@ struct QCC_function_s
const char *file;
int line;
char *name; //internal name of function
struct QCC_function_s *parentscope; //for nested functions
struct QCC_type_s *type; //same as the def's type
struct QCC_def_s *def;
struct QCC_def_s *firstlocal;

View file

@ -220,6 +220,8 @@ const QCC_sref_t nullsref = {0};
struct QCC_function_s *pr_scope; // the function being parsed, or NULL
QCC_type_t *pr_classtype; // the class that the current function is part of.
QCC_type_t *pr_assumetermtype; //undefined things get this time, with no warning about being undeclared (used for the state function, so prototypes are not needed)
QCC_function_t *pr_assumetermscope;
unsigned int pr_assumetermflags; //GDF_
pbool pr_dumpasm;
QCC_string_t s_file, s_file2; // filename for function definition
@ -1626,6 +1628,7 @@ static QCC_sref_t QCC_GetTemp(QCC_type_t *type);
void QCC_FreeTemp(QCC_sref_t t);
void QCC_FreeDef(QCC_def_t *def);
QCC_sref_t QCC_MakeSRefForce(QCC_def_t *def, unsigned int ofs, QCC_type_t *type);
QCC_sref_t QCC_MakeSRef(QCC_def_t *def, unsigned int ofs, QCC_type_t *type);
//we're about to overwrite the given def, so if there's any aliases to it, we need to clear them out.
static void QCC_ClobberDef(QCC_def_t *def)
@ -2916,11 +2919,39 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
QCC_FreeTemp(var_a);
optres_assignments++;
if (flags&STFL_DISCARDRESULT)
{
QCC_FreeTemp(var_b);
var_b = nullsref;
}
return var_b;
}
}
}
}
else if (op - pr_opcodes == OP_ADD_I && statements[numstatements-1].op == OP_MUL_I && opt_assignments)
{
//mul_i idx 4i tmp
//add_i tmp 2i out
//becomes add_piw 2i idx out
// const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a);
const QCC_eval_t *eval_b = QCC_SRef_EvalConst(statements[numstatements-1].b);
if (eval_b && eval_b->_int == 4)
{
if (opt_assignments && var_a.cast && var_a.sym == statements[numstatements-1].c.sym && var_a.ofs == statements[numstatements-1].c.ofs)
if (var_a.sym && var_b.sym && var_a.sym->temp && var_a.sym->refcount==1)
{
op = &pr_opcodes[OP_ADD_PIW];
QCC_FreeDef(var_a.sym);
var_a = var_b;
var_b = statements[numstatements-1].a;
numstatements--;
QCC_ForceUnFreeDef(var_b.sym);
}
}
}
}
if (!QCC_OPCodeValid(op))
@ -3156,10 +3187,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
var_a.cast = type_float;
}
if (var_b.cast)
{
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_F], var_a, var_b, NULL, 0));
return var_b;
}
return QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_F], var_a, var_b, NULL, flags&STFL_DISCARDRESULT);
}
return var_a;
case OP_CONV_FTOI:
@ -3185,10 +3213,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
var_a.cast = type_integer;
}
if (var_b.cast)
{
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_I], var_a, var_b, NULL, 0));
return var_b;
}
return QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_I], var_a, var_b, NULL, flags&STFL_DISCARDRESULT);
}
return var_a;
case OP_STORE_P:
@ -5008,13 +5033,24 @@ QCC_sref_t QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
}
}
if (!strcmp(funcname, "alloca"))
{ //FIXME: half of these functions with regular expression arguments should be handled later or something
QCC_sref_t sz;
{ //FIXME: half of these functions with known arguments should be handled later or something
QCC_sref_t sz, ret;
if (!func.sym->initialized)
func.sym->initialized = 3;
func.sym->referenced = true;
QCC_FreeTemp(func);
sz = QCC_PR_Expression(TOP_PRIORITY, 0);
QCC_PR_Expect(")");
sz = QCC_SupplyConversion(sz, ev_integer, true);
sz = QCC_PR_Statement(&pr_opcodes[OP_PUSH], sz, nullsref, NULL);
return sz;
//result = push_words((sz+3)/4);
sz = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], sz, QCC_MakeIntConst(3), NULL);
sz = QCC_PR_Statement(&pr_opcodes[OP_DIV_I], sz, QCC_MakeIntConst(4), NULL);
QCC_FreeTemp(sz);
ret = QCC_GetTemp(QCC_PointerTypeTo(type_variant));
QCC_PR_SimpleStatement(&pr_opcodes[OP_PUSH], sz, nullsref, ret, false); //push *(int*)&a elements
return ret;
}
if (!strcmp(funcname, "_"))
{
@ -6386,12 +6422,20 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
}
arraysize = 0;
//convert it to ints if that makes sense
if (QCC_OPCodeValid(&pr_opcodes[OP_ADD_I]))
{
if (idx.cast)
idx = QCC_SupplyConversion(idx, ev_integer, true);
tmp = QCC_SupplyConversion(tmp, ev_integer, true);
}
if (t->size != 1) /*don't multiply by type size if the instruction/emulation will do that instead*/
{
if (tmp.cast->type == ev_float)
tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], tmp, QCC_MakeFloatConst(t->size), NULL);
tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], QCC_SupplyConversion(tmp, ev_float, true), QCC_MakeFloatConst(t->size), NULL);
else
tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], tmp, QCC_MakeIntConst(t->size), NULL);
tmp = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], QCC_SupplyConversion(tmp, ev_integer, true), QCC_MakeIntConst(t->size), NULL);
}
//legacy opcodes needs to stay using floats even if an int was specified
@ -6404,9 +6448,9 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
/*calc the new index*/
if (idx.cast && idx.cast->type == ev_float && tmp.cast->type == ev_float)
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], idx, QCC_SupplyConversion(tmp, ev_float, true), NULL);
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], QCC_SupplyConversion(idx, ev_float, true), QCC_SupplyConversion(tmp, ev_float, true), NULL);
else if (idx.cast)
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, QCC_SupplyConversion(tmp, ev_integer, true), NULL);
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], QCC_SupplyConversion(idx, ev_integer, true), QCC_SupplyConversion(tmp, ev_integer, true), NULL);
else
idx = tmp;
}
@ -6453,7 +6497,7 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
{
tmp = QCC_MakeIntConst(t->params[i].ofs);
if (idx.cast)
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL);
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], QCC_SupplyConversion(idx, ev_integer, true), QCC_SupplyConversion(tmp, ev_integer, true), NULL);
else
idx = tmp;
}
@ -6461,7 +6505,7 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a
{
tmp = QCC_MakeFloatConst(t->params[i].ofs);
if (idx.cast)
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], idx, tmp, NULL);
idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_F], QCC_SupplyConversion(idx, ev_float, true), QCC_SupplyConversion(tmp, ev_float, true), NULL);
else
idx = tmp;
}
@ -6617,22 +6661,19 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
d = QCC_GetTemp(type_vector);
d.cast = type_float;
if (x.cast->type == ev_float)
x=QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, x, d, NULL, STFL_PRESERVEB);
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, x, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
else
x=QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, x, d, NULL, STFL_PRESERVEB);
QCC_FreeTemp(x);
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, x, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
d.ofs++;
if (y.cast->type == ev_float)
y=QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, y, d, NULL, STFL_PRESERVEB);
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, y, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
else
y=QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, y, d, NULL, STFL_PRESERVEB);
QCC_FreeTemp(y);
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, y, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
d.ofs++;
if (z.cast->type == ev_float)
z=QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, z, d, NULL, STFL_PRESERVEB);
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, z, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
else
z=QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, z, d, NULL, STFL_PRESERVEB);
QCC_FreeTemp(z);
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, z, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
d.ofs++;
d.ofs -= 3;
d.cast = type_vector;
@ -6719,6 +6760,7 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
d = QCC_MakeIntConst(0);
else if ( (!strcmp(name, "randomv")) ||
(!strcmp(name, "sizeof")) ||
(!strcmp(name, "alloca")) ||
(!strcmp(name, "entnum")) ||
(!strcmp(name, "autocvar")) ||
(!strcmp(name, "used_model")) ||
@ -6753,7 +6795,7 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
}
else if (pr_assumetermtype)
{
d = QCC_PR_GetSRef (pr_assumetermtype, name, NULL, true, 0, false);
d = QCC_PR_GetSRef (pr_assumetermtype, name, pr_assumetermscope, true, 0, pr_assumetermflags);
if (!d.cast)
QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name);
}
@ -6942,7 +6984,7 @@ QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit)
char typeb[256];
TypeName(src.cast, typea, sizeof(typea));
TypeName(cast, typeb, sizeof(typeb));
QCC_PR_ParseWarning(0, "Implicit cast from %s to %s\n", typea, typeb);
QCC_PR_ParseWarning(0, "Implicit cast from %s to %s", typea, typeb);
}
}
src.cast = cast;
@ -6968,7 +7010,7 @@ QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit)
char typeb[256];
TypeName(src.cast, typea, sizeof(typea));
TypeName(cast, typeb, sizeof(typeb));
QCC_PR_ParseWarning(0, "Implicit cast from %s to %s\n", typea, typeb);
QCC_PR_ParseWarning(0, "Implicit cast from %s to %s", typea, typeb);
}
src.cast = cast;
}
@ -8008,7 +8050,9 @@ QCC_sref_t QCC_StoreToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable, pb
{
addr = dest->base;
}
QCC_PR_Statement(&pr_opcodes[OP_STOREP_C], addr, source, NULL);
// if (readable) //if we're returning source, make sure it can't get freed
// QCC_UnFreeTemp(source);
QCC_PR_StatementFlags(&pr_opcodes[OP_STOREP_C], source, addr, NULL, STFL_DISCARDRESULT|(preservedest?STFL_PRESERVEB:0)|(readable?STFL_PRESERVEA:0));
}
break;
case REF_ACCESSOR:
@ -9839,6 +9883,7 @@ void QCC_PR_ParseState (void)
{
QCC_sref_t s1, def;
//FIXME: this is ambiguous with pre-inc and post-inc logic.
if (QCC_PR_CheckToken("++") || QCC_PR_CheckToken("--"))
{
s1 = QCC_PR_ParseImmediate ();
@ -9920,6 +9965,8 @@ void QCC_PR_ParseState (void)
QCC_PR_ParseWarning(WARN_UNEXPECTEDPUNCT, "missing comma in state definition");
pr_assumetermtype = type_function;
pr_assumetermscope = pr_scope->parentscope;
pr_assumetermflags = GDF_CONST | (pr_assumetermscope?GDF_STATIC:0);
def = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
if (typecmp(def.cast, type_function))
{
@ -10863,6 +10910,7 @@ QCC_function_t *QCC_PR_GenerateQCFunction (QCC_def_t *def, QCC_type_t *type)
func->firstlocal = NULL;
func->def = def;
func->type = type;
func->parentscope = pr_scope;
return func;
}
@ -11816,6 +11864,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
{
if (scope)
{
//FIXME: should we be scanning the locals list instead, and remove the localstable?
def = pHash_Get(&localstable, name);
while(def)
@ -11829,23 +11878,38 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
if ( def->scope && def->scope != scope)
{
def = pHash_GetNext(&localstable, name, def);
continue; // in a different function
struct QCC_function_s *pscope = NULL;
if (def->isstatic)
{
for (pscope = scope->parentscope; pscope; pscope = pscope->parentscope)
if (def->scope == pscope)
break;
}
if (!pscope)
{
def = pHash_GetNext(&localstable, name, def);
continue; // in a different function
}
}
if (type && typecmp(def->type, type))
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type, typebuf1, sizeof(typebuf1)), TypeName(def->type, typebuf2, sizeof(typebuf2)));
if (def->arraysize != arraysize && arraysize>=0)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
if (allocate && scope && !(flags & GDF_STATIC))
{
if (allocate == 2)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Duplicate definition of %s.", name);
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
if (def->isstatic)
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "nonstatic redeclaration of %s ignored", name);
else
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
// if (!scope)
// QCC_PR_ParsePrintDef(def);
}
else if (allocate && (flags & GDF_STATIC) && !def->isstatic)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "static redefinition of %s follows non-static definition.", name);
QCC_ForceUnFreeDef(def);
return def;
@ -11919,7 +11983,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
}
if (def->arraysize != arraysize && arraysize>=0)
QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope)
if (allocate && scope && !(flags & GDF_STATIC))
{
if (allocate == 2)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Duplicate definition of %s.", name);
@ -11929,7 +11993,10 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
continue; // in a different function
}
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
if (def->isstatic)
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "nonstatic redeclaration of %s ignored", name);
else
QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name);
QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, def);
// if (!scope)
// QCC_PR_ParsePrintDef(def);
@ -13060,17 +13127,21 @@ void QCC_PR_ParseDefs (char *classname)
else if (forceused) //FIXME: make proper pragma(used) thingie
gd_flags |= GDF_USED;
#if IAMNOTLAZY
if (dynlength.cast)
{
#if 1//IAMNOTLAZY
def = QCC_PR_GetDef (QCC_PR_PointerType(type), name, pr_scope, allocatenew, 0, gd_flags);
dynlength = QCC_SupplyConversion(dynlength, ev_integer, true);
if (type->size != 1)
dynlength = QCC_PR_Statement(pr_opcodes+OP_MUL_I, dynlength, QCC_MakeIntConst(type->size), NULL);
QCC_PR_SimpleStatement(&pr_opcodes[OP_PUSH], dynlength, nullsref, def, false); //push *(int*)&a elements
QCC_PR_SimpleStatement(&pr_opcodes[OP_PUSH], dynlength, nullsref, QCC_MakeSRef(def, 0, def->type), false); //push *(int*)&a elements
QCC_FreeTemp(dynlength);
QCC_FreeDef(def);
#else
QCC_PR_ParseError(ERR_NOTANAME, "%s is dynamically sized", name);
#endif
}
else
#endif
def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, gd_flags);
if (!def)

View file

@ -14,6 +14,8 @@
#define EMBEDDEBUG
#define IDI_ICON_FTEQCC MAKEINTRESOURCE(101)
void AddSourceFile(const char *parentsrc, const char *filename);
void GUI_ParseCommandLine(char *args);
void GUI_RevealOptions(void);
@ -2145,7 +2147,7 @@ void EditFile(char *name, int line, pbool setcontrol)
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
wndclass.hIcon = 0;
wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (void *)COLOR_WINDOW;
wndclass.lpszMenuName = 0;
@ -3429,7 +3431,7 @@ void OptionsDialog(void)
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
wndclass.hIcon = 0;
wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (void *)COLOR_WINDOW;
wndclass.lpszMenuName = 0;
@ -4719,7 +4721,7 @@ void CreateOutputWindow(pbool doannoates)
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
wndclass.hIcon = 0;
wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (void *)COLOR_WINDOW;
wndclass.lpszMenuName = 0;
@ -5076,7 +5078,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = ghInstance;
wndclass.hIcon = 0;
wndclass.hIcon = LoadIcon(ghInstance, IDI_ICON_FTEQCC);
wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
wndclass.hbrBackground = (void *)COLOR_WINDOW;
wndclass.lpszMenuName = 0;

View file

@ -34,6 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PF_sqlescape PF_Fixme
#define PF_sqlversion PF_Fixme
#define PF_sqlreadfloat PF_Fixme
#define PF_sqlreadblob PF_Fixme
#define PF_sqlescapeblob PF_Fixme
#endif
#ifndef CLIENTONLY
@ -3752,14 +3754,18 @@ void QCBUILTIN PF_sv_particleeffectnum(pubprogfuncs_t *prinst, struct globalvars
*/
int i;
G_FLOAT(OFS_RETURN) = 0;
if (s[0] <= ' ')
{
PR_BIError (prinst, "PF_precache_particles: Bad string");
/*if (!ssqc_deprecated_warned)
{
PR_RunWarning(prinst, "PF_precache_particles: Bad string");
ssqc_deprecated_warned = true;
}*/
return;
}
G_FLOAT(OFS_RETURN) = 0;
for (i=1 ; i<MAX_SSPARTICLESPRE ; i++)
{
if (!*sv.strings.particle_precache[i])
@ -3769,14 +3775,16 @@ void QCBUILTIN PF_sv_particleeffectnum(pubprogfuncs_t *prinst, struct globalvars
if (sv.state != ss_loading)
{
Con_DPrintf("Delayed particle precache: %s\n", s);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i|PC_PARTICLE);
MSG_WriteString(&sv.reliable_datagram, s);
MSG_WriteByte(&sv.multicast, svcfte_precache);
MSG_WriteShort(&sv.multicast, i|PC_PARTICLE);
MSG_WriteString(&sv.multicast, s);
#ifdef NQPROT
MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache);
MSG_WriteShort(&sv.nqreliable_datagram, i|PC_PARTICLE);
MSG_WriteString(&sv.nqreliable_datagram, s);
MSG_WriteByte(&sv.nqmulticast, svcdp_precache);
MSG_WriteShort(&sv.nqmulticast, i|PC_PARTICLE);
MSG_WriteString(&sv.nqmulticast, s);
#endif
SV_MulticastProtExt(vec3_origin, MULTICAST_ALL_R, pr_global_struct->dimension_send, PEXT_CSQC, 0);
}
}
if (!strcmp(sv.strings.particle_precache[i], s))
@ -5869,6 +5877,83 @@ void QCBUILTIN PF_sqlreadfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_
G_FLOAT(OFS_RETURN) = 0;
}
void QCBUILTIN PF_sqlreadblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
sqlserver_t *server;
queryresult_t *qres;
char *data;
int serveridx = G_FLOAT(OFS_PARM0);
int queryidx = G_FLOAT(OFS_PARM1);
int row = G_FLOAT(OFS_PARM2);
int column = G_FLOAT(OFS_PARM3);
int dst = G_INT(OFS_PARM4);
int dstsize = G_INT(OFS_PARM5);
if (dst <= 0 || dst+dstsize >= prinst->stringtablesize)
{ //FIXME: this check should be some utility function.
PR_BIError(prinst, "PF_sqlreadblob: invalid dest\n");
return;
}
if (SQL_Available())
{
server = SQL_GetServer(serveridx, false);
if (server)
{
qres = SQL_GetQueryResult(server, queryidx, row);
if (qres)
{
size_t blobsize;
data = SQL_ReadField(server, qres, row, column, true, &blobsize);
if (data)
{ //unsure how to handle overflows. we truncate for now.
blobsize = min(blobsize, dstsize);
G_INT(OFS_RETURN) = blobsize;
memcpy(prinst->stringtable + dst, data, blobsize);
return;
}
}
else
{
Con_Printf("Invalid sql request/row\n");
PR_StackTrace(prinst, false);
}
}
}
// else we failed to get anything
G_INT(OFS_RETURN) = 0;
}
void QCBUILTIN PF_sqlescapeblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char hex[16] = "0123456789abcdef";
// int serveridx = G_FLOAT(OFS_PARM0); //fixme
int qcptr = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
char *out;
qbyte *blob = prinst->stringtable + qcptr;
if (qcptr <= 0 || qcptr+size >= prinst->stringtablesize)
{ //FIXME: this check should be some utility function.
PR_BIError(prinst, "PF_sqlescapeblob: invalid blob\n");
return;
}
G_INT(OFS_RETURN) = prinst->AllocTempString(prinst, &out, size*2+4);
//"x'DEADBEEF'"
*out++ = 'x';
*out++ = '\'';
for (; size > 0; size--, blob++)
{
*out++ = hex[*blob>>4];
*out++ = hex[*blob&15];
}
*out++ = '\'';
*out++ = 0;
}
void QCBUILTIN PF_sqlerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
sqlserver_t *server;
@ -7806,6 +7891,16 @@ void QCBUILTIN PF_sv_trailparticles(pubprogfuncs_t *prinst, struct globalvars_s
ednum = G_EDICTNUM(prinst, OFS_PARM1);
}
if (efnum <= 0)
{
// if (!ssqc_deprecated_warned)
// {
// PR_RunWarning(prinst, "PF_sv_trailparticles: invalid effect");
// ssqc_deprecated_warned = true;
// }
return;
}
MSG_WriteByte(&sv.multicast, svcfte_trailparticles);
MSG_WriteEntity(&sv.multicast, ednum);
MSG_WriteShort(&sv.multicast, efnum);
@ -7840,6 +7935,16 @@ void QCBUILTIN PF_sv_pointparticles(pubprogfuncs_t *prinst, struct globalvars_s
float *vel = (prinst->callargc < 3)?vec3_origin:G_VECTOR(OFS_PARM2);
int count = (prinst->callargc < 4)?1:G_FLOAT(OFS_PARM3);
if (efnum <= 0)
{
// if (!ssqc_deprecated_warned)
// {
// PR_RunWarning(prinst, "PF_sv_pointparticles: invalid effect");
// ssqc_deprecated_warned = true;
// }
return;
}
if (count > 65535)
count = 65535;
@ -8648,10 +8753,10 @@ static void ParamNegateFix ( float * xx, float * yy, int Zone )
static void QCBUILTIN PF_ShowPic(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *slot = PR_GetStringOfs(prinst, OFS_PARM0);
const char *picname = PR_GetStringOfs(prinst, OFS_PARM1);
float x = G_FLOAT(OFS_PARM2);
float y = G_FLOAT(OFS_PARM3);
float zone = G_FLOAT(OFS_PARM4);
const char *picname = PR_GetStringOfs(prinst, OFS_PARM1);
float x = G_FLOAT(OFS_PARM2);
float y = G_FLOAT(OFS_PARM3);
unsigned int zone = G_FLOAT(OFS_PARM4);
int entnum;
client_t *cl;
@ -9090,9 +9195,18 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd)
if (delta[0] || delta[1] || delta[2])
{
//eular angle changes suck
client_t *cl = ClientReliableWrite_BeginSplit(client, svcfte_setangledelta, 7);
for (i=0 ; i < 3 ; i++)
ClientReliableWrite_Angle16 (cl, delta[i]);
if (client->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)
{
client_t *cl = ClientReliableWrite_BeginSplit(client, svcfte_setangledelta, 7);
for (i=0 ; i < 3 ; i++)
ClientReliableWrite_Angle16 (cl, delta[i]);
}
else
{
client_t *cl = ClientReliableWrite_BeginSplit(client, svc_setangle, 7);
for (i=0 ; i < 3 ; i++)
ClientReliableWrite_Angle (cl, sv_player->v->v_angle[i]);
}
}
}
@ -9729,6 +9843,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"sqlescape", PF_sqlescape, 0, 0, 0, 256, "string(float serveridx, string data)"}, // sqlescape (FTE_SQL)
{"sqlversion", PF_sqlversion, 0, 0, 0, 257, "string(float serveridx)"}, // sqlversion (FTE_SQL)
{"sqlreadfloat", PF_sqlreadfloat, 0, 0, 0, 258, "float(float serveridx, float queryidx, float row, float column)"}, // sqlreadfloat (FTE_SQL)
{"sqlreadblob", PF_sqlreadblob, 0, 0, 0, 0, "int(float serveridx, float queryidx, float row, float column, _variant *ptr, int maxsize)"},
{"sqlescapeblob", PF_sqlescapeblob, 0, 0, 0, 0, "string(float serveridx, _variant *ptr, int maxsize)"},
{"stoi", PF_stoi, 0, 0, 0, 259, D("int(string)", "Converts the given string into a true integer. Base 8, 10, or 16 is determined based upon the format of the string.")},
{"itos", PF_itos, 0, 0, 0, 260, D("string(int)", "Converts the passed true integer into a base10 string.")},
@ -11017,10 +11133,10 @@ void PR_DumpPlatform_f(void)
{"CHAN_BODY", "const float", QW|NQ|CS, NULL, CHAN_BODY},
{"CHANF_RELIABLE", "const float", QW, NULL, 8},
{"SOUNDFLAG_RELIABLE", "const float", QW|NQ, NULL, CF_RELIABLE},
{"SOUNDFLAG_ABSVOLUME", "const float", /*QW|NQ|*/CS,NULL, CF_ABSVOLUME},
{"SOUNDFLAG_FORCELOOP", "const float", /*QW|NQ|*/CS,NULL, CF_FORCELOOP},
{"SOUNDFLAG_NOSPACIALISE", "const float", /*QW|NQ|*/CS,NULL, CF_NOSPACIALISE},
{"SOUNDFLAG_RELIABLE", "const float", QW|NQ, "The sound will be sent reliably, and without regard to phs.", CF_RELIABLE},
{"SOUNDFLAG_ABSVOLUME", "const float", /*QW|NQ|*/CS,"The sample's volume is not scaled by the volume cvar. Use with caution", CF_ABSVOLUME},
{"SOUNDFLAG_FORCELOOP", "const float", /*QW|NQ|*/CS,"The sound will restart once it reaches the end of the sample.", CF_FORCELOOP},
{"SOUNDFLAG_NOSPACIALISE", "const float", /*QW|NQ|*/CS,"The different audio channels are played at the same volume regardless of which way the player is facing, without needing to use 0 attenuation.", CF_NOSPACIALISE},
{"ATTN_NONE", "const float", QW|NQ|CS, "Sounds with this attenuation can be heard throughout the map", ATTN_NONE},
{"ATTN_NORM", "const float", QW|NQ|CS, "Standard attenuation", ATTN_NORM},
@ -11103,11 +11219,11 @@ void PR_DumpPlatform_f(void)
{"STUFFCMD_IGNOREINDEMO","const float", QW|NQ, "The protocol we are connected to the server with.", STUFFCMD_IGNOREINDEMO},
{"STUFFCMD_DEMOONLY", "const float", QW|NQ, "The protocol we are connected to the server with.", STUFFCMD_DEMOONLY},
{"SOUND_RELIABLE", "const float", QW|NQ, "The sound will be sent reliably, and without regard to phs.", CF_RELIABLE},
/* {"SOUND_RELIABLE", "const float", QW|NQ, "The sound will be sent reliably, and without regard to phs.", CF_RELIABLE},
{"SOUND_FORCELOOP", "const float", QW|NQ|CS,"The sound will restart once it reaches the end of the sample.", CF_FORCELOOP},
{"SOUND_NOSPACIALISE", "const float", QW|NQ|CS,"The different audio channels are played at the same volume regardless of which way the player is facing, without needing to use 0 attenuation.", CF_NOSPACIALISE},
{"SOUND_ABSVOLUME", "const float", QW|NQ|CS,"The sample's volume is not scaled by the volume cvar. Use with caution", CF_ABSVOLUME},
*/
// edict.flags
{"FL_FLY", "const float", QW|NQ|CS, NULL, FL_FLY},
{"FL_SWIM", "const float", QW|NQ|CS, NULL, FL_SWIM},
@ -11171,6 +11287,17 @@ void PR_DumpPlatform_f(void)
{"MF_TRACER2", "const float", QW|NQ|CS, NULL, EF_MF_TRACER2>>24},
{"MF_TRACER3", "const float", QW|NQ|CS, NULL, EF_MF_TRACER3>>24},
{"SL_ORG_TL", "const float", QW|NQ, NULL, SL_ORG_TL},
{"SL_ORG_TR", "const float", QW|NQ, NULL, SL_ORG_TR},
{"SL_ORG_BL", "const float", QW|NQ, NULL, SL_ORG_BL},
{"SL_ORG_BR", "const float", QW|NQ, NULL, SL_ORG_BR},
{"SL_ORG_MM", "const float", QW|NQ, NULL, SL_ORG_MM},
{"SL_ORG_TM", "const float", QW|NQ, NULL, SL_ORG_TM},
{"SL_ORG_BM", "const float", QW|NQ, NULL, SL_ORG_BM},
{"SL_ORG_ML", "const float", QW|NQ, NULL, SL_ORG_ML},
{"SL_ORG_MR", "const float", QW|NQ, NULL, SL_ORG_MR},
{"PFLAGS_NOSHADOW", "const float", QW|NQ|CS, "Associated RT lights attached will not cast shadows, making them significantly faster to draw.", PFLAGS_NOSHADOW},
{"PFLAGS_CORONA", "const float", QW|NQ|CS, "Enables support of coronas on the associated rtlights.", PFLAGS_CORONA},
{"PFLAGS_FULLDYNAMIC", "const float", QW|NQ, "When set in self.pflags, enables fully-customised dynamic lights. Custom rtlight information is not otherwise used.", PFLAGS_FULLDYNAMIC},

View file

@ -540,6 +540,7 @@ void SV_Map_f (void)
if (strlen(level) > 4 &&
(!strcmp(level + strlen(level)-4, ".cin") ||
!strcmp(level + strlen(level)-4, ".roq") ||
!strcmp(level + strlen(level)-4, ".pcx") ||
!strcmp(level + strlen(level)-4, ".avi")))
{
cinematic = true;
@ -2590,7 +2591,7 @@ static void SV_SendGameCommand_f(void)
}
else
#endif
Con_Printf("This command requires a Q2 sever\n");
Con_Printf("Mod-specific command not known\n");
}

View file

@ -2705,10 +2705,10 @@ int glowsize=0, glowcolor=0, colourmod=0;
else
MSG_WriteByte (msg,ent->number);
if (bits & NQU_MODEL) MSG_WriteByte (msg, ent->modelindex);
if (bits & NQU_FRAME) MSG_WriteByte (msg, ent->frame);
if (bits & NQU_COLORMAP) MSG_WriteByte (msg, ent->colormap);
if (bits & NQU_SKIN) MSG_WriteByte (msg, ent->skinnum);
if (bits & NQU_MODEL) MSG_WriteByte (msg, ent->modelindex & 0xff);
if (bits & NQU_FRAME) MSG_WriteByte (msg, ent->frame & 0xff);
if (bits & NQU_COLORMAP) MSG_WriteByte (msg, ent->colormap & 0xff);
if (bits & NQU_SKIN) MSG_WriteByte (msg, ent->skinnum & 0xff);
if (bits & NQU_EFFECTS) MSG_WriteByte (msg, eff & 0x00ff);
if (bits & NQU_ORIGIN1) MSG_WriteCoord (msg, ent->origin[0]);
if (bits & NQU_ANGLE1) MSG_WriteAngle(msg, ent->angles[0]);
@ -2723,18 +2723,18 @@ int glowsize=0, glowcolor=0, colourmod=0;
if (bits & RMQU_SCALE) MSG_WriteByte(msg, ent->scale);
if (bits & FITZU_FRAME2) MSG_WriteByte(msg, ent->frame>>8);
if (bits & FITZU_MODEL2) MSG_WriteByte(msg, ent->modelindex>>8);
if (bits & FITZU_LERPFINISH)MSG_WriteByte(msg, (ed->v->nextthink - sv.world.physicstime) * 255);
if (bits & FITZU_LERPFINISH)MSG_WriteByte(msg, bound(0, (int)((ed->v->nextthink - sv.world.physicstime) * 255), 255));
}
else
{
if (bits & DPU_ALPHA) MSG_WriteByte(msg, ent->trans*255);
if (bits & DPU_SCALE) MSG_WriteByte(msg, ent->scale*16);
if (bits & DPU_ALPHA) MSG_WriteByte(msg, ent->trans);
if (bits & DPU_SCALE) MSG_WriteByte(msg, ent->scale);
if (bits & DPU_EFFECTS2) MSG_WriteByte(msg, eff >> 8);
if (bits & DPU_GLOWSIZE) MSG_WriteByte(msg, glowsize);
if (bits & DPU_GLOWCOLOR) MSG_WriteByte(msg, glowcolor);
if (bits & DPU_COLORMOD) MSG_WriteByte(msg, colourmod);
if (bits & DPU_FRAME2) MSG_WriteByte(msg, (int)ent->frame >> 8);
if (bits & DPU_MODEL2) MSG_WriteByte(msg, (int)ent->modelindex >> 8);
if (bits & DPU_FRAME2) MSG_WriteByte(msg, ent->frame >> 8);
if (bits & DPU_MODEL2) MSG_WriteByte(msg, ent->modelindex >> 8);
}
}
#endif

View file

@ -5290,7 +5290,10 @@ void SV_Init (quakeparms_t *parms)
#endif
if (sv.state == ss_dead)
SV_Error ("Couldn't load a map");
{
Cmd_ExecuteString("path", RESTRICT_LOCAL);
SV_Error ("Couldn't load a map. You may need to use the -basedir argument.");
}
}
}

View file

@ -196,7 +196,10 @@ void Sys_Error (const char *error, ...)
tcsetattr(STDIN_FILENO, TCSADRAIN, &orig);
*(int*)-3 = 0;
//we used to fire sigsegv. this resulted in people reporting segfaults and not the error message that appeared above. resulting in wasted debugging.
//abort should trigger a SIGABRT and still give us the same stack trace. should be more useful that way.
abort();
exit (1);
}
@ -616,6 +619,7 @@ static void Friendly_Crash_Handler(int sig, siginfo_t *info, void *vcontext)
case SIGILL: strcpy(signame, "SIGILL"); break;
case SIGFPE: strcpy(signame, "SIGFPE"); break;
case SIGBUS: strcpy(signame, "SIGBUS"); break;
case SIGABRT: strcpy(signame, "SIGABRT"); break;
case SIGSEGV: Q_snprintfz(signame, sizeof(signame), "SIGSEGV (%p)", info->si_addr); break;
default: Q_snprintfz(signame, sizeof(signame), "%i", sig); break;
}
@ -707,6 +711,7 @@ int main(int argc, char *argv[])
sigaction(SIGILL, &act, NULL);
sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGABRT, &act, NULL);
sigaction(SIGBUS, &act, NULL);
}
#endif

View file

@ -81,10 +81,10 @@ cvar_t sv_floodprotect_suicide = CVAR("sv_floodprotect_suicide", "1");
cvar_t sv_floodprotect_sendmessage = CVARAF("sv_floodprotect_sendmessage", "",
"floodprotmsg", 0);
cvar_t votelevel = SCVAR("votelevel", "0");
cvar_t voteminimum = SCVAR("voteminimum", "4");
cvar_t votepercent = SCVAR("votepercent", "-1");
cvar_t votetime = SCVAR("votetime", "10");
cvar_t votelevel = CVARD("votelevel", "0", "This is the restriction level of commands that players may vote for. You can reconfigure commands, cvars, or aliases individually. Additionally, aliases can be configured via aliaslevel to be executed at a different level from their restriction level. This can be used to indirectly allow voting for 'map dm4' for instance, without allowing people to vote for every map.");
cvar_t voteminimum = CVARD("voteminimum", "4", "At least this many players must vote the same way for the vote to pass.");
cvar_t votepercent = CVARD("votepercent", "-1", "At least this percentage of players must vote the same way for the vote to pass.");
cvar_t votetime = CVARD("votetime", "10", "Votes will be discarded after this many minutes");
cvar_t pr_allowbutton1 = CVARFD("pr_allowbutton1", "1", CVAR_LATCH, "The button1 field is believed to have been intended to work with the +use command, but it was never hooked up. In NetQuake, this field was often repurposed for other things as it was not otherwise used (and cannot be removed without breaking the crc), while third-party QuakeWorld engines did decide to implement it as believed was intended. As a result, this cvar only applies to QuakeWorld mods and a value of 1 is only likely to cause issues with NQ mods that were ported to QW.");
extern cvar_t sv_minping;
@ -445,13 +445,15 @@ void SV_New_f (void)
void SVNQ_New_f (void)
{
extern cvar_t coop;
char message[2048];
int i;
int maxplayers = 0;
int op;
char message[2048];
char build[256], mapname[128];
int i;
int maxplayers = 0;
int op;
unsigned int protext1 = 0, protext2 = 0, protmain = 0, protfl = 0;
char *protoname;
extern cvar_t sv_listen_nq;
const char *gamedir;
host_client->prespawn_stage = PRESPAWN_INVALID;
host_client->prespawn_idx = 0;
@ -554,8 +556,28 @@ void SVNQ_New_f (void)
break;
}
#ifdef OFFICIAL_RELEASE
Q_snprintfz(build, sizeof(build), "v%i.%02i", FTE_VER_MAJOR, FTE_VER_MINOR);
#else
#if defined(SVNREVISION)
if (strcmp(STRINGIFY(SVNREVISION), "-"))
Q_snprintfz(build, sizeof(build), "SVN %s", STRINGIFY(SVNREVISION));
else
#endif
Q_snprintfz(build, sizeof(build), "%s", __DATE__);
#endif
gamedir = Info_ValueForKey (svs.info, "*gamedir");
if (!gamedir[0])
{
gamedir = FS_GetGamedir(true);
}
COM_FileBase(sv.modelname, mapname, sizeof(mapname));
Q_snprintfz (message, sizeof(message), "%c\n%s - "DISTRIBUTION" (%s%s%s%s %s) - %s", 2, gamedir,
protoname,(protext1||(protext2&~(PEXT2_REPLACEMENTDELTAS|PEXT2_VOICECHAT)))?"+":"",(protext2&PEXT2_REPLACEMENTDELTAS)?"F":"",(protext2&PEXT2_VOICECHAT)?"V":"",
build, mapname);
MSG_WriteByte (&host_client->netchan.message, svc_print);
Q_snprintfz (message, sizeof(message), "%c\n%s %s%s%s%s server\n", 2, version_string(), (protext2&PEXT2_REPLACEMENTDELTAS)?"FTE":"", protoname, (protext1||(protext2&~(PEXT2_REPLACEMENTDELTAS|PEXT2_VOICECHAT)))?"+":"", (protext2&PEXT2_VOICECHAT)?"V":"");
MSG_WriteString (&host_client->netchan.message,message);
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7)
@ -4145,12 +4167,23 @@ void SV_Vote_f (void)
if (!votelevel.value || ((host_client->penalties & (BAN_MUTE|BAN_DEAF)) == (BAN_MUTE|BAN_DEAF)))
{
SV_ClientTPrintf(host_client, PRINT_HIGH, "Voting was dissallowed\n");
SV_ClientTPrintf(host_client, PRINT_HIGH, "Voting is dissallowed on this server\n");
return;
}
if (!*command)
{
char cmds[900];
Cmd_EnumerateLevel(votelevel.value, cmds, sizeof(cmds));
SV_ClientTPrintf(host_client, PRINT_HIGH, "Allowed commands:\n%s\n", cmds);
return;
}
if (host_client->penalties & BAN_MUTE)
{
SV_ClientTPrintf(host_client, PRINT_HIGH, "Sorry, you cannot vote when muted as it may allow you to send a message.\n");
//pretend to vote for it
if (host_client->penalties & BAN_STEALTH)
SV_ClientTPrintf(host_client, PRINT_HIGH, "%s casts a vote for '%s'\n", host_client->name, command);
else
SV_ClientTPrintf(host_client, PRINT_HIGH, "Sorry, you cannot vote when muted as it may allow you to send a message.\n");
return;
}
@ -5591,7 +5624,7 @@ ucmd_t ucmdsq2[] = {
{"nextserver", SVQ2_NextServer_f, true},
{"vote", SV_Vote_f, true},
{"ftevote", SV_Vote_f, true},
//#ifdef SVRANKING
// {"topten", Rank_ListTop10_f, true},
@ -6930,10 +6963,18 @@ done:
args[i] = 0;
rname = MSG_ReadString();
if (i)
rname = va("Cmd_%s_%s", rname, args);
rname = va("CSEv_%s_%s", rname, args);
else
rname = va("Cmd_%s", rname);
rname = va("CSEv_%s", rname);
f = PR_FindFunction(svprogfuncs, rname, PR_ANY);
if (!f)
{
if (i)
rname = va("Cmd_%s_%s", rname, args);
else
rname = va("Cmd_%s", rname);
f = PR_FindFunction(svprogfuncs, rname, PR_ANY);
}
if (f)
{
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player);

View file

@ -75,7 +75,6 @@ void HUD_Plus_f(void)
{
char *t;
hud_t *hud;
char buf[64];
if (Cmd_Argc() < 1)
return;

View file

@ -436,7 +436,9 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(GetPlayerInfo);
CHECKBUILTIN(LocalPlayerNumber);
CHECKBUILTIN(GetLocalPlayerNumbers);
#ifdef FTEPLUGIN
CHECKBUILTIN(GetLastInputFrame);
#endif
CHECKBUILTIN(GetTrackerOwnFrags);
CHECKBUILTIN(GetServerInfo);
CHECKBUILTIN(SetUserInfo);