some Q2 compat tweaks. moved all q2 temp-ents to particle scripts.

PF_VarString can now shortcircuit, directly returning the first argument (which also bypasses related length limitations). this required const correctness fixes.
r_showshaders cvar reports the wall texture being pointed at.
improve dp compat in a number of areas, should now mostly be able to run xonotic 0.8.2, but will need some more extra cvars/defaults/stuff.
fix q3bsp loader race condition.
fix dpm loader multi-surface issue.
remove limit on stringbuffer count.
don't poll xinput (because its disturbingly slow), instead wait for some window message before re-checking.
fixed splitscreen saved games.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5140 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-08-14 16:38:44 +00:00
parent 0a6cbdf39a
commit c4d3497054
95 changed files with 3417 additions and 2308 deletions

View File

@ -1980,7 +1980,7 @@ static int QDECL CompleteDemoList (const char *name, qofs_t flags, time_t mtime,
ctx->cb(name, ctx);
return true;
}
void CL_DemoList_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx)
void CL_DemoList_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
if (argn == 1)
{

View File

@ -2647,7 +2647,7 @@ void CL_Reconnect_f (void)
if (cls.download && cls.download->method <= DL_QWPENDING) // don't change when downloading
return;
#ifdef NQPROT
if (cls.protocol == CP_NETQUAKE && Cmd_FromGamecode())
if (cls.protocol == CP_NETQUAKE && Cmd_IsInsecure())
{
CL_Changing_f();
return;
@ -5505,7 +5505,7 @@ double Host_Frame (double time)
{
//nq can send 'frames' without any entities before we're on the server, leading to short periods where the local player's position is not known. this is bad. so be more cautious with nq. this might break csqc.
CL_TransitionEntities();
if (cl.currentpackentities->num_entities
if (cl.currentpackentities->num_entities || cl.currentpackentities->servertime
#ifdef CSQC_DAT
|| (cls.fteprotocolextensions & PEXT_CSQC)
#endif

View File

@ -4972,6 +4972,7 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
{
int i;
char *col;
int ospec = player->spectator;
Q_strncpyz (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name));
Q_strncpyz (player->team, Info_ValueForKey (player->userinfo, "team"), sizeof(player->team));
@ -5029,7 +5030,8 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
}
// Update the rules since spectators can bypass everything but players can't
CL_CheckServerInfo();
if (ospec != player->spectator)
CL_CheckServerInfo();
Skin_FlushPlayers();
}
@ -5378,223 +5380,6 @@ static void CL_MuzzleFlash (int entnum)
}
}
#ifdef Q2CLIENT
void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs);
static void CLQ2_ParseMuzzleFlash (void)
{
vec3_t fv, rv, dummy;
dlight_t *dl;
int i, weapon;
vec3_t org, ang;
int silenced;
float volume;
char soundname[64];
i = (unsigned short)(short)MSG_ReadShort ();
if (i < 1 || i >= Q2MAX_EDICTS)
Host_Error ("CL_ParseMuzzleFlash: bad entity");
weapon = MSG_ReadByte ();
silenced = weapon & Q2MZ_SILENCED;
weapon &= ~Q2MZ_SILENCED;
CL_GetNumberedEntityInfo(i, org, ang);
dl = CL_AllocDlight (i);
VectorCopy (org, dl->origin);
AngleVectors (ang, fv, rv, dummy);
VectorMA (dl->origin, 18, fv, dl->origin);
VectorMA (dl->origin, 16, rv, dl->origin);
if (silenced)
dl->radius = 100 + (rand()&31);
else
dl->radius = 200 + (rand()&31);
dl->minlight = 32;
dl->die = cl.time+0.05; //+ 0.1;
dl->decay = 1;
dl->channelfade[0] = 2;
dl->channelfade[1] = 2;
dl->channelfade[2] = 2;
if (silenced)
volume = 0.2;
else
volume = 1;
switch (weapon)
{
case Q2MZ_BLASTER:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_BLUEHYPERBLASTER:
dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_HYPERBLASTER:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_MACHINEGUN:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
break;
case Q2MZ_SHOTGUN:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case Q2MZ_SSHOTGUN:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_CHAINGUN1:
dl->radius = 200 + (rand()&31);
dl->color[0] = 1;dl->color[1] = 0.25;dl->color[2] = 0;
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
break;
case Q2MZ_CHAINGUN2:
dl->radius = 225 + (rand()&31);
dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
dl->die = cl.time + 0.1; // long delay
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.05);
break;
case Q2MZ_CHAINGUN3:
dl->radius = 250 + (rand()&31);
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
dl->die = cl.time + 0.1; // long delay
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.033);
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.066);
break;
case Q2MZ_RAILGUN:
dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_ROCKET:
dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case Q2MZ_GRENADE:
dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case Q2MZ_BFG:
dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_LOGIN:
dl->color[0] = 0;dl->color[1] = 1; dl->color[2] = 0;
dl->die = cl.time + 1.0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
// CL_LogoutEffect (pl->current.origin, weapon);
break;
case Q2MZ_LOGOUT:
dl->color[0] = 1;dl->color[1] = 0; dl->color[2] = 0;
dl->die = cl.time + 1.0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
// CL_LogoutEffect (pl->current.origin, weapon);
break;
case Q2MZ_RESPAWN:
dl->color[0] = 1;dl->color[1] = 1; dl->color[2] = 0;
dl->die = cl.time + 1.0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
// CL_LogoutEffect (pl->current.origin, weapon);
break;
// RAFAEL
case Q2MZ_PHALANX:
dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/plasshot.wav"), volume, ATTN_NORM, 0);
break;
// RAFAEL
case Q2MZ_IONRIPPER:
dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0);
break;
// ======================
// PGM
case Q2MZ_ETF_RIFLE:
dl->color[0] = 0.9;dl->color[1] = 0.7;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/nail1.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_SHOTGUN2:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_HEATBEAM:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
dl->die = cl.time + 100;
// Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/bfg__l1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_BLASTER2:
dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
// FIXME - different sound for blaster2 ??
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_TRACKER:
// negative flashes handled the same in gl/soft until CL_AddDLights
dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/disint2.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_NUKE1:
dl->color[0] = 1;dl->color[1] = 0;dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case Q2MZ_NUKE2:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case Q2MZ_NUKE4:
dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
dl->die = cl.time + 100;
break;
case Q2MZ_NUKE8:
dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 1;
dl->die = cl.time + 100;
break;
// PGM
// ======================
}
}
static void CLQ2_ParseMuzzleFlash2 (void)
{
int ent;
int flash_number;
ent = (unsigned short)(short)MSG_ReadShort ();
if (ent < 1 || ent >= Q2MAX_EDICTS)
Host_EndGame ("CL_ParseMuzzleFlash2: bad entity");
flash_number = MSG_ReadByte ();
CLQ2_RunMuzzleFlash2(ent, flash_number);
}
static void CLQ2_ParseInventory (int seat)
{
unsigned int i;
for (i=0 ; i<Q2MAX_ITEMS ; i++)
cl.inventory[seat][i] = MSG_ReadShort ();
}
#endif
//return if we want to print the message.
static char *CL_ParseChat(char *text, player_info_t **player, int *msgflags)
{
@ -6249,9 +6034,9 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds
{
*msg = '\0';
Con_DLPrintf((cls.state==ca_active)?1:2, "stufftext: %s\n", stufftext);
if (!strncmp(stufftext, "fullserverinfo ", 15))
if (!strncmp(stufftext, "fullserverinfo ", 15) || !strncmp(stufftext, "//fullserverinfo ", 17))
{
Cmd_TokenizeString(stufftext, false, false);
Cmd_TokenizeString(stufftext+2, false, false);
if (Cmd_Argc() == 2)
{
cl.haveserverinfo = true;
@ -6624,6 +6409,7 @@ void CLQW_ParseServerMessage (void)
char *s;
int i, j;
int destsplit;
vec3_t ang;
float f;
qboolean csqcpacket = false;
inframe_t *inf;
@ -6800,33 +6586,41 @@ void CLQW_ParseServerMessage (void)
#endif
case svcfte_setangledelta:
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] += MSG_ReadAngle16 ();
ang[i] = cl.playerview[destsplit].viewangles[i] + MSG_ReadAngle16 ();
if (!CSQC_Parse_SetAngles(destsplit, ang, true))
VectorCopy (ang, cl.playerview[destsplit].viewangles);
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles);
break;
case svc_setangle:
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
//I really don't get the point of fixangles in an mvd. to disable interpolation for that frame?
vec3_t ang;
i = MSG_ReadByte();
//I really don't get the point of fixangles in an mvd. just to disable interpolation for that frame?
int pl = MSG_ReadByte();
for (i=0 ; i<3 ; i++)
ang[i] = MSG_ReadAngle();
for (j = 0; j < cl.splitclients; j++)
{
playerview_t *pv = &cl.playerview[j];
if (Cam_TrackNum(pv) == i)
if (Cam_TrackNum(pv) == pl)
{
inf->packet_entities.fixangles[j] = true;
VectorCopy(ang, inf->packet_entities.fixedangles[j]);
}
}
break;
}
inf->packet_entities.fixangles[destsplit] = true;
for (i=0 ; i<3 ; i++)
else
{
cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].intermissionangles[i] = inf->packet_entities.fixedangles[destsplit][i] = MSG_ReadAngle ();
inframe_t *inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK];
for (i=0 ; i<3 ; i++)
ang[i] = MSG_ReadAngle();
if (!CSQC_Parse_SetAngles(destsplit, ang, false))
{
inf->packet_entities.fixangles[destsplit] = true;
VectorCopy (ang, cl.playerview[destsplit].viewangles);
VectorCopy (ang, inf->packet_entities.fixedangles[destsplit]);
}
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles);
}
break;
@ -7648,6 +7442,7 @@ void CLNQ_ParseServerMessage (void)
int cmd;
char *s;
int i, j;
vec3_t ang;
// received_framecount = host_framecount;
// cl.last_servermessage = realtime;
@ -7945,11 +7740,16 @@ void CLNQ_ParseServerMessage (void)
a = MSG_ReadByte ();
if (i < cl.allocated_client_slots)
{
cl.players[i].rtopcolor = a&0x0f;
cl.players[i].rbottomcolor = (a&0xf0)>>4;
CLNQ_CheckPlayerIsSpectator(i);
// cl.players[i].rtopcolor = a&0x0f;
// cl.players[i].rbottomcolor = (a&0xf0)>>4;
// sprintf(cl.players[i].team, "%2d", cl.players[i].rbottomcolor);
sprintf(cl.players[i].team, "%2d", cl.players[i].rbottomcolor);
Info_SetValueForKey(cl.players[i].userinfo, "topcolor", va("%i", a&0x0f), sizeof(cl.players[i].userinfo));
Info_SetValueForKey(cl.players[i].userinfo, "bottomcolor", va("%i", (a&0xf0)>>4), sizeof(cl.players[i].userinfo));
Info_SetValueForKey(cl.players[i].userinfo, "team", va("%i", (a&0xf0)>>4), sizeof(cl.players[i].userinfo));
CL_ProcessUserInfo (i, &cl.players[i]);
// CLNQ_CheckPlayerIsSpectator(i);
if (cls.state == ca_active)
Skin_Find (&cl.players[i]);
@ -7996,16 +7796,24 @@ void CLNQ_ParseServerMessage (void)
break;
case svcfte_setangledelta:
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] += MSG_ReadAngle16 ();
ang[i] = cl.playerview[destsplit].viewangles[i] + MSG_ReadAngle16 ();
if (!CSQC_Parse_SetAngles(destsplit, ang, true))
VectorCopy (ang, cl.playerview[destsplit].viewangles);
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles);
break;
case svc_setangle:
{
inframe_t *inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK];
inf->packet_entities.fixangles[destsplit] = true;
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].intermissionangles[i] = inf->packet_entities.fixedangles[destsplit][i] = MSG_ReadAngle ();
ang[i] = MSG_ReadAngle();
if (!CSQC_Parse_SetAngles(destsplit, ang, false))
{
inf->packet_entities.fixangles[destsplit] = true;
VectorCopy (ang, cl.playerview[destsplit].viewangles);
VectorCopy (ang, inf->packet_entities.fixedangles[destsplit]);
}
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles);
}
break;

View File

@ -378,7 +378,7 @@ Called for important messages that should stay in the center of the screen
for a few moments
==============
*/
void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
{
size_t i;
cprint_t *p;
@ -486,7 +486,7 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
}
else if (str[1] == 'I')
{
char *e;
const char *e;
int l;
str+=2;
e = strchr(str, ':');

View File

@ -57,8 +57,8 @@ static const char *q2efnames[] =
"TEQ2_PLASMA_EXPLOSION",
"TEQ2_TUNNEL_SPARKS",
"TEQ2_BLASTER2",
"TEQ2_RAILTRAIL2",
"TEQ2_FLAME",
"TEQ2_RAILTRAIL2", //not implemented in vanilla
NULL,//"TEQ2_FLAME", //not implemented in vanilla
NULL,//"TEQ2_LIGHTNING",
"TEQ2_DEBUGTRAIL",
"TEQ2_PLAIN_EXPLOSION",
@ -2493,795 +2493,6 @@ static struct{
{0xe8, "q2part.te_splashblood"}
};
#define ATTN_NONE 0
#define ATTN_NORM 1
#define ATTN_STATIC 1
void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float delay)
{
S_StartSound(entnum, entchannel, sfx, origin, NULL, fvol, attenuation, -delay, 0, 0);
}
static qboolean CLQ2_ParseTEnt_RemoveMe(q2particleeffects_t type)
{ //FIXME: this function needs to die, once we're sure its no longer needed.
vec3_t pos, pos2, dir;
explosion_t *ex;
int cnt;
int color;
int r;
Con_DPrintf("Q2TE legacy code: te %i\n", type);
switch(type)
{
case Q2TE_BLOOD: // bullet hitting flesh
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLOOD]))
if (P_RunParticleEffectType(pos, dir, 1, ptqw_blood))
P_RunParticleEffect(pos, dir, 0xe8, 60);
if (cl_legacystains.ival) Surf_AddStain(pos, 0, -10, -10, 40);
break;
case Q2TE_GUNSHOT: // bullet hitting wall
case Q2TE_SPARKS:
case Q2TE_BULLET_SPARKS:
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (type == Q2TE_GUNSHOT)
P_RunParticleEffect (pos, dir, 0, 40);
else
P_RunParticleEffect (pos, dir, 0xe0, 6);
if (cl_legacystains.ival) Surf_AddStain(pos, -10, -10, -10, 20);
if (type != Q2TE_SPARKS)
{
CL_SmokeAndFlash(pos);
// impact sound (nope, not the same as Q1...)
cnt = rand()&15;
if (cnt == 1)
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/ric1.wav"), 1, ATTN_NORM, 0);
else if (cnt == 2)
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/ric2.wav"), 1, ATTN_NORM, 0);
else if (cnt == 3)
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/ric3.wav"), 1, ATTN_NORM, 0);
}
break;
case Q2TE_SCREEN_SPARKS:
case Q2TE_SHIELD_SPARKS:
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (type == Q2TE_SCREEN_SPARKS)
P_RunParticleEffect (pos, dir, 0xd0, 40);
else
P_RunParticleEffect (pos, dir, 0xb0, 40);
//FIXME : replace or remove this sound
S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0);
break;
case Q2TE_SHOTGUN: // bullet hitting wall
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffect (pos, dir, 0, 20);
CL_SmokeAndFlash(pos);
if (cl_legacystains.ival) Surf_AddStain(pos, -10, -10, -10, 20);
break;
case Q2TE_SPLASH: // bullet hitting water
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
r = MSG_ReadByte ();
if (r > sizeof(q2splash_info)/sizeof(q2splash_info[0]))
r = 0;
if (P_RunParticleEffectType(pos, dir, cnt, pt_q2[Q2SPLASH_UNKNOWN+r]))
P_RunParticleEffect (pos, dir, q2splash_info[r].colour, cnt);
if (r == Q2SPLASH_SPARKS)
{
r = rand() & 3;
if (r == 1)
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/spark5.wav"), 1, ATTN_NORM, 0);
else if (r == 2)
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/spark6.wav"), 1, ATTN_NORM, 0);
else
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("world/spark7.wav"), 1, ATTN_NORM, 0);
}
break;
case Q2TE_LASER_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
P_RunParticleEffect (pos, dir, color, cnt);
break;
// RAFAEL
case Q2TE_BLUEHYPERBLASTER:
MSG_ReadPos (pos);
MSG_ReadPos (dir);
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLUEHYPERBLASTER]))
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLASTER]))
P_RunParticleEffect (pos, dir, 0xe0, 40);
break;
case Q2TE_BLASTER: // blaster hitting wall
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLASTER]))
P_RunParticleEffect (pos, dir, 0xe0, 40);
if (cl_legacystains.ival) Surf_AddStain(pos, 0, -5, -10, 20);
ex = CL_AllocExplosion (pos);
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, MLV_WARN);
ex->firstframe = 0;
ex->numframes = 4;
ex->flags = Q2RF_FULLBRIGHT|RF_ADDITIVE|RF_NOSHADOW|RF_TRANSLUCENT;
ex->angles[0] = acos(dir[2])/M_PI*180;
// PMM - fixed to correct for pitch of 0
if (dir[0])
ex->angles[1] = atan2(dir[1], dir[0])/M_PI*180;
else if (dir[1] > 0)
ex->angles[1] = 90;
else if (dir[1] < 0)
ex->angles[1] = 270;
else
ex->angles[1] = 0;
ex->angles[0]*=r_meshpitch.value;
S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0);
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 * r_explosionlight.value;
dl->die = cl.time + 0.4;
dl->decay = 400;
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 0.0;
dl->channelfade[0] = 0.5;
dl->channelfade[1] = 0.51;
dl->channelfade[2] = 0.0;
}
break;
case Q2TE_RAILTRAIL: // railgun effect
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_RAILTRAIL], 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, P_INVALID, 0x74, 8, NULL);
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/railgf1a.wav"), 1, ATTN_NORM, 0);
break;
case Q2TE_EXPLOSION2:
case Q2TE_GRENADE_EXPLOSION:
case Q2TE_GRENADE_EXPLOSION_WATER:
MSG_ReadPos (pos);
if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
P_RunParticleEffect(pos, NULL, 0xe0, 256);
if (cl_legacystains.ival) Surf_AddStain(pos, -1, -1, -1, 100);
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 + r_explosionlight.value*200;
dl->die = cl.time + 0.5;
dl->decay = 300;
dl->color[0] = 1.0;
dl->color[1] = 0.5;
dl->color[2] = 0.5;
dl->channelfade[0] = 0.36;
dl->channelfade[1] = 0.19;
dl->channelfade[2] = 0.19;
}
// sound
if (type == Q2TE_GRENADE_EXPLOSION_WATER)
S_StartSound (0, 0, S_PrecacheSound ("weapons/xpld_wat.wav"), pos, NULL, 1, 1, 0, 0, 0);
else
S_StartSound (0, 0, S_PrecacheSound ("weapons/grenlx1a.wav"), pos, NULL, 1, 1, 0, 0, 0);
// sprite
// if (!R_ParticleExplosionHeart(pos))
{
ex = CL_AllocExplosion (pos);
VectorClear(ex->angles);
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explo4].modelname, MLV_WARN);
ex->firstframe = 30;
ex->flags |= RF_TRANSLUCENT;
ex->numframes = 19;
ex->skinnum = -1;
}
break;
/*
ex = CL_AllocExplosion ();
VectorCopy (pos, ex->ent.origin);
ex->type = ex_poly;
ex->ent.flags = RF_FULLBRIGHT;
ex->start = cl.frame.servertime - 100;
ex->light = 350;
ex->lightcolor[0] = 1.0;
ex->lightcolor[1] = 0.5;
ex->lightcolor[2] = 0.5;
ex->ent.model = cl_mod_explo4;
ex->frames = 19;
ex->baseframe = 30;
ex->ent.angles[1] = rand() % 360;
CL_ExplosionParticles (pos);
if (type == TE_GRENADE_EXPLOSION_WATER)
Q2S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
else
Q2S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
break;
*/
// RAFAEL
case Q2TE_PLASMA_EXPLOSION:
MSG_ReadPos (pos);
/* ex = CL_AllocExplosion ();
VectorCopy (pos, ex->ent.origin);
ex->type = ex_poly;
ex->ent.flags = RF_FULLBRIGHT;
ex->start = cl.frame.servertime - 100;
ex->light = 350;
ex->lightcolor[0] = 1.0;
ex->lightcolor[1] = 0.5;
ex->lightcolor[2] = 0.5;
ex->ent.angles[1] = rand() % 360;
ex->ent.model = cl_mod_explo4;
if (frand() < 0.5)
ex->baseframe = 15;
ex->frames = 15;
CL_ExplosionParticles (pos);
Q2S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
*/ break;
case Q2TE_EXPLOSION1:
case Q2TE_EXPLOSION1_BIG: // PMM
case Q2TE_ROCKET_EXPLOSION:
case Q2TE_ROCKET_EXPLOSION_WATER:
case Q2TE_EXPLOSION1_NP: // PMM
MSG_ReadPos (pos);
// particle effect
if (type != Q2TE_EXPLOSION1_BIG && type != Q2TE_EXPLOSION1_NP)
{
if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
P_RunParticleEffect(pos, NULL, 0xe0, 256);
if (cl_legacystains.ival) Surf_AddStain(pos, -1, -1, -1, 100);
}
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 + r_explosionlight.value*200;
dl->die = cl.time + 0.5;
dl->decay = 300;
dl->color[0] = 1.0;
dl->color[1] = 0.5;
dl->color[2] = 0.4;
dl->channelfade[0] = 0.36;
dl->channelfade[1] = 0.19;
dl->channelfade[2] = 0.19;
}
// sound
if (type == Q2TE_ROCKET_EXPLOSION_WATER)
S_StartSound (0, 0, S_PrecacheSound ("weapons/xpld_wat.wav"), pos, NULL, 1, 1, 0, 0, 0);
else
S_StartSound (0, 0, S_PrecacheSound ("weapons/rocklx1a.wav"), pos, NULL, 1, 1, 0, 0, 0);
// sprite
// if (!R_ParticleExplosionHeart(pos))
{
ex = CL_AllocExplosion (pos);
VectorClear(ex->angles);
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explo4].modelname, MLV_WARN);
ex->flags |= RF_TRANSLUCENT;
if (rand()&1)
ex->firstframe = 15;
else
ex->firstframe = 0;
ex->numframes = 15;
ex->skinnum = -1;
}
break;
/*
ex = CL_AllocExplosion ();
VectorCopy (pos, ex->ent.origin);
ex->type = ex_poly;
ex->ent.flags = RF_FULLBRIGHT;
ex->start = cl.frame.servertime - 100;
ex->light = 350;
ex->lightcolor[0] = 1.0;
ex->lightcolor[1] = 0.5;
ex->lightcolor[2] = 0.5;
ex->ent.angles[1] = rand() % 360;
if (type != TE_EXPLOSION1_BIG) // PMM
ex->ent.model = cl_mod_explo4; // PMM
else
ex->ent.model = cl_mod_explo4_big;
if (frand() < 0.5)
ex->baseframe = 15;
ex->frames = 15;
if ((type != TE_EXPLOSION1_BIG) && (type != TE_EXPLOSION1_NP)) // PMM
CL_ExplosionParticles (pos); // PMM
if (type == TE_ROCKET_EXPLOSION_WATER)
Q2S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
else
Q2S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
break;
*/ case Q2TE_BFG_EXPLOSION:
MSG_ReadPos (pos);
/* ex = CL_AllocExplosion ();
VectorCopy (pos, ex->ent.origin);
ex->type = ex_poly;
ex->flags = RF_FULLBRIGHT;
ex->start = cl.q2frame.servertime - 100;
ex->light = 350;
ex->lightcolor[0] = 0.0;
ex->lightcolor[1] = 1.0;
ex->lightcolor[2] = 0.0;
ex->model = cl_mod_bfg_explo;
ex->flags |= RF_TRANSLUCENT;
ex->alpha = 0.30;
ex->frames = 4;
*/ break;
case Q2TE_BFG_BIGEXPLOSION:
MSG_ReadPos (pos);
// CL_BFGExplosionParticles (pos);
if (P_RunParticleEffectTypeString(pos, dir, 1, "te_bfg_bigexplosion"))
P_RunParticleEffect(pos, dir, 0xd0, 256); // TODO: x+(r%8) unstead of x&7+(r&7)
break;
case Q2TE_BFG_LASER:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
CL_Laser(pos, pos2, 0xd0d1d2d3);
break;
case Q2TE_BUBBLETRAIL:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_BUBBLETRAIL], 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, P_INVALID, 4, 8, NULL);
break;
case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (BT_Q2PARASITE);
break;
case Q2TE_BOSSTPORT: // boss teleporting to station
MSG_ReadPos (pos);
/* CL_BigTeleportParticles (pos);
*/ Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0);
break;
case Q2TE_GRAPPLE_CABLE:
CL_ParseBeam (BT_Q2GRAPPLE);
MSG_ReadPos (pos);
break;
// RAFAEL
case Q2TE_WELDING_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
// TODO: fix to Q2's standards
P_RunParticleEffect(pos, dir, color, cnt);
/* CL_ParticleEffect2 (pos, dir, color, cnt);
ex = CL_AllocExplosion ();
VectorCopy (pos, ex->ent.origin);
ex->type = ex_flash;
// note to self
// we need a better no draw flag
ex->ent.flags = RF_BEAM;
ex->start = cl.frame.servertime - 0.1;
ex->light = 100 + (rand()%75);
ex->lightcolor[0] = 1.0;
ex->lightcolor[1] = 1.0;
ex->lightcolor[2] = 0.3;
ex->ent.model = cl_mod_flash;
ex->frames = 2;
*/ break;
case Q2TE_GREENBLOOD:
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (P_RunParticleEffectTypeString(pos, dir, 1, "te_greenblood"))
P_RunParticleEffect(pos, dir, 0xdf, 30); // TODO: x+(r%8) unstead of x&7+(r&7)
// CL_ParticleEffect2 (pos, dir, 0xdf, 30);
break;
// RAFAEL
case Q2TE_TUNNEL_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
// CL_ParticleEffect3 (pos, dir, color, cnt);
break;
//=============
//PGM
// PMM -following code integrated for flechette (different color)
case Q2TE_BLASTER2: // green blaster hitting wall
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLASTER2]))
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLASTER]))
P_RunParticleEffect (pos, dir, 0xd0, 40);
if (cl_legacystains.ival) Surf_AddStain(pos, -10, 0, -10, 20);
ex = CL_AllocExplosion (pos);
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, MLV_WARN);
ex->firstframe = 0;
ex->numframes = 4;
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->angles[0] = acos(dir[2])/M_PI*180;
// PMM - fixed to correct for pitch of 0
if (dir[0])
ex->angles[1] = atan2(dir[1], dir[0])/M_PI*180;
else if (dir[1] > 0)
ex->angles[1] = 90;
else if (dir[1] < 0)
ex->angles[1] = 270;
else
ex->angles[1] = 0;
ex->angles[0]*=r_meshpitch.value;
S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0);
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 * r_explosionlight.value;
dl->die = cl.time + 0.4;
dl->decay = 400;
dl->color[0] = 0.05;
dl->color[1] = 1.0;
dl->color[2] = 0.05;
dl->channelfade[0] = 0.1;
dl->channelfade[1] = 0.5;
dl->channelfade[2] = 0.1;
}
break;
case Q2TE_FLECHETTE: // blue blaster effect
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_FLECHETTE]))
if (P_RunParticleEffectType(pos, dir, 1, pt_q2[Q2TE_BLASTER]))
P_RunParticleEffect (pos, dir, 0x6f, 40);
if (cl_legacystains.ival) Surf_AddStain(pos, -10, -2, 0, 20);
ex = CL_AllocExplosion (pos);
ex->start = cl.time;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, MLV_WARN);
ex->firstframe = 0;
ex->numframes = 4;
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->angles[0] = acos(dir[2])/M_PI*180;
// PMM - fixed to correct for pitch of 0
if (dir[0])
ex->angles[1] = atan2(dir[1], dir[0])/M_PI*180;
else if (dir[1] > 0)
ex->angles[1] = 90;
else if (dir[1] < 0)
ex->angles[1] = 270;
else
ex->angles[1] = 0;
ex->angles[0]*=r_meshpitch.value;
S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0);
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 * r_explosionlight.value;
dl->die = cl.time + 0.4;
dl->decay = 400;
dl->color[0] = 0.19;
dl->color[1] = 0.41;
dl->color[2] = 0.75;
dl->channelfade[0] = 0.085;
dl->channelfade[1] = 0.180;
dl->channelfade[2] = 0.300;
}
break;
case Q2TE_LIGHTNING:
CL_ParseBeam(BT_Q1LIGHTNING1);
Q2S_StartSound (pos, 0, 0, S_PrecacheSound("weapons/tesla.wav"), 1, ATTN_NORM, 0);
break;
case Q2TE_DEBUGTRAIL:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, P_INVALID, 116, 8, NULL);
break;
case Q2TE_PLAIN_EXPLOSION:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
// ex->type = ex_poly;
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->angles[1] = rand() % 360;
ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explo4].modelname, MLV_WARN);
if (rand() < RAND_MAX/2)
ex->firstframe = 15;
ex->numframes = 15;
Q2S_StartSound (pos, 0, 0, S_PrecacheSound("weapons/rocklx1a.wav"), 1, ATTN_NORM, 0);
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 + r_explosionlight.value*200;
dl->die = cl.time + 0.5;
dl->decay = 300;
dl->color[0] = 1.0;
dl->color[1] = 0.5;
dl->color[2] = 0.4;
dl->channelfade[0] = 0.36;
dl->channelfade[1] = 0.19;
dl->channelfade[2] = 0.19;
}
break;
/*
case Q2TE_FLASHLIGHT:
MSG_ReadPos(&net_message, pos);
ent = MSG_ReadShort(&net_message);
CL_Flashlight(ent, pos);
break;
case Q2TE_FORCEWALL:
MSG_ReadPos(&net_message, pos);
MSG_ReadPos(&net_message, pos2);
color = MSG_ReadByte (&net_message);
CL_ForceWall(pos, pos2, color);
break;
*/
case Q2TE_HEATBEAM:
MSG_ReadPos(pos);
MSG_ReadPos(pos2);
// ent = CL_ParsePlayerBeam (cl_mod_heatbeam);
break;
/*
case Q2TE_MONSTER_HEATBEAM:
ent = CL_ParsePlayerBeam (cl_mod_monster_heatbeam);
break;
case Q2TE_HEATBEAM_SPARKS:
// cnt = MSG_ReadByte (&net_message);
cnt = 50;
MSG_ReadPos (&net_message, pos);
MSG_ReadDir (&net_message, dir);
// r = MSG_ReadByte (&net_message);
// magnitude = MSG_ReadShort (&net_message);
r = 8;
magnitude = 60;
color = r & 0xff;
CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
break;
case Q2TE_HEATBEAM_STEAM:
// cnt = MSG_ReadByte (&net_message);
cnt = 20;
MSG_ReadPos (&net_message, pos);
MSG_ReadDir (&net_message, dir);
// r = MSG_ReadByte (&net_message);
// magnitude = MSG_ReadShort (&net_message);
// color = r & 0xff;
color = 0xe0;
magnitude = 60;
CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
break;
case Q2TE_STEAM:
CL_ParseSteam();
break;
case Q2TE_BUBBLETRAIL2:
// cnt = MSG_ReadByte (&net_message);
cnt = 8;
MSG_ReadPos (&net_message, pos);
MSG_ReadPos (&net_message, pos2);
CL_BubbleTrail2 (pos, pos2, cnt);
S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
break;
*/
case Q2TE_MOREBLOOD:
MSG_ReadPos (pos);
MSG_ReadDir (dir);
if (P_RunParticleEffectTypeString(pos, dir, 1, "te_moreblood"))
if (P_RunParticleEffectType(pos, dir, 4, ptqw_blood))
P_RunParticleEffect(pos, dir, 0xe8, 250);
break;
case Q2TE_CHAINFIST_SMOKE:
dir[0]=0; dir[1]=0; dir[2]=1;
MSG_ReadPos(pos);
P_RunParticleEffectTypeString(pos, NULL, 1, "TEQ2_CHAINFIST_SMOKE");
break;
case Q2TE_ELECTRIC_SPARKS:
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffect(pos, dir, 0x75, 40);
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/lashit.wav"), 1, ATTN_NORM, 0);
break;
case Q2TE_TRACKER_EXPLOSION:
MSG_ReadPos (pos);
// effect
if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_tracker_explosion"))
P_RunParticleEffect(pos, NULL, 0, 128); // TODO: needs to be nonrandom instead of 0+r%8
// light
// light
if (r_explosionlight.value)
{
dlight_t *dl;
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 * r_explosionlight.value;
dl->die = cl.time + 0.1;
dl->minlight = 250;
dl->color[0] = -1.0;
dl->color[1] = -1.0;
dl->color[2] = -1.0;
}
// sound
Q2S_StartSound (pos, 0, 0, S_PrecacheSound("weapons/disrupthit.wav"), 1, ATTN_NORM, 0);
break;
case Q2TE_TELEPORT_EFFECT:
case Q2TE_DBALL_GOAL:
MSG_ReadPos (pos);
if (P_RunParticleEffectType(pos, NULL, 1, pt_teleportsplash))
P_RunParticleEffect(pos, NULL, 8, 768);
// This effect won't match ---
// Color should be 7+(rand()%8)
// not 8&~7+(rand()%8)
break;
case Q2TE_WIDOWBEAMOUT:
// this one is really annoying, it's supposed to be a random choice
// between 2*8, 13*8, 21*8, 18*8, and it respreads every frame
// into a circle but it could be faked well enough, well except for
// the fact that these effects have ids associated with them
// sort of how beams have ents associated
MSG_ReadShort(); // id
if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_widowbeamout"))
P_RunParticleEffect(pos, NULL, 13*8, 300);
break;
case Q2TE_NUKEBLAST:
// same problem as te_widowbeamout, but colors are a bit easier to manage
// and there's no id to read in
MSG_ReadPos (pos);
if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_nukeblast"))
P_RunParticleEffect(pos, NULL, 110, 700);
break;
case Q2TE_WIDOWSPLASH:
// there's the color issue like with te_widowbeamout, but the particles
// are spawned in an immediate circle and not substained, so it's much
// easier to manage
MSG_ReadPos (pos);
if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_widowsplash"))
P_RunParticleEffect(pos, NULL, 13*8, 256);
break;
//PGM
//==============
case CRTE_LEADERBLASTER:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_BLASTER_MUZZLEFLASH:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0.1*5, 0*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_muzzleflash");
break;
case CRTE_BLUE_MUZZLEFLASH:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0.1*5, 0*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_blue_muzzleflash");
break;
case CRTE_SMART_MUZZLEFLASH:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0*5, 0.2*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_smart_muzzleflash");
break;
case CRTE_LEADERFIELD:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_DEATHFIELD:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
VectorCopy (pos, ex->origin);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0*5, 0.2*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_deathfield");
break;
case CRTE_BLASTERBEAM:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, P_FindParticleType("q2part.TR_BLASTERTRAIL2"), 0, NULL, NULL);
break;
/* case CRTE_STAIN:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_FIRE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_CABLEGUT:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_SMOKE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
*/
default:
return false;
}
return true;
}
void CLQ2_ParseTEnt (void)
{
beam_t *b;
@ -3293,19 +2504,12 @@ void CLQ2_ParseTEnt (void)
int r;
int ent;
// int magnitude;
explosion_t *ex;
type = MSG_ReadByte ();
if (type <= Q2TE_MAX)
{
pt = pt_q2[type];
if (pt == P_INVALID && q2efnames[type])
{
Con_Printf("Q2TE legacy code: te %i\n", type);
if (CLQ2_ParseTEnt_RemoveMe(type))
return;
}
}
else
pt = P_INVALID;
switch (type)
@ -3431,21 +2635,80 @@ void CLQ2_ParseTEnt (void)
P_ParticleTrailIndex(pos, pos2, pt, color, 0, NULL);
break;
case Q2TE_RAILTRAIL2:
case Q2TE_FLAME:
case Q2TE_FLASHLIGHT:
case Q2TE_WIDOWBEAMOUT:
case Q2TE_FLASHLIGHT: //white 400-radius dlight
MSG_ReadPos(pos);
ent = MSG_ReadShort();
P_ParticleTrail(pos, pos, pt, ent, NULL, NULL);
break;
case Q2TE_WIDOWBEAMOUT: /*requires state tracking to keep it splurting constantly for 2.1 secs*/
ent = MSG_ReadShort();
MSG_ReadPos(pos);
Con_Printf("FIXME: Q2TE_WIDOWBEAMOUT not implemented\n");
break;
case Q2TE_RAILTRAIL2: /*not implemented in vanilla*/
case Q2TE_FLAME: /*not implemented in vanilla*/
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
break;
//My old attempt at running AlienArena years ago. probably not enough now. Other engines will have other effects.
case CRTE_LEADERBLASTER:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_BLASTER_MUZZLEFLASH:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0.1*5, 0*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_muzzleflash");
break;
case CRTE_BLUE_MUZZLEFLASH:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0.1*5, 0*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_blue_muzzleflash");
break;
case CRTE_SMART_MUZZLEFLASH:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0*5, 0.2*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_smart_muzzleflash");
break;
case CRTE_LEADERFIELD:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_DEATHFIELD:
MSG_ReadPos (pos);
ex = CL_AllocExplosion (pos);
VectorCopy (pos, ex->origin);
ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW;
ex->start = cl.q2frame.servertime - 100;
CL_NewDlight(0, pos, 350, 0.5, 0.2*5, 0*5, 0.2*5);
P_RunParticleEffectTypeString(pos, NULL, 1, "te_deathfield");
break;
case CRTE_BLASTERBEAM:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, P_FindParticleType("q2part.TR_BLASTERTRAIL2"), 0, NULL, NULL);
break;
/* case CRTE_STAIN:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_FIRE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_CABLEGUT:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_SMOKE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
*/
#ifdef __GNUC__
case (Q2TE_FLECHETTE+1) ... Q2PT_MAX:
// case (Q2TE_MAX+1) ... Q2PT_MAX:
// default:
#else
default:
#endif
// Con_Printf("CLQ2_ParseTEnt: bad/non-implemented type %i\n", type);
if (!CLQ2_ParseTEnt_RemoveMe(type))
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
break;
}
}

View File

@ -576,7 +576,7 @@ struct q3refdef_s {
// text messages for deform text shaders
char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
};
void D3D9_Set2D (void);
void R_DrawNameTags(void);
void VQ3_RenderView(const q3refdef_t *ref)
{
int i;
@ -619,11 +619,12 @@ void VQ3_RenderView(const q3refdef_t *ref)
for (i = 0; i < MAX_MAP_AREA_BYTES/sizeof(int); i++)
((int*)r_refdef.areabits)[i] = ((int*)ref->areamask)[i] ^ ~0;
R_RenderView();
R_DrawNameTags();
r_refdef.playerview = NULL;
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
{
GL_Set2D (false);
// GL_Set2D (false);
}
#endif

View File

@ -114,7 +114,7 @@ typedef struct
short gravity;
short delta_angles[3]; // add to command angles to get view direction
// changed by spawns, rotating objects, and teleporters
// short pad;
short pad;
} q2pmove_state_t;
typedef struct
@ -1198,7 +1198,7 @@ void CL_WriteRecordQ2DemoMessage(sizebuf_t *msg);
void CL_Stop_f (void);
void CL_Record_f (void);
void CL_ReRecord_f (void);
void CL_DemoList_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx);
void CL_DemoList_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx);
void CL_PlayDemo_f (void);
void CL_QTVPlay_f (void);
void CL_QTVPoll (void);
@ -1380,12 +1380,13 @@ void CSQC_MapEntityEdited(int modelindex, int idx, const char *newe);
qboolean CSQC_LoadResource(char *resname, char *restype);
qboolean CSQC_ParsePrint(char *message, int printlevel);
qboolean CSQC_ParseGamePacket(void);
qboolean CSQC_CenterPrint(int lplayernum, char *cmd);
qboolean CSQC_Parse_Damage(float save, float take, vec3_t source);
void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd);
qboolean CSQC_CenterPrint(int seat, const char *cmd);
qboolean CSQC_Parse_Damage(int seat, float save, float take, vec3_t source);
qboolean CSQC_Parse_SetAngles(int seat, vec3_t newangles, qboolean wasdelta);
void CSQC_Input_Frame(int seat, usercmd_t *cmd);
void CSQC_WorldLoaded(void);
qboolean CSQC_ParseTempEntity(void);
qboolean CSQC_ConsoleCommand(char *cmd);
qboolean CSQC_ConsoleCommand(const char *cmd);
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, unsigned int devid);
qboolean CSQC_MouseMove(float xdelta, float ydelta, unsigned int devid);
qboolean CSQC_MousePosition(float xabs, float yabs, unsigned int devid);
@ -1537,7 +1538,9 @@ void CLQ2_ParseBaseline (void);
void CLQ2_ClearParticleState(void);
void CLR1Q2_ParsePlayerUpdate(void);
void CLQ2_ParseFrame (int extrabits);
void CLQ2_RunMuzzleFlash2 (int ent, int flash_number);
void CLQ2_ParseMuzzleFlash (void);
void CLQ2_ParseMuzzleFlash2 (void);
void CLQ2_ParseInventory (int seat);
int CLQ2_RegisterTEntModels (void);
void CLQ2_WriteDemoBaselines(sizebuf_t *buf);
#endif

View File

@ -81,9 +81,6 @@ float LerpAngle (float a2, float a1, float frac)
#define Q2MAX_STATS 32
void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs);
typedef struct q2centity_s
{
entity_state_t baseline; // delta from this if not from a previous frame
@ -100,6 +97,10 @@ typedef struct q2centity_s
float fly_stoptime;
} q2centity_t;
static void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float delay)
{
S_StartSound(entnum, entchannel, sfx, origin, NULL, fvol, attenuation, -delay, 0, 0);
}
sfx_t *S_PrecacheSexedSound(int entnum, const char *soundname)
{
if (soundname[0] == '*')
@ -214,6 +215,23 @@ entity_state_t clq2_parse_entities[MAX_PARSE_ENTITIES];
void CL_SmokeAndFlash(vec3_t origin);
void CL_GetNumberedEntityInfo (int num, float *org, float *ang)
{
q2centity_t *ent;
if (num < 0 || num >= MAX_Q2EDICTS)
Host_EndGame ("CL_GetNumberedEntityInfo: bad ent");
ent = &cl_entities[num];
if (org)
VectorCopy (ent->current.origin, org);
if (ang)
VectorCopy (ent->current.angles, ang);
// FIXME: bmodel issues...
}
void CLQ2_WriteDemoBaselines(sizebuf_t *buf)
{
int i;
@ -641,6 +659,220 @@ void CLQ2_RunMuzzleFlash2 (int ent, int flash_number)
}
}
void CLQ2_ParseMuzzleFlash (void)
{
vec3_t fv, rv, dummy;
dlight_t *dl;
int i, weapon;
vec3_t org, ang;
int silenced;
float volume;
char soundname[64];
i = (unsigned short)(short)MSG_ReadShort ();
if (i < 1 || i >= Q2MAX_EDICTS)
Host_Error ("CL_ParseMuzzleFlash: bad entity");
weapon = MSG_ReadByte ();
silenced = weapon & Q2MZ_SILENCED;
weapon &= ~Q2MZ_SILENCED;
CL_GetNumberedEntityInfo(i, org, ang);
dl = CL_AllocDlight (i);
VectorCopy (org, dl->origin);
AngleVectors (ang, fv, rv, dummy);
VectorMA (dl->origin, 18, fv, dl->origin);
VectorMA (dl->origin, 16, rv, dl->origin);
if (silenced)
dl->radius = 100 + (rand()&31);
else
dl->radius = 200 + (rand()&31);
dl->minlight = 32;
dl->die = cl.time+0.05; //+ 0.1;
dl->decay = 1;
dl->channelfade[0] = 2;
dl->channelfade[1] = 2;
dl->channelfade[2] = 2;
if (silenced)
volume = 0.2;
else
volume = 1;
switch (weapon)
{
case Q2MZ_BLASTER:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_BLUEHYPERBLASTER:
dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_HYPERBLASTER:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_MACHINEGUN:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
break;
case Q2MZ_SHOTGUN:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case Q2MZ_SSHOTGUN:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_CHAINGUN1:
dl->radius = 200 + (rand()&31);
dl->color[0] = 1;dl->color[1] = 0.25;dl->color[2] = 0;
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
break;
case Q2MZ_CHAINGUN2:
dl->radius = 225 + (rand()&31);
dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
dl->die = cl.time + 0.1; // long delay
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.05);
break;
case Q2MZ_CHAINGUN3:
dl->radius = 250 + (rand()&31);
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
dl->die = cl.time + 0.1; // long delay
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0);
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.033);
Q_snprintfz(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.066);
break;
case Q2MZ_RAILGUN:
dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_ROCKET:
dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case Q2MZ_GRENADE:
dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
break;
case Q2MZ_BFG:
dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_LOGIN:
dl->color[0] = 0;dl->color[1] = 1; dl->color[2] = 0;
dl->die = cl.time + 1.0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
// CL_LogoutEffect (pl->current.origin, weapon);
break;
case Q2MZ_LOGOUT:
dl->color[0] = 1;dl->color[1] = 0; dl->color[2] = 0;
dl->die = cl.time + 1.0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
// CL_LogoutEffect (pl->current.origin, weapon);
break;
case Q2MZ_RESPAWN:
dl->color[0] = 1;dl->color[1] = 1; dl->color[2] = 0;
dl->die = cl.time + 1.0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
// CL_LogoutEffect (pl->current.origin, weapon);
break;
// RAFAEL
case Q2MZ_PHALANX:
dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/plasshot.wav"), volume, ATTN_NORM, 0);
break;
// RAFAEL
case Q2MZ_IONRIPPER:
dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0);
break;
// ======================
// PGM
case Q2MZ_ETF_RIFLE:
dl->color[0] = 0.9;dl->color[1] = 0.7;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/nail1.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_SHOTGUN2:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_HEATBEAM:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
dl->die = cl.time + 100;
// Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/bfg__l1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_BLASTER2:
dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
// FIXME - different sound for blaster2 ??
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_TRACKER:
// negative flashes handled the same in gl/soft until CL_AddDLights
dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1;
Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/disint2.wav"), volume, ATTN_NORM, 0);
break;
case Q2MZ_NUKE1:
dl->color[0] = 1;dl->color[1] = 0;dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case Q2MZ_NUKE2:
dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
dl->die = cl.time + 100;
break;
case Q2MZ_NUKE4:
dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
dl->die = cl.time + 100;
break;
case Q2MZ_NUKE8:
dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 1;
dl->die = cl.time + 100;
break;
// PGM
// ======================
}
}
void CLQ2_ParseMuzzleFlash2 (void)
{
int ent;
int flash_number;
ent = (unsigned short)(short)MSG_ReadShort ();
if (ent < 1 || ent >= Q2MAX_EDICTS)
Host_EndGame ("CL_ParseMuzzleFlash2: bad entity");
flash_number = MSG_ReadByte ();
CLQ2_RunMuzzleFlash2(ent, flash_number);
}
void CLQ2_ParseInventory (int seat)
{
unsigned int i;
for (i=0 ; i<Q2MAX_ITEMS ; i++)
cl.inventory[seat][i] = MSG_ReadShort ();
}
/*
=========================================================================
@ -702,7 +934,7 @@ CL_ParseDelta
Can go from either a baseline or a previous packet_entity
==================
*/
void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
static void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
{
// set everything to the state we are delta'ing from
*to = *from;
@ -2323,20 +2555,4 @@ void CLQ2_AddEntities (void)
#endif
}
void CL_GetNumberedEntityInfo (int num, float *org, float *ang)
{
q2centity_t *ent;
if (num < 0 || num >= MAX_Q2EDICTS)
Host_EndGame ("CL_GetNumberedEntityInfo: bad ent");
ent = &cl_entities[num];
if (org)
VectorCopy (ent->current.origin, org);
if (ang)
VectorCopy (ent->current.angles, ang);
// FIXME: bmodel issues...
}
#endif

View File

@ -967,8 +967,6 @@ void Con_CycleConsole(void)
}
}
void Con_Log(char *s);
/*
================
Con_Printf

View File

@ -79,7 +79,7 @@ static qboolean xinput_useaudio;
#ifdef AVAIL_DINPUT
#ifndef _MSC_VER
#ifndef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x0700
#endif
@ -166,6 +166,12 @@ static DWORD joy_flags;
#define MAX_JOYSTICKS 8
static struct wjoy_s {
qboolean isxinput; //xinput device
enum
{
DS_UNKNOWN,
DS_PRESENT,
DS_NOTPRESENT
} devstate;
unsigned int id; //windows id. device id is the index.
unsigned int devid; //quake id (generally player index)
DWORD numbuttons;
@ -1975,91 +1981,111 @@ void INS_Commands (void)
}
void INS_DeviceChanged(void *ctx, void *data, size_t a ,size_t b)
{ //called on WM_DEVICECHANGE
unsigned int idx;
for (idx = 0; idx < joy_count; idx++)
{
wjoy[idx].devstate = DS_UNKNOWN;
}
}
/*
===============
INS_ReadJoystick
===============
*/
qboolean INS_ReadJoystick (struct wjoy_s *joy)
static qboolean INS_ReadJoystick (struct wjoy_s *joy)
{
if (joy->devstate != DS_NOTPRESENT)
{ //xinput samples all basically say to poll, but that gives really shit performance.
//instead we wait until our window thread gets a WM_DEVICECHANGE before we restart polling an inactive device.
//this can safe us a couple ms each frame.
#ifdef AVAIL_XINPUT
if (joy->isxinput)
{
XINPUT_STATE xistate;
XINPUT_VIBRATION vibrator;
HRESULT hr;
memset(&xistate, 0, sizeof(xistate));
hr = pXInputGetState(joy->id, &xistate);
if (in_xinput.ival == 2)
if (joy->isxinput)
{
Con_Printf("xi%i %s, b:%#x r:%u,%u l:%u,%u t:%u,%u\n", joy->id, (hr==ERROR_SUCCESS)?"success":va("%lx", hr), xistate.Gamepad.wButtons,
xistate.Gamepad.sThumbRX, xistate.Gamepad.sThumbRY,
xistate.Gamepad.sThumbLX,xistate.Gamepad.sThumbLY,
xistate.Gamepad.bLeftTrigger,xistate.Gamepad.bRightTrigger);
}
else if (in_xinput.ival == 3 && joy->id == 0)
{
//I don't have a controller to test this with, so we fake stuff.
POINT p;
GetCursorPos(&p);
hr = ERROR_SUCCESS;
xistate.Gamepad.wButtons = rand() & 0xfff0;
xistate.Gamepad.sThumbRX = 0;//(p.x/1920.0)*0xffff - 0x8000;
xistate.Gamepad.sThumbRY = 0;//(p.y/1080.0)*0xffff - 0x8000;
xistate.Gamepad.sThumbLX = (p.x/1920.0)*0xffff - 0x8000;
xistate.Gamepad.sThumbLY = (p.y/1080.0)*0xffff - 0x8000;
xistate.Gamepad.bLeftTrigger = 0;
xistate.Gamepad.bRightTrigger = 0;
}
XINPUT_STATE xistate;
XINPUT_VIBRATION vibrator;
HRESULT hr;
memset(&xistate, 0, sizeof(xistate));
hr = pXInputGetState(joy->id, &xistate);
if (hr == ERROR_SUCCESS)
{ //ERROR_SUCCESS
//do we care about the dwPacketNumber?
joy->buttonstate = xistate.Gamepad.wButtons & 0xffff;
if (xistate.Gamepad.bLeftTrigger >= 128)
joy->buttonstate |= 0x10000;
if (xistate.Gamepad.bRightTrigger >= 128)
joy->buttonstate |= 0x20000;
if (joy->devid != DEVID_UNSET)
if (in_xinput.ival == 2)
{
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_RIGHT, xistate.Gamepad.sThumbLX / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_DOWN, xistate.Gamepad.sThumbLY / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_TRIGGER, xistate.Gamepad.bLeftTrigger/255.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_RIGHT, xistate.Gamepad.sThumbRX / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_DOWN, xistate.Gamepad.sThumbRY / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_TRIGGER, xistate.Gamepad.bRightTrigger/255.0);
vibrator.wLeftMotorSpeed = xinput_leftvibrator.value * 0xffff;
vibrator.wRightMotorSpeed = xinput_rightvibrator.value * 0xffff;
pXInputSetState(joy->id, &vibrator);
Con_Printf("xi%i %s, b:%#x r:%u,%u l:%u,%u t:%u,%u\n", joy->id, (hr==ERROR_SUCCESS)?"success":va("%lx", hr), xistate.Gamepad.wButtons,
xistate.Gamepad.sThumbRX, xistate.Gamepad.sThumbRY,
xistate.Gamepad.sThumbLX,xistate.Gamepad.sThumbLY,
xistate.Gamepad.bLeftTrigger,xistate.Gamepad.bRightTrigger);
}
return true;
else if (in_xinput.ival == 3 && joy->id == 0)
{
//I don't have a controller to test this with, so we fake stuff.
POINT p;
GetCursorPos(&p);
hr = ERROR_SUCCESS;
xistate.Gamepad.wButtons = rand() & 0xfff0;
xistate.Gamepad.sThumbRX = 0;//(p.x/1920.0)*0xffff - 0x8000;
xistate.Gamepad.sThumbRY = 0;//(p.y/1080.0)*0xffff - 0x8000;
xistate.Gamepad.sThumbLX = (p.x/1920.0)*0xffff - 0x8000;
xistate.Gamepad.sThumbLY = (p.y/1080.0)*0xffff - 0x8000;
xistate.Gamepad.bLeftTrigger = 0;
xistate.Gamepad.bRightTrigger = 0;
}
if (hr == ERROR_SUCCESS)
{ //ERROR_SUCCESS
//do we care about the dwPacketNumber?
joy->devstate = DS_PRESENT;
joy->buttonstate = xistate.Gamepad.wButtons & 0xffff;
if (xistate.Gamepad.bLeftTrigger >= 128)
joy->buttonstate |= 0x10000;
if (xistate.Gamepad.bRightTrigger >= 128)
joy->buttonstate |= 0x20000;
if (joy->devid != DEVID_UNSET)
{
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_RIGHT, xistate.Gamepad.sThumbLX / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_DOWN, xistate.Gamepad.sThumbLY / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_TRIGGER, xistate.Gamepad.bLeftTrigger/255.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_RIGHT, xistate.Gamepad.sThumbRX / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_DOWN, xistate.Gamepad.sThumbRY / 32768.0);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_TRIGGER, xistate.Gamepad.bRightTrigger/255.0);
vibrator.wLeftMotorSpeed = xinput_leftvibrator.value * 0xffff;
vibrator.wRightMotorSpeed = xinput_rightvibrator.value * 0xffff;
pXInputSetState(joy->id, &vibrator);
}
return true;
}
else if (hr == ERROR_DEVICE_NOT_CONNECTED)
joy->devstate = DS_NOTPRESENT;
}
}
else
else
#endif
{
memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji);
ji.dwFlags = joy_flags;
if (joyGetPosEx (joy->id, &ji) == JOYERR_NOERROR)
{
joy->povstate = ji.dwPOV;
joy->buttonstate = ji.dwButtons;
if (joy->devid != DEVID_UNSET)
memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji);
ji.dwFlags = joy_flags;
if (joyGetPosEx (joy->id, &ji) == JOYERR_NOERROR)
{
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_RIGHT, (ji.dwXpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_DOWN, (ji.dwYpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_AUX, (ji.dwZpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_RIGHT, (ji.dwRpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_DOWN, (ji.dwUpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_AUX, (ji.dwVpos - 32768.0) / 32768);
joy->devstate = DS_PRESENT;
joy->povstate = ji.dwPOV;
joy->buttonstate = ji.dwButtons;
if (joy->devid != DEVID_UNSET)
{
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_RIGHT, (ji.dwXpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_DOWN, (ji.dwYpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_LT_AUX, (ji.dwZpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_RIGHT, (ji.dwRpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_DOWN, (ji.dwUpos - 32768.0) / 32768);
IN_JoystickAxisEvent(joy->devid, GPAXIS_RT_AUX, (ji.dwVpos - 32768.0) / 32768);
}
return true;
}
return true;
else
joy->devstate = DS_NOTPRESENT;
}
}

View File

@ -306,10 +306,10 @@ void Key_PrintQCDefines(vfsfile_t *f)
==============================================================================
*/
qboolean Cmd_IsCommand (char *line)
qboolean Cmd_IsCommand (const char *line)
{
char command[128];
char *cmd, *s;
const char *cmd, *s;
int i;
s = line;
@ -1987,20 +1987,7 @@ void Key_Unbindall_f (void)
Key_SetBinding (i, ~0, NULL, Cmd_ExecLevel);
}
void Key_AliasEdit_f (void)
{
char *alias = Cmd_AliasExist(Cmd_Argv(1), RESTRICT_LOCAL);
char quotedalias[2048];
if (alias)
{
COM_QuotedString(alias, quotedalias, sizeof(quotedalias), false);
Key_ConsoleReplace(va("alias %s %s", Cmd_Argv(1), quotedalias));
}
else
Con_Printf("Not an alias\n");
}
void Key_Bind_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx)
void Key_Bind_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
keyname_t *kn;
size_t len = strlen(partial);
@ -2312,7 +2299,6 @@ void Key_Init (void)
Cmd_AddCommand ("bindlevel",Key_BindLevel_f);
Cmd_AddCommandAD ("unbind",Key_Unbind_f, Key_Bind_c, NULL);
Cmd_AddCommand ("unbindall",Key_Unbindall_f);
Cmd_AddCommand ("aliasedit",Key_AliasEdit_f);
Cvar_Register (&con_selectioncolour, "Console variables");
Cvar_Register (&con_echochat, "Console variables");

View File

@ -480,8 +480,8 @@ void MP_Keyup(int key, int unicode, unsigned int devid);
qboolean MP_MouseMove(float x, float y, unsigned int devid);
qboolean MP_MousePosition(float x, float y, unsigned int devid);
qboolean MP_JoystickAxis(int axis, float value, unsigned int devid);
int MP_BuiltinValid(char *name, int num);
qboolean MP_ConsoleCommand(char *cmdtext);
int MP_BuiltinValid(const char *name, int num);
qboolean MP_ConsoleCommand(const char *cmdtext);
#endif
#define MGT_BAD ~0

View File

@ -1,17 +1,17 @@
#ifdef VKQUAKE
#if defined(__LP64__) || defined(_WIN64)
#define VulkanWasDesignedByARetard void*
#define VulkanAPIRandomness void*
#elif defined(_MSC_VER) && _MSC_VER < 1300
#define VulkanWasDesignedByARetard __int64
#define VulkanAPIRandomness __int64
#else
#define VulkanWasDesignedByARetard long long
#define VulkanAPIRandomness long long
#endif
#define VkRetardedDescriptorSet VulkanWasDesignedByARetard
#define VkRetardedShaderModule VulkanWasDesignedByARetard
#define VkRetardedPipelineLayout VulkanWasDesignedByARetard
#define VkRetardedDescriptorSetLayout VulkanWasDesignedByARetard
#define VkRetardedBuffer VulkanWasDesignedByARetard
#define VkRetardedDeviceMemory VulkanWasDesignedByARetard
#define VkRetardedDescriptorSet VulkanAPIRandomness
#define VkRetardedShaderModule VulkanAPIRandomness
#define VkRetardedPipelineLayout VulkanAPIRandomness
#define VkRetardedDescriptorSetLayout VulkanAPIRandomness
#define VkRetardedBuffer VulkanAPIRandomness
#define VkRetardedDeviceMemory VulkanAPIRandomness
#endif
//These are defined later in the source tree. This file should probably be moved to a later spot.
@ -129,7 +129,7 @@ extern void SCR_BeginLoadingPlaque (void);
extern void SCR_EndLoadingPlaque (void);
extern void SCR_DrawConsole (qboolean noback);
extern void SCR_SetUpToDrawConsole (void);
extern void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode);
extern void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode);
void R_DrawTextField(int x, int y, int w, int h, const char *text, unsigned int defaultmask, unsigned int fieldflags, struct font_s *font, vec2_t fontscale);
#define CPRINT_LALIGN (1<<0) //L
@ -418,7 +418,7 @@ typedef struct rendererinfo_s {
void (*Draw_Shutdown) (void);
void (*IMG_UpdateFiltering) (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean (*IMG_LoadTextureMips) (texid_t tex, struct pendingtextureinfo *mips);
qboolean (*IMG_LoadTextureMips) (texid_t tex, const struct pendingtextureinfo *mips);
void (*IMG_DestroyTexture) (texid_t tex);
void (*R_Init) (void); //FIXME - merge implementations

View File

@ -899,7 +899,7 @@ void QCBUILTIN PF_cl_sprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
//this is a bit pointless for menus as it doesn't know player names or anything.
#ifndef CLIENTONLY
int clientnum = G_FLOAT(OFS_PARM0);
char *str = PF_VarString(prinst, 1, pr_globals);
const char *str = PF_VarString(prinst, 1, pr_globals);
if (sv.active && clientnum < sv.allocated_client_slots && svs.clients[clientnum].state >= cs_connected)
SV_PrintToClient(&svs.clients[clientnum], PRINT_HIGH, str);
#endif
@ -907,7 +907,7 @@ void QCBUILTIN PF_cl_sprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
void QCBUILTIN PF_cl_bprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
#ifndef CLIENTONLY
char *str = PF_VarString(prinst, 0, pr_globals);
const char *str = PF_VarString(prinst, 0, pr_globals);
if (sv.active)
SV_BroadcastPrintf(PRINT_HIGH, "%s", str);
#endif
@ -931,4 +931,14 @@ void QCBUILTIN PF_cl_localsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_
S_LocalSound2(s, chan, vol);
}
void QCBUILTIN PF_cl_getgamedirinfo(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //IMPLEMENTME
// int diridx = G_FLOAT(OFS_PARM0);
// int propidx = G_FLOAT(OFS_PARM1);
//propidx 0 == name
//propidx 1 == description (contents of modinfo.txt)
G_INT(OFS_RETURN) = 0;
}
#endif

View File

@ -111,6 +111,7 @@ extern sfx_t *cl_sfx_r_exp3;
globalfunction(parse_print, "CSQC_Parse_Print"); \
globalfunction(parse_event, "CSQC_Parse_Event"); \
globalfunction(parse_damage, "CSQC_Parse_Damage"); \
globalfunction(parse_setangles, "CSQC_Parse_SetAngles"); \
globalfunction(input_event, "CSQC_InputEvent"); \
globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \
globalfunction(rendererrestarted, "CSQC_RendererRestarted"); \
@ -509,6 +510,8 @@ csqcextfields
#undef fieldentity
#undef fieldstring
#undef fieldfunction
PR_RegisterFieldVar(csqcprogs, ev_void, NULL, pr_fixbrokenqccarrays.ival, -1);
}
static csqcedict_t **csqcent;
@ -731,7 +734,7 @@ static void QCBUILTIN PF_checkbuiltin (pubprogfuncs_t *prinst, struct globalvars
static void QCBUILTIN PF_cl_cprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 0, pr_globals);
const char *str = PF_VarString(prinst, 0, pr_globals);
if (csqc_playerseat >= 0)
SCR_CenterPrint(csqc_playerseat, str, true);
}
@ -767,6 +770,8 @@ static float CSQC_PitchScaleForModelIndex(int index)
return 1;
}
wedict_t *skel_gettaginfo_args (pubprogfuncs_t *prinst, vec3_t axis[3], vec3_t origin, int tagent, int tagnum);
static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
{
int ival;
@ -846,6 +851,13 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
out->scale = in->xv->scale;
}
if (csqc_isdarkplaces && in->xv->tag_entity)
{
csqcedict_t *p = (csqcedict_t*)skel_gettaginfo_args(csqcprogs, out->axis, out->origin, in->xv->tag_entity, in->xv->tag_index);
if (p && (int)p->xv->renderflags & CSQCRF_VIEWMODEL)
out->flags |= RF_DEPTHHACK|RF_WEAPONMODEL;
}
ival = in->v->colormap;
out->playerindex = -1;
if (ival > 0 && ival <= MAX_CLIENTS)
@ -2230,7 +2242,7 @@ static void QCBUILTIN PF_cs_getstati(pubprogfuncs_t *prinst, struct globalvars_s
G_FLOAT(OFS_RETURN) = 0;
PR_RunWarning(prinst, "invalid stat index");
}
else if (stnum >= 128 && csqc_isdarkplaces)
else if (stnum >= 128 && csqc_isdarkplaces && cls.protocol != CP_NETQUAKE && !CPNQ_IS_DP)
{ //dpp7 stats are fucked.
G_FLOAT(OFS_RETURN) = csqc_playerview->statsf[stnum];
csqc_deprecated("hacked stat type");
@ -2259,7 +2271,7 @@ static void QCBUILTIN PF_cs_getstatbits(pubprogfuncs_t *prinst, struct globalvar
count = 1;
G_FLOAT(OFS_RETURN) = (((unsigned int)val)&(((1<<count)-1)<<first))>>first;
}
else if (csqc_isdarkplaces)
else if (csqc_isdarkplaces && cls.protocol != CP_NETQUAKE && !CPNQ_IS_DP)
{
G_FLOAT(OFS_RETURN) = (int)csqc_playerview->statsf[stnum]; //stupid. mods like xonotic end up with an ugly hud if they're actually given any precision
if (G_FLOAT(OFS_RETURN) != csqc_playerview->statsf[stnum])
@ -2657,6 +2669,8 @@ static void QCBUILTIN PF_cs_precachefile(pubprogfuncs_t *prinst, struct globalva
static void QCBUILTIN PF_cs_PrecacheSound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *soundname = PR_GetStringOfs(prinst, OFS_PARM0);
if (!*soundname) //invalid
return;
Sound_CheckDownload(soundname);
S_PrecacheSound(soundname);
}
@ -2829,7 +2843,7 @@ static void QCBUILTIN PF_ReadPicture(pubprogfuncs_t *prinst, struct globalvars_s
static void QCBUILTIN PF_objerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
struct edict_s *ed;
s = PF_VarString(prinst, 0, pr_globals);
@ -3524,6 +3538,13 @@ static const char *PF_cs_getplayerkey_internal (unsigned int pnum, const char *k
else
sprintf(ret, "'%g %g %g'", ((col&0xff0000)>>16)/255.0, ((col&0x00ff00)>>8)/255.0, ((col&0x0000ff)>>0)/255.0);
}
#ifndef NOLEGACY
else if (csqc_isdarkplaces && !strcmp(keyname, "colors")) //checks to see if a player has locally been set to ignored (for text chat)
{
ret = buffer;
sprintf(ret, "%i", cl.players[pnum].ttopcolor + cl.players[pnum].tbottomcolor*16);
}
#endif
else if (!strcmp(keyname, "ignored")) //checks to see if a player has locally been set to ignored (for text chat)
{
ret = buffer;
@ -3559,7 +3580,7 @@ static const char *PF_cs_getplayerkey_internal (unsigned int pnum, const char *k
//string(string keyname)
static void QCBUILTIN PF_cs_serverkey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *keyname = PF_VarString(prinst, 0, pr_globals);
const char *keyname = PF_VarString(prinst, 0, pr_globals);
const char *ret = PF_cs_serverkey_internal(keyname);
if (*ret)
RETURN_TSTRING(ret);
@ -3904,94 +3925,6 @@ static void QCBUILTIN PF_getlightstylergb (pubprogfuncs_t *prinst, struct global
VectorScale(cl_lightstyle[stnum].colours, value*(1.0/256), G_VECTOR(OFS_RETURN));
}
//entity(string field, float match) findchainflags = #450
//chained search for float, int, and entity reference fields
static void QCBUILTIN PF_cs_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
int s;
csqcedict_t *ent, *chain;
chain = (csqcedict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = G_FLOAT(OFS_PARM1);
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = (csqcedict_t*)EDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
if (!((int)((float *)ent->v)[f] & s))
continue;
ent->v->chain = EDICT_TO_PROG(prinst, (edict_t*)chain);
chain = ent;
}
RETURN_EDICT(prinst, (edict_t*)chain);
}
//entity(string field, float match) findchainfloat = #403
static void QCBUILTIN PF_cs_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
float s;
csqcedict_t *ent, *chain;
chain = (csqcedict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = G_FLOAT(OFS_PARM1);
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = (csqcedict_t*)EDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
if (((float *)ent->v)[f] != s)
continue;
ent->v->chain = EDICT_TO_PROG(prinst, (edict_t*)chain);
chain = ent;
}
RETURN_EDICT(prinst, (edict_t*)chain);
}
//entity(string field, string match) findchain = #402
//chained search for strings in entity fields
static void QCBUILTIN PF_cs_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
const char *s;
string_t t;
csqcedict_t *ent, *chain;
chain = (csqcedict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = PR_GetStringOfs(prinst, OFS_PARM1);
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = (csqcedict_t*)EDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
t = *(string_t *)&((float*)ent->v)[f];
if (!t)
continue;
if (strcmp(PR_GetString(prinst, t), s))
continue;
ent->v->chain = EDICT_TO_PROG(prinst, (edict_t*)chain);
chain = ent;
}
RETURN_EDICT(prinst, (edict_t*)chain);
}
static void QCBUILTIN PF_cl_te_gunshot (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *pos = G_VECTOR(OFS_PARM0);
@ -4598,7 +4531,7 @@ static void CS_ConsoleCommand_f(void)
}
static void QCBUILTIN PF_cs_registercommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 0, pr_globals);
const char *str = PF_VarString(prinst, 0, pr_globals);
if (!Cmd_Exists(str))
Cmd_AddCommand(str, CS_ConsoleCommand_f);
}
@ -5386,9 +5319,16 @@ static void QCBUILTIN PF_cs_getplayerstat(pubprogfuncs_t *prinst, struct globalv
static void QCBUILTIN PF_V_CalcRefdef(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
{ //this function is essentially an overcomplicated way to shirk from defining your own view bobbing.
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
Con_DPrintf("Warning: V_CalcRefdef (builtin 640) not implemented.\n");
enum
{
TELEPORTED,
JUMPING,
DEAD,
INTERMISSION
} flags = G_FLOAT(OFS_PARM1);
csqc_deprecated("V_CalcRefdef is so lame. man up and define your own behaviour.\n");
// if (ent->xv->entnum >= 1 && ent->xv->entnum <= MAX_CLIENTS)
// CSQC_ChangeLocalPlayer(ent->xv->entnum-1);
@ -6122,8 +6062,8 @@ static struct {
//400
{"copyentity", PF_copyentity, 400}, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
{"setcolors", PF_NoCSQC, 401}, // #401 void(entity cl, float colours) setcolors (DP_SV_SETCOLOR) (don't implement)
{"findchain", PF_cs_findchain, 402}, // #402 entity(string field, string match) findchain (DP_QC_FINDCHAIN)
{"findchainfloat", PF_cs_findchainfloat, 403}, // #403 entity(float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
{"findchain", PF_findchain, 402}, // #402 entity(string field, string match) findchain (DP_QC_FINDCHAIN)
{"findchainfloat", PF_findchainfloat, 403}, // #403 entity(float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
{"effect", PF_cl_effect, 404}, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
{"te_blood", PF_cl_te_blooddp, 405}, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
@ -6182,7 +6122,7 @@ static struct {
{"cvar_string", PF_cvar_string, 448}, // #448 string(float n) cvar_string (DP_QC_CVAR_STRING)
{"findflags", PF_FindFlags, 449}, // #449 entity(entity start, .entity fld, float match) findflags (DP_QC_FINDFLAGS)
{"findchainflags", PF_cs_findchainflags, 450}, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
{"findchainflags", PF_findchainflags, 450}, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
{"gettagindex", PF_gettagindex, 451}, // #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO)
{"gettaginfo", PF_gettaginfo, 452}, // #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO)
{"dropclient", PF_NoCSQC, 453}, // #453 void(entity player) dropclient (DP_SV_BOTCLIENT) (don't implement)
@ -6366,7 +6306,7 @@ static struct {
{"getextresponse", PF_cl_getextresponse, 624},
#endif
{"netaddress_resolve", PF_netaddress_resolve, 625},
{"getgamedirinfo", PF_cl_getgamedirinfo, 626},
{"sprintf", PF_sprintf, 627},
{"getsurfacenumtriangles", PF_getsurfacenumtriangles,628},
{"getsurfacetriangle", PF_getsurfacetriangle, 629},
@ -7130,6 +7070,15 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
G_FLOAT(OFS_PARM2) = version_number();
PR_ExecuteProgram(csqcprogs, csqcg.init_function);
}
/*
{
char *watchname = "something";
void *dbg = PR_FindGlobal(csqcprogs, watchname, 0, NULL);
if (!csqcprogs->SetWatchPoint(csqcprogs, watchname))
Con_Printf("Unable to watch %s\n", watchname);
}
*/
// csqcprogs->ToggleBreak(csqcprogs, "something", 0, 2);
Con_DPrintf("Loaded csqc\n");
csqcmapentitydataloaded = false;
@ -7782,7 +7731,7 @@ qboolean CSQC_ConsoleLink(char *text, char *info)
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_ConsoleCommand(char *cmd)
qboolean CSQC_ConsoleCommand(const char *cmd)
{
void *pr_globals;
if (!csqcprogs || !csqcg.console_command)
@ -7898,11 +7847,13 @@ qboolean CSQC_LoadResource(char *resname, char *restype)
return !!G_FLOAT(OFS_RETURN);
}
qboolean CSQC_Parse_Damage(float save, float take, vec3_t source)
qboolean CSQC_Parse_Damage(int seat, float save, float take, vec3_t source)
{
void *pr_globals;
if (!csqcprogs || !csqcg.parse_damage)
return false;
CSQC_ChangeLocalPlayer(seat);
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
((float *)pr_globals)[OFS_PARM0] = save;
@ -7994,13 +7945,13 @@ qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend)
PR_ExecuteProgram (csqcprogs, csqcg.parse_stuffcmd);
return true;
}
qboolean CSQC_CenterPrint(int lplayernum, char *cmd)
qboolean CSQC_CenterPrint(int seat, const char *cmd)
{
void *pr_globals;
if (!csqcprogs || !csqcg.parse_centerprint)
return false;
CSQC_ChangeLocalPlayer(lplayernum);
CSQC_ChangeLocalPlayer(seat);
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd));
@ -8009,12 +7960,30 @@ qboolean CSQC_CenterPrint(int lplayernum, char *cmd)
return G_FLOAT(OFS_RETURN) || csqc_isdarkplaces;
}
void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd)
qboolean CSQC_Parse_SetAngles(int seat, vec3_t newangles, qboolean wasdelta)
{
void *pr_globals;
if (!csqcprogs || !csqcg.parse_setangles)
return false;
CSQC_ChangeLocalPlayer(seat);
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
((float *)pr_globals)[OFS_PARM0+0] = newangles[0];
((float *)pr_globals)[OFS_PARM0+1] = newangles[1];
((float *)pr_globals)[OFS_PARM0+2] = newangles[2];
((float *)pr_globals)[OFS_PARM1] = wasdelta;
PR_ExecuteProgram (csqcprogs, csqcg.parse_setangles);
return G_FLOAT(OFS_RETURN);
}
void CSQC_Input_Frame(int seat, usercmd_t *cmd)
{
if (!csqcprogs || !csqcg.input_frame)
return;
CSQC_ChangeLocalPlayer(lplayernum);
CSQC_ChangeLocalPlayer(seat);
if (csqcg.simtime)
*csqcg.simtime = cl.servertime;

View File

@ -320,6 +320,7 @@ void CL_LoadFont_f(void)
char *slotname = Cmd_Argv(1);
char *facename = Cmd_Argv(2);
int sizenum = 3;
extern cvar_t dpcompat_console, gl_font;
//loadfont slot face size1 size2...
@ -386,6 +387,9 @@ void CL_LoadFont_f(void)
fontslot[slotnum].sizes++;
}
}
if (dpcompat_console.ival)
Cvar_Set(&gl_font, facename);
}
}
@ -480,6 +484,12 @@ void QCBUILTIN PF_CL_stringwidth(pubprogfuncs_t *prinst, struct globalvars_s *pr
int usecolours = G_FLOAT(OFS_PARM1);
float *size = (prinst->callargc > 2)?G_VECTOR(OFS_PARM2):NULL;
if (!qrenderer)
{
G_FLOAT(OFS_RETURN) = 0;
return;
}
end = COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), !usecolours);
PR_CL_BeginString(prinst, 0, 0, size?size[0]:8, size?size[1]:8, &px, &py);
@ -1260,7 +1270,7 @@ static void QCBUILTIN PF_menu_cvar_string (pubprogfuncs_t *prinst, struct global
void QCBUILTIN PF_nonfatalobjerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
struct edict_s *ed;
eval_t *selfp;
@ -1921,7 +1931,7 @@ void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
static void QCBUILTIN PF_menu_cprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 0, pr_globals);
const char *str = PF_VarString(prinst, 0, pr_globals);
SCR_CenterPrint(0, str, true);
}
static void QCBUILTIN PF_cl_changelevel (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -1963,7 +1973,7 @@ static void MP_ConsoleCommand_f(void)
}
static void QCBUILTIN PF_menu_registercommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 0, pr_globals);
const char *str = PF_VarString(prinst, 0, pr_globals);
if (!Cmd_Exists(str))
Cmd_AddCommand(str, MP_ConsoleCommand_f);
}
@ -2279,7 +2289,7 @@ static struct {
{"getextresponse", PF_cl_getextresponse, 624},
#endif
{"netaddress_resolve", PF_netaddress_resolve, 625},
//gap
{"getgamedirinfo", PF_cl_getgamedirinfo, 626},
{"sprintf", PF_sprintf, 627},
//gap
{"setkeybind", PF_Fixme, 630},
@ -2297,7 +2307,7 @@ static struct {
static builtin_t menu_builtins[1024];
int MP_BuiltinValid(char *name, int num)
int MP_BuiltinValid(const char *name, int num)
{
int i;
for (i = 0; BuiltinList[i].name; i++)
@ -2620,7 +2630,7 @@ static void MP_GameCommand_f(void)
inmenuprogs--;
}
qboolean MP_ConsoleCommand(char *cmdtext)
qboolean MP_ConsoleCommand(const char *cmdtext)
{
void *pr_globals;
if (!menu_world.progs)
@ -2739,6 +2749,7 @@ void MP_Draw(void)
((float *)pr_globals)[OFS_PARM0+0] = vid.width;
((float *)pr_globals)[OFS_PARM0+1] = vid.height;
((float *)pr_globals)[OFS_PARM0+2] = 0;
((float *)pr_globals)[OFS_PARM1+0] = vid.height; //dp compat, ish
if (mp_drawloading_function && (scr_drawloading||scr_disabled_for_loading))
{
((float *)pr_globals)[OFS_PARM1] = scr_disabled_for_loading;

View File

@ -198,7 +198,6 @@ static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[
out[10] = vz[2];
out[11] = t[2];
}
#if !defined(SERVERONLY) && defined(RAGDOLL)
static void bonemat_fromaxisorg(float *out, vec3_t axis[3], const float t[3])
{
out[0] = axis[0][0];
@ -214,7 +213,6 @@ static void bonemat_fromaxisorg(float *out, vec3_t axis[3], const float t[3])
out[10]= axis[2][2];
out[11]= t[2];
}
#endif
static void bonemat_fromentity(world_t *w, wedict_t *ed, float *trans)
{
vec3_t d[3], a;
@ -243,6 +241,21 @@ static void bonemat_toqcvectors(const float *in, float vx[3], float vy[3], float
t [1] = in[7];
t [2] = in[11];
}
static void bonemat_toaxisorg(const float *src, vec3_t axis[3], float t[3])
{
axis[0][0] = src[0];
axis[0][1] = src[4];
axis[0][2] = src[8];
axis[1][0] = src[1];
axis[1][1] = src[5];
axis[1][2] = src[9];
axis[2][0] = src[2];
axis[2][1] = src[6];
axis[2][2] = src[10];
t[0] = src[3];
t[1] = src[7];
t[2] = src[11];
}
static void bonematident_toqcvectors(float vx[3], float vy[3], float vz[3], float t[3])
{
@ -2269,12 +2282,9 @@ void QCBUILTIN PF_gettaginfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
world_t *w = prinst->parms->user;
wedict_t *ent = G_WEDICT(prinst, OFS_PARM0);
int tagnum = G_FLOAT(OFS_PARM1);
int tagent = ent->xv->tag_entity;
int chain = 10;
int modelindex = ent->v->modelindex;
model_t *mod = w->Get_CModel(w, modelindex);
float transent[12];
float transforms[12];
float result[12];
@ -2283,31 +2293,64 @@ void QCBUILTIN PF_gettaginfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
framestate_t fstate;
w->Get_FrameState(w, ent, &fstate);
if (!Mod_GetTag(mod, tagnum, &fstate, transforms))
{
if (!Mod_GetTag(w->Get_CModel(w, ent->v->modelindex), tagnum, &fstate, transforms))
bonemat_fromidentity(transforms);
}
bonemat_fromentity(w, ent, transent);
R_ConcatTransforms((void*)transent, (void*)transforms, (void*)result);
while (ent->xv->tag_entity && chain --> 0)
while (tagent && chain --> 0)
{
ent = PROG_TO_WEDICT(prinst, tagent);
w->Get_FrameState(w, ent, &fstate);
if (!Mod_GetTag(mod, tagnum, &fstate, transforms))
if (!Mod_GetTag(w->Get_CModel(w, ent->v->modelindex), tagnum, &fstate, transforms))
bonemat_fromidentity(transforms);
bonemat_fromentity(w, ent, transent);
R_ConcatTransforms((void*)transforms, (void*)result, (void*)result2);
R_ConcatTransforms((void*)transent, (void*)result2, (void*)result);
ent = PROG_TO_WEDICT(prinst, ent->xv->tag_entity);
tagent = ent->xv->tag_entity;
tagnum = ent->xv->tag_index;
}
bonemat_toqcvectors(result, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
}
//writes to axis+origin. returns root entity.
wedict_t *skel_gettaginfo_args (pubprogfuncs_t *prinst, vec3_t axis[3], vec3_t origin, int tagent, int tagnum)
{
world_t *w = prinst->parms->user;
wedict_t *ent = NULL;
int chain = 10;
float transent[12];
float transforms[12];
float result[12];
float result2[12];
framestate_t fstate;
bonemat_fromaxisorg(result, axis, origin);
while (tagent && chain --> 0)
{
ent = PROG_TO_WEDICT(prinst, tagent);
w->Get_FrameState(w, ent, &fstate);
if (!Mod_GetTag(w->Get_CModel(w, ent->v->modelindex), tagnum, &fstate, transforms))
bonemat_fromidentity(transforms);
bonemat_fromentity(w, ent, transent);
R_ConcatTransforms((void*)transforms, (void*)result, (void*)result2);
R_ConcatTransforms((void*)transent, (void*)result2, (void*)result);
tagent = ent->xv->tag_entity;
tagnum = ent->xv->tag_index;
}
bonemat_toaxisorg(result, axis, origin);
return ent;
}
//vector(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO)
void QCBUILTIN PF_gettagindex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2342,7 +2385,7 @@ void QCBUILTIN PF_frameforname (pubprogfuncs_t *prinst, struct globalvars_s *pr_
world_t *w = prinst->parms->user;
unsigned int modelindex = G_FLOAT(OFS_PARM0);
int surfaceidx = 0;
char *str = PF_VarString(prinst, 1, pr_globals);
const char *str = PF_VarString(prinst, 1, pr_globals);
model_t *mod = w->Get_CModel(w, modelindex);
if (mod)
@ -2627,7 +2670,7 @@ void QCBUILTIN PF_skinforname (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
#ifndef SERVERONLY
world_t *w = prinst->parms->user;
unsigned int modelindex = G_FLOAT(OFS_PARM0);
char *str = PF_VarString(prinst, 1, pr_globals);
const char *str = PF_VarString(prinst, 1, pr_globals);
int surfaceidx = 0;
model_t *mod = w->Get_CModel(w, modelindex);

View File

@ -3442,6 +3442,22 @@ char *particle_set_q2part =
"scalefactor 0.8\n"
"}\n"
"r_part placeholder\n"
"{ //FIXME: fix the things that assoc this!\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 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0 255 //something that makes it obviously a placeholder.\n"
"}\n"
"r_part te_splashsparks\n"
"{\n"
"texture \"classicparticle\"\n"
@ -3674,9 +3690,9 @@ char *particle_set_q2part =
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0 7\n"
/*smoke puff models*/
"/*smoke puff models*/\n"
"assoc q2_smokeandflash\n"
/*low chance of various sounds*/
"/*low chance of various sounds*/\n"
"sound world/ric1.wav 1 1 0 0 1\n"
"sound world/ric2.wav 1 1 0 0 1\n"
"sound world/ric3.wav 1 1 0 0 1\n"
@ -3697,7 +3713,7 @@ char *particle_set_q2part =
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0 7\n"
/*smoke puff models*/
"/*smoke puff models*/\n"
"assoc q2_smokeandflash\n"
"}\n"
@ -3845,6 +3861,22 @@ char *particle_set_q2part =
"lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part teq2_bluehyperblaster\n"
"{ //misnamed - just the regular orangey particles without sound/puff\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 60\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 40\n"
"orgadd 0 15\n"
"veladd 30\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0xe0 7\n"
"}\n"
"r_part TR_BLASTERTRAIL\n"
"{\n"
"texture \"classicparticle\"\n"
@ -3895,9 +3927,25 @@ char *particle_set_q2part =
"spawnvel 5\n"
"die 1 1.2\n"
"colorindex 4 7\n"
"velbias 0 0 6\n"
"}\n"
"r_part teq2_bubbletrail2\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"scale 0.5\n"
"alpha 1\n"
"scalefactor 0.8\n"
"step 8\n"
"spawnorg 2\n"
"spawnvel 10\n"
"die 1 1.1\n"
"colorindex 4 7\n"
"velbias 0 0 20\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part TEQ2_RAILTRAIL\n"
"r_part teq2_railtrail\n"
"{\n"
//blue spiral
"texture \"classicparticle\"\n"
@ -3914,7 +3962,7 @@ char *particle_set_q2part =
"sound \"weapons/railgf1a.wav\" 1 1 0 0\n"
"}\n"
"r_part +TEQ2_RAILTRAIL\n"
"r_part +teq2_railtrail\n"
"{\n"
//grey filler
"texture \"classicparticle\"\n"
@ -3929,6 +3977,25 @@ char *particle_set_q2part =
"colorindex 0 15\n"
"}\n"
"r_part teq2_railtrail2\n"
"{ //This is not implemented in vanilla, so we've no idea what it should really look like.\n"
//we just use the blue spiral with no core.
//blue spiral
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"scale 0.5\n"
"alpha 1\n"
"scalefactor 0.8\n"
"step 1\n"
"spawnmode spiral 64\n"
"spawnorg 3\n"
"spawnvel 6\n"
"die 1 1.2\n"
"colorindex 116 7\n"
"sound \"weapons/railgf1a.wav\" 1 1 0 0\n"
"}\n"
//regular explosion particles
"r_part std_explosion_particles\n"
"{\n"
@ -4024,6 +4091,81 @@ char *particle_set_q2part =
"model \"models/objects/r_explode/tris.md2\" framestart=30 frames=19 skin=-1 fullbright noshadow\n"
"}\n"
"r_part teq2_plain_explosion\n"
"{ //basically like regular explosions, but with no particle effect.\n"
"lighttime 0.5\n"
"lightradius 350\n"
"lightradiusfade 300\n"
"lightrgb 1.0 0.5 0.4\n"
"lightrgbfade 0.36 0.19 0.19\n"
"sound \"weapons/rocklx1a.wav\" 1 1 0 0\n"
"model \"models/objects/r_explode/tris.md2\" framestart=0 frames=15 skin=-1 fullbright noshadow\n"
"model \"models/objects/r_explode/tris.md2\" framestart=15 frames=15 skin=-1 fullbright noshadow\n"
"}\n"
"r_part teq2_plasma_explosion\n"
"{ //not actually any different\n"
"assoc teq2_explosion1\n"
"}\n"
"r_part teq2_tracker_explosion\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 128\n"
"scale 1\n"
"alpha 1\n"
"die 1.5 2\n"
"randomvel 128\n"
"orgadd 0 31\n"
"spawnorg 16\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0 1\n"
"lighttime 0.1 //this is kinda too short.\n"
"lightradius 150\n"
"lightradiusfade 300\n"
"lightrgb -1.0 -1.0 -1.0\n"
"sound \"weapons/disrupthit.wav\" 1 1 0 0\n"
"}\n"
"r_part teq2_teleport_effect\n"
"{ //FIXME\n"
"assoc placeholder\n"
"}\n"
"r_part teq2_dball_goal\n"
"{ //FIXME\n"
"assoc placeholder\n"
"}\n"
"r_part teq2_widowsplash\n"
"{ //FIXME\n"
"assoc placeholder\n"
"}\n"
"r_part teq2_debugtrail\n"
"{ //FIXME\n"
"assoc placeholder\n"
"}\n"
"r_part teq2_chainfist_smoke\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 20\n"
"scale 1\n"
"alpha 1\n"
"die 0.5 0.8\n"
"spawnorg 2\n"
"randomvel 6.66 20\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0 7\n"
"}\n"
"r_part teq2_flashlight\n"
"{ //JUST a light.\n"
"lightradius 400\n"
"lighttime 0.15\n"
"lightrgb 1.0 1.0 1.0\n"
"lightshadows 1\n"
"}\n"
"r_part trq2_rocket\n"
"{\n"
"texture \"particles/quake\"\n"
@ -4075,36 +4217,66 @@ char *particle_set_q2part =
"assoc TR_BLASTERTRAIL\n"
"}\n"
//FIXME: add particles
"r_part tr_ionripper\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"step 3\n"
"scale 1\n"
"alpha 0.5\n"
"die 0.15 0.25\n"
"colorindex 0xe4 3\n"
"spawnmode tracer\n"
"spawnorg 0\n"
"spawnvel 10\n"
"lighttime 0\n"
"lightradius 100\n"
"lightrgb 1.0 0.5 0.5\n"
"}\n"
//FIXME: add particles
"r_part tr_tracker\n"
"{\n"
"{ //FIXME: doesn't match vanilla. works well enough though I guess.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"step 3\n"
"scale 1\n"
"alpha 1\n"
"die 0.5\n"
"spawnmode spiral 8.34\n"
"spawnorg 1\n"
"spawnvel 32\n"
"veladd 32\n"
"scalefactor 0\n"
"colorindex 0\n"
"lighttime 0\n"
"lightradius 200\n"
"lightrgb -1.0 -1.0 -1.0\n"
"}\n"
//FIXME: add particles
"r_part tr_tagtrail\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"step 5\n"
"scale 1\n"
"alpha 1\n"
"die 1.0 0.8\n"
"spawnorg 16\n"
"spawnvel 5\n"
"scalefactor 0\n"
"colorindex 220\n"
"lighttime 0\n"
"lightradius 225\n"
"lightrgb 1.0 1.0 0.0\n"
"}\n"
//FIXME: add particles
"r_part tr_trap\n"
"{\n"
"{ //FIXME: add particles\n"
"lighttime 0\n"
"lightradius 100 200\n"
"lightrgb 1.0 0.8 0.25\n"
"assoc placeholder\n"
"}\n"
//flags do NOT use coronas, because it obscures the holding player's skin colour
@ -4265,6 +4437,48 @@ char *particle_set_q2part =
"scalefactor 0.8\n"
"sound \"misc/bigtele.wav\" 1 0 0 0 1\n"
"}\n"
"r_part teq2_heatbeam_sparks\n"
"{ //FIXME\n"
"assoc placeholder\n"
"}\n"
"r_part teq2_heatbeam_steam\n"
"{ //FIXME\n"
"assoc placeholder\n"
"}\n"
"/*\n"
"r_part teq2_heatbeam_steam\n"
"{\n"
"count 20\n"
"colorindex 0xe0 7\n"
// magnitude 60
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20 magnitude/3\n"
"veladd magnitude\n"
"orgadd magnitude/10\n"
"spawnorg 4\n"
"gravity -400\n"
"scalefactor 0.8\n"
"}\n"
"*/\n"
//this is apparently just a trail effect (palette index specified by netcode)
"r_part teq2_forcewall\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"scale 0.5\n"
"alpha 1\n"
"scalefactor 0.8\n"
"step 5\n"
"spawnorg 3\n"
"randomvel 5\n"
"die 3 3.5\n"
"}\n"
;
#endif

View File

@ -449,18 +449,18 @@ image_t *Image_LoadTexture (const char *identifier, int width, int height, uploa
#ifdef D3D8QUAKE
void D3D8_Set2D (void);
void D3D8_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean D3D8_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean D3D8_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips);
void D3D8_DestroyTexture (texid_t tex);
#endif
#ifdef D3D9QUAKE
void D3D9_Set2D (void);
void D3D9_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean D3D9_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean D3D9_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips);
void D3D9_DestroyTexture (texid_t tex);
#endif
#ifdef D3D11QUAKE
void D3D11_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean D3D11_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean D3D11_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips);
void D3D11_DestroyTexture (texid_t tex);
#endif

View File

@ -409,6 +409,7 @@ cvar_t r_noaliasshadows = CVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE);
cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting.");
cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground.");
cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc.");
cvar_t r_showshaders = CVARD("r_showshaders", "0", "Debugging. Shows the name of the (worldmodel) shader being pointed to.");
cvar_t r_lightprepass_cvar = CVARFD("r_lightprepass", "0", CVAR_SHADERSYSTEM, "Experimental. Attempt to use a different lighting mechanism.");
int r_lightprepass;
@ -953,6 +954,7 @@ void Renderer_Init(void)
Cvar_Register (&r_showbboxes, GLRENDEREROPTIONS);
Cvar_Register (&r_showfields, GLRENDEREROPTIONS);
Cvar_Register (&r_showshaders, GLRENDEREROPTIONS);
#ifndef NOLEGACY
Cvar_Register (&r_polygonoffset_submodel_factor, GLRENDEREROPTIONS);
Cvar_Register (&r_polygonoffset_submodel_offset, GLRENDEREROPTIONS);

View File

@ -783,6 +783,10 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
}
switch(codec)
{
case VOIP_RAW16:
case VOIP_PCMA:
case VOIP_PCMU:
break;
case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:

View File

@ -247,7 +247,7 @@ static sfxcache_t *QDECL OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf
if (bytesread != 0) //0==eof
{
dec->failed = true;
Con_Printf("ogg decoding failed\n");
Con_Printf("ogg decoding failed %i\n", bytesread);
break;
}
if (start >= dec->decodedbytestart+dec->decodedbytecount)
@ -274,7 +274,7 @@ static sfxcache_t *QDECL OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf
if (bytesread != 0) //0==eof
{
dec->failed = true;
Con_Printf("ogg decoding failed\n");
Con_Printf("ogg decoding failed %i\n", bytesread);
return NULL;
}
if (start >= dec->decodedbytestart+dec->decodedbytecount)

View File

@ -93,29 +93,43 @@ typedef struct
} dma_t;
//client and server
//CF_RELIABLE 1
#define CF_FORCELOOP 2 // forces looping. set on static sounds.
#define CF_NOSPACIALISE 4 // these sounds are played at a fixed volume in both speakers, but still gets quieter with distance.
//#define CF_PAUSED 8 // rate = 0. or something.
//CF_ABSVOLUME
#define CF_NOREVERB 32 // disables reverb on this channel, if possible.
#define CF_FOLLOW 64 // follows the owning entity (stops moving if we lose track)
//#define CF_RESERVEDN 128 // reserved for things that should be networked.
//#define CF_RELIABLE 1
#define CF_FORCELOOP 2 // forces looping. set on static sounds.
#define CF_NOSPACIALISE 4 // these sounds are played at a fixed volume in both speakers, but still gets quieter with distance.
//#define CF_PAUSED 8 // rate = 0. or something.
//#define CF_ABSVOLUME 16
#define CF_NOREVERB 32 // disables reverb on this channel, if possible.
#define CF_FOLLOW 64 // follows the owning entity (stops moving if we lose track)
//#define CF_RESERVEDN 128 // reserved for things that should be networked.
//client only
#define CF_ABSVOLUME 16 // ignores volume cvar.
///CF_RELIABLE 1
//#define CF_FORCELOOP 2
//#define CF_NOSPACIALISE 4
///#define CF_PAUSED 8
#define CF_ABSVOLUME 16 // ignores volume cvar.
//#define CF_NOREVERB 32
//#define CF_FOLLOW 64
///#define CF_RESERVEDN 128
//client-internal
#define CF_AUTOSOUND 1024 // generated from q2 entities, which avoids breaking regular sounds, using it outside the sound system will probably break things.
#define CF_AUTOSOUND 1024 // generated from q2 entities, which avoids breaking regular sounds, using it outside the sound system will probably break things.
//server only
#define CF_RELIABLE 1 // serverside only. yeah, evil. screw you.
#define CF_UNICAST 256 // serverside only. the sound is sent to msg_entity only.
#define CF_SENDVELOCITY 512 // serverside hint that velocity is important
//#define CF_UNUSED 2048
//#define CF_UNUSED 4096
//#define CF_UNUSED 8192
//#define CF_UNUSED 16384
//#define CF_UNUSED 32768
#define CF_RELIABLE 1 // serverside only. yeah, evil. screw you.
//#define CF_FORCELOOP 2
//#define CF_NOSPACIALISE 4
///#define CF_PAUSED 8
//#define CF_NOREVERB 32
//#define CF_FOLLOW 64
///#define CF_RESERVEDN 128
#define CF_UNICAST 256 // serverside only. the sound is sent to msg_entity only.
#define CF_SENDVELOCITY 512 // serverside hint that velocity is important
///#define CF_UNUSED 2048
///#define CF_UNUSED 4096
///#define CF_UNUSED 8192
///#define CF_UNUSED 16384
///#define CF_UNUSED 32768
#define CF_NETWORKED (CF_NOSPACIALISE|CF_NOREVERB|CF_FORCELOOP|CF_FOLLOW/*|CF_RESERVEDN*/)

View File

@ -365,6 +365,15 @@ qboolean Sys_RandomBytes(qbyte *string, int len)
CryptReleaseContext(prov, 0);
return true;
}
#ifndef CALG_SHA_512
#define ALG_SID_SHA_256 12
#define ALG_SID_SHA_384 13
#define ALG_SID_SHA_512 14
#define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
#define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
#define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
#endif
//returns 0 on failure, otherwise returns the actual digest size and the digest (overallocate if lazy)
size_t HashCalculate(const char *hashtype, const void *data, size_t data_size, void *digest_out, size_t digest_size)
{
@ -378,12 +387,18 @@ size_t HashCalculate(const char *hashtype, const void *data, size_t data_size, v
alg = CALG_MD5;
else if (!Q_strcasecmp(hashtype, "SHA1"))
alg = CALG_SHA1;
#ifdef CALG_SHA_256
else if (!Q_strcasecmp(hashtype, "SHA256"))
alg = CALG_SHA_256; //only on xp sp3+
#endif
#ifdef CALG_SHA_384
else if (!Q_strcasecmp(hashtype, "SHA384"))
alg = CALG_SHA_384; //only on xp sp3+
#endif
#ifdef CALG_SHA_512
else if (!Q_strcasecmp(hashtype, "SHA512"))
alg = CALG_SHA_512; //only on xp sp3+
#endif
else
return 0;

View File

@ -22,7 +22,7 @@ static void Headless_Draw_Shutdown(void)
static void Headless_IMG_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis)
{
}
static qboolean Headless_IMG_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
static qboolean Headless_IMG_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
{
return true;
}

View File

@ -443,7 +443,7 @@ void V_ParseDamage (playerview_t *pv)
#endif
#ifdef CSQC_DAT
if (CSQC_Parse_Damage(armor, blood, from))
if (CSQC_Parse_Damage(pv-cl.playerview, armor, blood, from))
return;
#endif
@ -1854,6 +1854,8 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam)
}
#include "pr_common.h"
msurface_t *Mod_GetSurfaceNearPoint(model_t *model, vec3_t point);
char *Shader_GetShaderBody(shader_t *s, char *fname, size_t fnamesize);
extern vec3_t nametagorg[MAX_CLIENTS];
extern qboolean nametagseen[MAX_CLIENTS];
void R_DrawNameTags(void)
@ -1864,7 +1866,7 @@ void R_DrawNameTags(void)
char *ourteam;
int ourcolour;
extern cvar_t r_showfields, r_projection;
extern cvar_t r_showshaders, r_showfields, r_projection;
if (r_projection.ival) //we don't actually know how to transform the points unless the projection is coded in advance. and it isn't.
return;
@ -1982,6 +1984,34 @@ void R_DrawNameTags(void)
}
}
if (r_showshaders.ival && cl.worldmodel && cl.worldmodel->loadstate == MLS_LOADED)
{
trace_t trace;
char *str;
vec3_t targ;
vec2_t scale = {12,12};
msurface_t *surf;
VectorMA(r_refdef.vieworg, 8192, vpn, targ);
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace);
surf = Mod_GetSurfaceNearPoint(cl.worldmodel, trace.endpos);
if (surf)
{
shader_t *shader = surf->texinfo->texture->shader;
char *body = shader?Shader_GetShaderBody(shader, NULL, 0):NULL;
if (body)
{
str = va("%s\n{%s\n", surf->texinfo->texture->name, body);
Z_Free(body);
}
else
str = va("hit '%s'", surf->texinfo->texture->name);
}
else
str = "hit nothing";
R_DrawTextField(r_refdef.vrect.x + r_refdef.vrect.width/4, r_refdef.vrect.y, r_refdef.vrect.width/2, r_refdef.vrect.height, str, CON_WHITEMASK, CPRINT_LALIGN, font_default, scale);
}
if (((!r_refdef.playerview->spectator && !cls.demoplayback) || !scr_autoid.ival) && (!cl.teamplay || !scr_autoid_team.ival))
return;
if (cls.state != ca_active || !cl.validsequence || cl.intermissionmode != IM_NONE)

View File

@ -136,6 +136,7 @@ void INS_UpdateClipCursor (void);
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify);
void INS_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int pnum, qboolean genkeystate);
int INS_AppCommand(LPARAM lParam);
void INS_DeviceChanged(void *ctx, void *data, size_t a ,size_t b);
void S_BlockSound (void);
void S_UnblockSound (void);

View File

@ -593,6 +593,21 @@ typedef struct
#define Q3CONTENTS_TRIGGER 0x40000000
#define Q3CONTENTS_NODROP FTECONTENTS_SKY //0x80000000
//qc compat only. not used internally.
#define DPCONTENTS_SOLID 1 // hit a bmodel, not a bounding box
#define DPCONTENTS_WATER 2
#define DPCONTENTS_SLIME 4
#define DPCONTENTS_LAVA 8
#define DPCONTENTS_SKY 16
#define DPCONTENTS_BODY 32 // hit a bounding box, not a bmodel
#define DPCONTENTS_CORPSE 64 // hit a SOLID_CORPSE entity
#define DPCONTENTS_NODROP 128 // an area where backpacks should not spawn
#define DPCONTENTS_PLAYERCLIP 256 // blocks player movement
#define DPCONTENTS_MONSTERCLIP 512 // blocks monster movement
#define DPCONTENTS_DONOTENTER 1024 // AI hint brush
#define DPCONTENTS_BOTCLIP 2048 // AI hint brush
#define DPCONTENTS_OPAQUE 4096 // only fully opaque brushes get this (may be useful for line of sight checks)
//Texinfo flags - warning: these mix with q3 surface flags
#define TI_LIGHT 0x1 // value will hold the light strength

View File

@ -26,6 +26,7 @@ cvar_t ruleset_allow_in = CVAR("ruleset_allow_in", "1");
cvar_t rcon_level = CVAR("rcon_level", "20");
cvar_t cmd_maxbuffersize = CVAR("cmd_maxbuffersize", "65536");
cvar_t dpcompat_set = CVAR("dpcompat_set", "0");
cvar_t dpcompat_console = CVARD("dpcompat_console", "0", "Enables hacks to emulate DP's console.");
int Cmd_ExecLevel;
qboolean cmd_didwait;
qboolean cmd_blockwait;
@ -37,11 +38,11 @@ void Cmd_ForwardToServer (void);
typedef struct cmdalias_s
{
struct cmdalias_s *next;
char name[MAX_ALIAS_NAME];
char *value;
qbyte execlevel;
qbyte restriction;
int flags;
char name[1];
} cmdalias_t;
#define ALIAS_FROMSERVER 1
@ -733,7 +734,7 @@ static int QDECL CompleteExecList (const char *name, qofs_t flags, time_t mtime,
ctx->cb(name, ctx);
return true;
}
void Cmd_Exec_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx)
void Cmd_Exec_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
if (argn == 1)
{
@ -767,7 +768,19 @@ void Cmd_Echo_f (void)
Con_Printf ("\n");
}
void Cmd_ShowAlias_f (void)
static void Key_Alias_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
cmdalias_t *a;
size_t len = strlen(partial);
if (argn != 1)
return;
for (a = cmd_alias ; a ; a=a->next)
{
if (!Q_strncasecmp(partial,a->name, len))
ctx->cb(a->name, ctx);
}
}
static void Cmd_ShowAlias_f (void)
{
cmdalias_t *a;
char *s;
@ -880,9 +893,9 @@ void Cmd_Alias_f (void)
}
s = Cmd_Argv(1);
if (strlen(s) >= MAX_ALIAS_NAME || !strcmp(s, "say")) //reject aliasing the say command. We use it as an easy way to warn that our player is cheating.
if (!strcmp(s, "say")) //reject aliasing the say command. We use it as an easy way to warn that our player is cheating.
{
Con_TPrintf ("Alias name is too long\n");
Con_TPrintf ("Refusing to create an alias with the name '%s'\n", s);
return;
}
@ -941,16 +954,25 @@ void Cmd_Alias_f (void)
if (!a)
{
a = (cmdalias_t*)Z_Malloc (sizeof(cmdalias_t));
a->next = cmd_alias;
cmd_alias = a;
cmdalias_t **link;
a = (cmdalias_t*)Z_Malloc (sizeof(cmdalias_t) + strlen(s));
strcpy (a->name, s);
for (link = &cmd_alias; ; link = &(*link)->next)
{
if (!*link || strcmp((*link)->name, s) >= 0)
{
a->next = *link;
*link = a;
break;
}
}
}
if (Cmd_FromGamecode())
a->flags |= ALIAS_FROMSERVER;
else
a->flags &= ~ALIAS_FROMSERVER;
strcpy (a->name, s);
multiline = false;
if (Cmd_Argc() == 2) //check the next statement for being '{'
{
@ -986,7 +1008,7 @@ void Cmd_Alias_f (void)
strcat (cmd, " ");
}
if (!*cmd) //someone wants to wipe it. let them
if (!*cmd && !dpcompat_console.ival) //someone wants to wipe it. let them
{
if (a == cmd_alias)
{
@ -1021,6 +1043,21 @@ void Cmd_Alias_f (void)
}
}
#ifndef SERVERONLY
static void Cmd_AliasEdit_f (void)
{
char *alias = Cmd_AliasExist(Cmd_Argv(1), RESTRICT_LOCAL);
char quotedalias[2048];
if (alias)
{
COM_QuotedString(alias, quotedalias, sizeof(quotedalias), false);
Key_ConsoleReplace(va("alias %s %s", Cmd_Argv(1), quotedalias));
}
else
Con_Printf("Not an alias\n");
}
#endif
void Cmd_DeleteAlias(char *name)
{
cmdalias_t *a, *b;
@ -1210,8 +1247,8 @@ void Cvar_PurgeDefaults_f(void);
typedef struct cmd_function_s
{
struct cmd_function_s *next;
char *name;
char *description;
const char *name;
const char *description;
xcommand_t function;
xcommandargcompletion_t argcompletion;
@ -1320,34 +1357,95 @@ void Cmd_ShiftArgs (int ammount, qboolean expandstring)
}
}
char *Cmd_ExpandCvar(char *cvarname, int maxaccesslevel, int *newaccesslevel, int *len)
const char *Cmd_ExpandCvar(char *cvarterm, int maxaccesslevel, int *newaccesslevel, int *len)
{
char *ret = NULL, *end, *namestart;
char *fixup = NULL, fixval=0;
const char *ret = NULL;
char *fixup = NULL, fixval=0, *t;
cvar_t *var;
static char temp[12];
static char quoted[256];
unsigned int result;
int termlen, pl;
namestart = cvarname;
if (*cvarname == '{')
{
fixup = &cvarname[strlen(cvarname)-1];
int quotetype = 0;
const char *cvarname;
cvarname = cvarterm;
if (*cvarterm == '{')
{ //set foo ba"r; ${foo q} -> ba\"r
//set foo bar; ${foo asis} -> ba"r
//${bar q} -> <EMPTY>
//${bar ?} -> ""
//${bar !} -> <ERROR>
fixup = &cvarterm[strlen(cvarterm)-1];
if (*fixup != '}')
return NULL;
cvarterm++;
fixval = *fixup;
*fixup = 0;
cvarname++;
termlen = fixup - cvarname;
if (fixval)
termlen++;
if (fixup-cvarterm > 2 && !strncmp(fixup-2, " ?", 2))
{ //force expansion, even if not defined.
pl = 2;
quotetype = 2;
}
else if (fixup-cvarterm > 2 && !strncmp(fixup-2, " !", 2))
{ //abort is not defined
pl = 2;
quotetype = 3;
}
else if (fixup-cvarterm > 2 && !strncmp(fixup-2, " q", 2))
{ //escaping it if not empty, otherwise empty.
pl = 2;
quotetype = 1;
}
else if (fixup-cvarterm > 2 && !strncmp(fixup-5, " asis", 5))
{ //no escaping...
pl = 5;
quotetype = 0;
}
else
{
pl = 0;
quotetype = 1; //default to escaping.
}
if (pl)
{
*fixup = fixval;
fixup -= pl;
fixval = *fixup;
*fixup = 0;
}
if (*cvarterm == '$')
cvarname = Cmd_ExpandCvar(cvarterm+1, maxaccesslevel, newaccesslevel, &pl);
else
cvarname = cvarterm;
}
else
{
fixup = &cvarname[strlen(cvarname)];
fixup = &cvarterm[strlen(cvarterm)];
fixval = *fixup;
termlen = fixup - cvarname;
if (fixval)
termlen++;
}
result = strtoul(cvarname, &end, 10);
if (fixval && *end == 0) //only expand $0 if its actually ${0} - this avoids conflicting with the $0 macro
{ //purely numerical
ret = Cmd_Argv(result);
result = strtoul(cvarname, &t, 10);
if ((dpcompat_console.ival||fixval) && (*t == 0 || (*t == '-' && t[1] == 0))) //only expand $0 if its actually ${0} - this avoids conflicting with the $0 macro
{
if (*t == '-') //pure number with a trailing minus means
{ //args starting after that.
ret = Cmd_Args();
while (ret && result-- > 1)
ret = COM_StringParse(ret, com_token, sizeof(com_token), false, false);
while(ret && (*ret == ' ' || *ret == '\t'))
ret++;
}
else //purely numerical
ret = Cmd_Argv(result);
}
else if (!strcmp(cvarname, "*") || !stricmp(cvarname, "cmd_args"))
{
@ -1357,7 +1455,7 @@ char *Cmd_ExpandCvar(char *cvarname, int maxaccesslevel, int *newaccesslevel, in
{
ret = Cmd_Argv(atoi(cvarname+8));
}
else if (!stricmp(cvarname, "cmd_argc"))
else if (!strcmp(cvarname, "#") || !stricmp(cvarname, "cmd_argc"))
{
Q_snprintfz(temp, sizeof(temp), "%u", Cmd_Argc());
ret = temp;
@ -1373,12 +1471,25 @@ char *Cmd_ExpandCvar(char *cvarname, int maxaccesslevel, int *newaccesslevel, in
}
}
*fixup = fixval;
if (ret)
if (quotetype == 3)
{
*len = fixup - namestart;
if (fixval)
(*len)++;
if (ret)
quotetype = 1;
else
return NULL;
}
else if (quotetype == 2)
{
quotetype = 1;
if (!ret)
ret = "";
}
if (ret)
*len = termlen;
if (quotetype)
ret = COM_QuotedString(ret?ret:"", quoted, sizeof(quoted), true);
return ret;
}
@ -1391,14 +1502,14 @@ If not SERVERONLY, also expands $macro expressions
Note: dest must point to a 1024 byte buffer
================
*/
char *Cmd_ExpandString (char *data, char *dest, int destlen, int *accesslevel, qboolean expandcvars, qboolean expandmacros)
char *Cmd_ExpandString (const char *data, char *dest, int destlen, int *accesslevel, qboolean expandcvars, qboolean expandmacros)
{
unsigned int c;
char buf[255];
int i, len;
int quotes = 0;
char *str;
char *bestvar;
const char *str;
const char *bestvar;
int name_length, var_length;
qboolean striptrailing;
int maxaccesslevel = *accesslevel;
@ -1410,7 +1521,7 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int *accesslevel, q
if (c == '"')
quotes++;
if (c == '$' && !(quotes&1))
if (c == '$' && (!(quotes&1) || dpcompat_console.ival))
{
data++;
@ -1422,10 +1533,19 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int *accesslevel, q
buf[1] = 0;
bestvar = NULL;
var_length = 0;
while ((c = *data) > 32)
while((c = *data))
{
if (c == '$')
if (c < ' ')
break;
if (c == ' ' && buf[0] != '{')
break;
if (c == '$' && i == 0)
{
data++;
name_length = 0;
str = "$";
break;
}
data++;
buf[i++] = c;
buf[i] = 0;
@ -1683,7 +1803,7 @@ Cmd_AddCommand
============
*/
qboolean Cmd_AddCommandAD (char *cmd_name, xcommand_t function, xcommandargcompletion_t argcompletion, char *desc)
qboolean Cmd_AddCommandAD (const char *cmd_name, xcommand_t function, xcommandargcompletion_t argcompletion, const char *desc)
{
cmd_function_t *cmd;
@ -1712,9 +1832,9 @@ qboolean Cmd_AddCommandAD (char *cmd_name, xcommand_t function, xcommandargcompl
cmd = (cmd_function_t*)Z_Malloc (sizeof(cmd_function_t)+strlen(cmd_name)+1);
cmd->name = (char*)(cmd+1);
strcpy((char*)(cmd+1), cmd_name);
cmd->argcompletion = argcompletion;
cmd->description = desc;
strcpy(cmd->name, cmd_name);
cmd->function = function;
cmd->next = cmd_functions;
cmd->restriction = 0;
@ -1723,16 +1843,16 @@ qboolean Cmd_AddCommandAD (char *cmd_name, xcommand_t function, xcommandargcompl
return true;
}
qboolean Cmd_AddCommandD (char *cmd_name, xcommand_t function, char *desc)
qboolean Cmd_AddCommandD (const char *cmd_name, xcommand_t function, const char *desc)
{
return Cmd_AddCommandAD(cmd_name, function, NULL, desc);
}
qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function)
qboolean Cmd_AddCommand (const char *cmd_name, xcommand_t function)
{
return Cmd_AddCommandAD(cmd_name, function, NULL, NULL);
}
void Cmd_RemoveCommand (char *cmd_name)
void Cmd_RemoveCommand (const char *cmd_name)
{
cmd_function_t *cmd, **back;
@ -1893,7 +2013,7 @@ void Cmd_EnumerateLevel(int level, char *buf, size_t bufsize)
}
}
int Cmd_Level(char *name)
int Cmd_Level(const char *name)
{
cmdalias_t *a;
cmd_function_t *cmds;
@ -1937,7 +2057,7 @@ qboolean Cmd_Exists (const char *cmd_name)
Cmd_Exists
============
*/
char *Cmd_Describe (char *cmd_name)
const char *Cmd_Describe (const char *cmd_name)
{
cmd_function_t *cmd;
@ -1996,7 +2116,7 @@ struct cmdargcompletionctx_s
{
struct xcommandargcompletioncb_s cb;
cmd_function_t *cmd;
char *prefix;
const char *prefix;
size_t prefixlen;
match_t *match;
const char *desc;
@ -2045,7 +2165,7 @@ void Cmd_CompleteCheckArg(const char *value, void *vctx) //compare cumulative st
match->desc = desc;
}
}
char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens, int matchnum, const char **descptr)
char *Cmd_CompleteCommand (const char *partial, qboolean fullonly, qboolean caseinsens, int matchnum, const char **descptr)
{
extern cvar_group_t *cvar_groups;
cmd_function_t *cmd;
@ -2056,7 +2176,7 @@ char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens
cvar_group_t *grp;
cvar_t *cvar;
char *sp;
const char *sp;
for (sp = partial; *sp; sp++)
{
@ -2332,7 +2452,7 @@ A complete command line has been parsed, so try to execute it
FIXME: lookupnoadd the token to speed search?
============
*/
void Cmd_ExecuteString (char *text, int level)
void Cmd_ExecuteString (const char *text, int level)
{
//WARNING: PF_checkcommand should match the order.
cmd_function_t *cmd;
@ -2340,7 +2460,12 @@ void Cmd_ExecuteString (char *text, int level)
char dest[8192];
text = Cmd_ExpandString(text, dest, sizeof(dest), &level, !Cmd_IsInsecure()?true:false, true);
while (*text == ' ' || *text == '\n')
text++;
if (dpcompat_console.ival && !strncmp(text, "alias", 5) && (text[5] == ' ' || text[5] == '\t'))
; //certain commands don't get pre-expanded in dp. evil hack. quote them to pre-expand anyway. double evil.
else
text = Cmd_ExpandString(text, dest, sizeof(dest), &level, !Cmd_IsInsecure()?true:false, true);
Cmd_TokenizeString (text, level == RESTRICT_LOCAL?true:false, false);
// execute the command line
@ -2431,15 +2556,37 @@ void Cmd_ExecuteString (char *text, int level)
// if the alias value is a command or cvar and
// the alias is called with parameters, add them
if (Cmd_Argc() > 1 && (!strncmp(a->value, "cmd ", 4) || (!strchr(a->value, ' ') && !strchr(a->value, '\t') &&
(Cvar_FindVar(a->value) || (Cmd_Exists(a->value) && a->value[0] != '+' && a->value[0] != '-'))))
)
//unless we're mimicing dp, or the alias has explicit expansions (or macros) in which case it can do its own damn args
if (dpcompat_console.ival)
{
Cbuf_InsertText (Cmd_Args(), execlevel, false);
Cbuf_InsertText (" ", execlevel, false);
char *ignoringquoteswasstupid;
Cmd_ExpandString(a->value, dest, sizeof(dest), &execlevel, !Cmd_IsInsecure()?true:false, true);
for (ignoringquoteswasstupid = dest; *ignoringquoteswasstupid; )
{ //double up dollars, to prevent expansion when its actually execed.
if (*ignoringquoteswasstupid == '$')
{
memmove(ignoringquoteswasstupid+1, ignoringquoteswasstupid, strlen(ignoringquoteswasstupid)+1);
ignoringquoteswasstupid++;
}
ignoringquoteswasstupid++;
}
if ((a->restriction?a->restriction:rcon_level.ival) > execlevel)
return;
}
else if (!strchr(a->value, '$'))
{
if (Cmd_Argc() > 1 && (!strncmp(a->value, "cmd ", 4) || (!strchr(a->value, ' ') && !strchr(a->value, '\t') &&
(Cvar_FindVar(a->value) || (Cmd_Exists(a->value) && a->value[0] != '+' && a->value[0] != '-'))))
)
{
Cbuf_InsertText (Cmd_Args(), execlevel, false);
Cbuf_InsertText (" ", execlevel, false);
}
Cmd_ExpandStringArguments (a->value, dest, sizeof(dest));
Cmd_ExpandStringArguments (a->value, dest, sizeof(dest));
}
else
Q_strncpyz(dest, a->value, sizeof(dest));
Cbuf_InsertText (dest, execlevel, false);
#ifndef SERVERONLY
@ -2451,7 +2598,7 @@ void Cmd_ExecuteString (char *text, int level)
}
#endif
Con_DPrintf("Execing alias %s:\n%s\n", a->name, a->value);
Con_DPrintf("Execing alias %s ^3%s:\n^1%s\n^2%s\n", a->name, Cmd_Args(), a->value, dest);
return;
}
}
@ -2570,7 +2717,7 @@ Returns the position (1 to argc-1) in the command's argument list
where the given parameter apears, or 0 if not present
================
*/
int Cmd_CheckParm (char *parm)
int Cmd_CheckParm (const char *parm)
{
int i;
@ -3411,7 +3558,8 @@ void Cmd_set_f(void)
else
var = Cvar_Get(Cmd_Argv(1), text, CVAR_USERCREATED, "User variables");
var->flags |= forceflags;
if (var)
var->flags |= forceflags;
}
If_Token_Clear(mark);
@ -3784,11 +3932,12 @@ void Cmd_Init (void)
#ifndef SERVERONLY
Cmd_AddCommand ("cmd", Cmd_ForwardToServer_f);
Cmd_AddCommand ("condump", Cmd_Condump_f);
Cmd_AddCommandAD ("aliasedit", Cmd_AliasEdit_f, Key_Alias_c, NULL);
#endif
Cmd_AddCommand ("restrict", Cmd_RestrictCommand_f);
Cmd_AddCommand ("aliaslevel", Cmd_AliasLevel_f);
Cmd_AddCommandAD ("aliaslevel", Cmd_AliasLevel_f, Key_Alias_c, NULL);
Cmd_AddCommand ("showalias", Cmd_ShowAlias_f);
Cmd_AddCommandAD ("showalias", Cmd_ShowAlias_f, Key_Alias_c, NULL);
// Cmd_AddCommand ("msg_trigger", Cmd_Msg_Trigger_f);
// Cmd_AddCommand ("filter", Cmd_Msg_Filter_f);
@ -3831,6 +3980,7 @@ void Cmd_Init (void)
Cmd_AddCommandD ("in", Cmd_In_f, "Issues the given command after a time delay. Disabled if ruleset_allow_in is 0.");
Cvar_Register(&dpcompat_set, "Darkplaces compatibility");
Cvar_Register(&dpcompat_console, "Darkplaces compatibility");
Cvar_Register (&cl_warncmd, "Warnings");
Cvar_Register (&cfg_save_all, "client operation options");
Cvar_Register (&cfg_save_auto, "client operation options");

View File

@ -76,9 +76,9 @@ struct xcommandargcompletioncb_s
void(*cb)(const char *arg, struct xcommandargcompletioncb_s *ctx);
//private stuff follows.
};
typedef void (*xcommandargcompletion_t)(int argn, char *partial, struct xcommandargcompletioncb_s *ctx);
typedef void (*xcommandargcompletion_t)(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx);
int Cmd_Level(char *name);
int Cmd_Level(const char *name);
void Cmd_EnumerateLevel(int level, char *buf, size_t bufsize);
void Cmd_Init (void);
@ -86,10 +86,10 @@ void Cmd_Shutdown(void);
void Cmd_StuffCmds (void);
void Cmd_RemoveCommands (xcommand_t function); //unregister all commands that use the same function. for wrappers and stuff.
void Cmd_RemoveCommand (char *cmd_name);
qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function);
qboolean Cmd_AddCommandD (char *cmd_name, xcommand_t function, char *description);
qboolean Cmd_AddCommandAD (char *cmd_name, xcommand_t function, xcommandargcompletion_t argcomplete, char *description);
void Cmd_RemoveCommand (const char *cmd_name);
qboolean Cmd_AddCommand (const char *cmd_name, xcommand_t function);
qboolean Cmd_AddCommandD (const char *cmd_name, xcommand_t function, const char *description);
qboolean Cmd_AddCommandAD (const char *cmd_name, xcommand_t function, xcommandargcompletion_t argcomplete, const char *description);
// called by the init functions of other parts of the program to
// register commands and functions to call for them.
// The cmd_name is referenced later, so it should not be in temp memory
@ -100,10 +100,10 @@ qboolean Cmd_Exists (const char *cmd_name);
char *Cmd_AliasExist(const char *name, int restrictionlevel);
// used by the cvar code to check for cvar / command name overlap
char *Cmd_Describe (char *cmd_name);
const char *Cmd_Describe (const char *cmd_name);
char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens, int matchnum, const char **descptr);
qboolean Cmd_IsCommand (char *line);
char *Cmd_CompleteCommand (const char *partial, qboolean fullonly, qboolean caseinsens, int matchnum, const char **descptr);
qboolean Cmd_IsCommand (const char *line);
// attempts to match a partial command for automatic command line completion
// returns NULL if nothing fits
@ -122,7 +122,7 @@ extern cvar_t cmd_gamecodelevel, cmd_allowaccess;
// functions. Cmd_Argv () will return an empty string, not a NULL
// if arg > argc, so string operations are always safe.
int Cmd_CheckParm (char *parm);
int Cmd_CheckParm (const char *parm);
// Returns the position (1 to argc-1) in the command's argument list
// where the given parameter apears, or 0 if not present
@ -136,7 +136,7 @@ const char *Cmd_TokenizeString (const char *text, qboolean expandmacros, qboolea
// Takes a null terminated string. Does not need to be /n terminated.
// breaks the string up into arg tokens.
void Cmd_ExecuteString (char *text, int restrictionlevel);
void Cmd_ExecuteString (const char *text, int restrictionlevel);
void Cmd_Args_Set(const char *newargs, size_t len);
@ -170,7 +170,7 @@ void Cmd_MessageTrigger (char *message, int type);
void Cmd_ShiftArgs (int ammount, qboolean expandstring);
char *Cmd_ExpandString (char *data, char *dest, int destlen, int *accesslevel, qboolean expandcvars, qboolean expandmacros);
char *Cmd_ExpandString (const char *data, char *dest, int destlen, int *accesslevel, qboolean expandcvars, qboolean expandmacros);
qboolean If_EvaluateBoolean(const char *text, int restriction);
extern cvar_t rcon_level;

View File

@ -998,7 +998,12 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion
unsigned int frame = fs->frame[b];
float time = fs->frametime[b];
if (frame >= inf->numanimations)
continue;//frame = (unsigned)frame%inf->groups;
{
if (inf->numanimations)
frame = 0;
else
continue;//frame = (unsigned)frame%inf->groups;
}
g = &inf->ofsanimations[frame];
if (!g->numposes)
@ -6433,7 +6438,7 @@ qboolean QDECL Mod_LoadDarkPlacesModel(model_t *mod, void *buffer, size_t fsize)
}
vert = (dpmvertex_t*)bonevert;
}
Alias_BuildGPUWeights(mod, root, numtransforms, firsttransform, false);
Alias_BuildGPUWeights(mod, m, numtransforms, firsttransform, false);
Z_Free(firsttransform);
}

View File

@ -3883,6 +3883,7 @@ skipwhite:
//same as COM_Parse, but parses two quotes next to each other as a single quote as part of the string
char *COM_StringParse (const char *data, char *token, unsigned int tokenlen, qboolean expandmacros, qboolean qctokenize)
{
extern cvar_t dpcompat_console;
int c;
int len;
char *s;
@ -3950,40 +3951,62 @@ skipwhite:
if (c == '\"')
{
data++;
while (1)
if (dpcompat_console.ival)
{
if (len >= tokenlen-1)
while (1)
{
token[len] = '\0';
return (char*)data;
}
if (len >= tokenlen-1)
{
token[len] = '\0';
return (char*)data;
}
c = *data++;
if (c=='\"')
{
c = *(data);
if (c!='\"')
c = *data++;
if (c=='\\' && (*data == '\"' || *data == '\\'))
c = *data++; //eat limited escaping inside strings.
else if (c=='\"')
{
token[len] = 0;
return (char*)data;
}
data++;
/* while (c=='\"')
else if (!c)
{
token[len] = c;
len++;
c = *++data;
token[len] = 0;
return (char*)data-1;
}
*/
token[len] = c;
len++;
}
if (!c)
}
else
{
while (1)
{
token[len] = 0;
return (char*)data-1;
if (len >= tokenlen-1)
{
token[len] = '\0';
return (char*)data;
}
c = *data++;
if (c=='\"')
{
c = *(data);
if (c!='\"')
{
token[len] = 0;
return (char*)data;
}
data++;
}
if (!c)
{
token[len] = 0;
return (char*)data-1;
}
token[len] = c;
len++;
}
token[len] = c;
len++;
}
}
@ -4220,8 +4243,9 @@ skipwhite:
const char *COM_QuotedString(const char *string, char *buf, int buflen, qboolean omitquotes)
{
extern cvar_t dpcompat_console;
const char *result = buf;
if (strchr(string, '\r') || strchr(string, '\n') || strchr(string, '\"'))
if (strchr(string, '\r') || strchr(string, '\n') || (!dpcompat_console.ival && strchr(string, '\"')))
{
if (!omitquotes)
{
@ -4285,10 +4309,26 @@ const char *COM_QuotedString(const char *string, char *buf, int buflen, qboolean
}
else
buflen -= 1;
while(*string && buflen >= 1)
if (dpcompat_console.ival)
{
*buf++ = *string++;
buflen--;
while(*string && buflen >= 1)
{
if (*string == '\\' || *string == '\"')
{
*buf++ = '\\';
buflen--;
}
*buf++ = *string++;
buflen--;
}
}
else
{
while(*string && buflen >= 1)
{
*buf++ = *string++;
buflen--;
}
}
if (!omitquotes)
*buf++ = '\"'; //closing quote

View File

@ -754,8 +754,8 @@ typedef enum {
LOG_RCON,
LOG_TYPES
} logtype_t;
void Log_String (logtype_t lognum, char *s);
void Con_Log (char *s);
void Log_String (logtype_t lognum, const char *s);
void Con_Log (const char *s);
void Log_Logfile_f (void);
void Log_Init(void);
void Log_ShutDown(void);

View File

@ -3024,9 +3024,10 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
//nehahra has to be weird with extra cvars, and buggy fullbrights.
#define NEHCFG QCFG "set nospr32 0\nset cutscene 1\nalias startmap_sp \"map nehstart\"\nr_fb_bmodels 0\nr_fb_models 0\n"
/*stuff that makes dp-only mods work a bit better*/
#define DPCOMPAT QCFG "set _cl_playermodel \"\"\n set dpcompat_set 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
#define DPCOMPAT QCFG "gl_specular 1\nset _cl_playermodel \"\"\n set dpcompat_set 1\ndpcompat_console 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
/*nexuiz/xonotic has a few quirks/annoyances...*/
#define NEXCFG DPCOMPAT "cl_loopbackprotocol dpp7\nset sv_listen_dp 1\nset sv_listen_qw 0\nset sv_listen_nq 0\nset sv_listen_q3 0\nset dpcompat_nopreparse 1\nset r_particlesdesc effectinfo\nset sv_bigcoords 1\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\npr_enable_uriget 0\n"
#define NEXCFG DPCOMPAT "cl_nopred 1\ncl_loopbackprotocol dpp7\nset sv_listen_dp 1\nset sv_listen_qw 0\nset sv_listen_nq 0\nset dpcompat_nopreparse 1\nset r_particlesdesc effectinfo\nset sv_bigcoords 1\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\npr_enable_uriget 0\n"
#define XONCFG NEXCFG "set qport $qport_\ncom_parseutf8 1\npr_fixbrokenqccarrays 2\n"
/*some modern non-compat settings*/
#define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n"
/*set some stuff so our regular qw client appears more like hexen2. sv_mintic is required to 'fix' the ravenstaff so that its projectiles don't impact upon each other*/
@ -3095,7 +3096,7 @@ const gamemode_info_t gamemode_info[] = {
{"-nehahra", "nehahra", "FTE-Quake", {"id1/pak0.pak","id1/quake.rc"},NEHCFG, {"id1", "qw", "nehahra", "*fte"}, "Quake: Seal Of Nehahra"},
//various quake-based standalone mods.
{"-nexuiz", "nexuiz", "Nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "*ftedata"}, "Nexuiz"},
{"-xonotic", "xonotic", "Xonotic", {"xonotic.exe"}, NEXCFG, {"data", "*ftedata"}, "Xonotic"},
{"-xonotic", "xonotic", "Xonotic", {"xonotic.exe"}, XONCFG, {"data", "*ftedata"}, "Xonotic"},
// {"-spark", "spark", "Spark", {"base/src/progs.src",
// "base/qwprogs.dat",
// "base/pak0.pak"}, DMFCFG, {"base", }, "Spark"},
@ -4152,6 +4153,38 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
#else
#if defined(__linux__) || defined(__unix__) || defined(__apple__)
#include <sys/stat.h>
static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname)
{
/*
Find where Valve's Steam distribution platform is installed.
Then take a look at that location for the relevent installed app.
*/
FILE *f;
DWORD resultlen;
HKEY key = NULL;
char *ev = getenv("HOME");
if (ev && *ev)
{
Q_snprintfz(basepath, basepathlen, "%s/.steam/steam/SteamApps/common/%s", ev, steamdir);
if ((f = fopen(va("%s/%s", basepath, fname), "rb")))
{
fclose(f);
return true;
}
Q_snprintfz(basepath, basepathlen, "%s/.local/share/Steam/SteamApps/common/%s", ev, steamdir);
if ((f = fopen(va("%s/%s", basepath, fname), "rb")))
{
fclose(f);
return true;
}
/.local/share/Steam
}
return false;
}
#endif
qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen, qboolean allowprompts)
{
@ -4162,6 +4195,9 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
gamename = "quake"; //just a paranoia fallback, shouldn't be needed.
if (!strcmp(gamename, "quake"))
{
if (Sys_SteamHasFile(basepath, basepathlen, "quake", "id1/pak0.pak"))
return true;
if (stat("/usr/share/quake/", &sb) == 0)
{
if (S_ISDIR(sb.st_mode))
@ -4171,6 +4207,17 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
}
}
}
else if (!strcmp(gamename, "quake2"))
{
if (Sys_SteamHasFile(basepath, basepathlen, "quake 2", "baseq2/pak0.pak"))
return true;
}
else if (!strcmp(gamename, "hexen2") || !strcmp(gamename, "h2mp"))
{
if (Sys_SteamHasFile(basepath, basepathlen, "hexen 2", "data/pak0.pak"))
return true;
}
s = va("/usr/share/games/%s/", gamename);
if (stat(s, &sb) == 0)
{

View File

@ -377,6 +377,26 @@ typedef struct cminfo_s
qbyte portalopen[MAX_Q2MAP_AREAPORTALS]; //memset will work if it's a qbyte, really it should be a qboolean
int mapisq3;
#ifdef Q3BSPS
//this is for loading stuff. it used to be globals, but we have threads now. and multiple q3bsps at the same time is a problem.
int numvertexes;
vecV_t *verts; //3points
vec2_t *vertstmexcoords;
vec2_t *vertlstmexcoords[MAXRLIGHTMAPS];
vec4_t *colors4f_array[MAXRLIGHTMAPS];
vec3_t *normals_array;
//vec3_t *map_svector_array;
//vec3_t *map_tvector_array;
index_t *surfindexes;
//int map_numsurfindexes;
q3cface_t *faces;
int numfaces;
#endif
} cminfo_t;
static q2mapsurface_t nullsurface;
@ -399,20 +419,6 @@ qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2
}
#ifdef Q3BSPS
static int numvertexes;
static vecV_t *map_verts; //3points
static vec2_t *map_vertstmexcoords;
static vec2_t *map_vertlstmexcoords[MAXRLIGHTMAPS];
static vec4_t *map_colors4f_array[MAXRLIGHTMAPS];
static vec3_t *map_normals_array;
//static vec3_t *map_svector_array;
//static vec3_t *map_tvector_array;
static index_t *map_surfindexes;
//static int map_numsurfindexes;
static q3cface_t *map_faces;
static int numfaces;
int PlaneTypeForNormal ( vec3_t normal )
{
@ -954,12 +960,12 @@ static qboolean CM_CreatePatchesForLeafs (model_t *loadmodel, cminfo_t *prv)
q2mapsurface_t *surf;
q3cpatch_t *patch;
q3cmesh_t *cmesh;
int *checkout = alloca(sizeof(int)*numfaces);
int *checkout = alloca(sizeof(int)*prv->numfaces);
if (map_noCurves.ival)
return true;
memset (checkout, -1, sizeof(int)*numfaces);
memset (checkout, -1, sizeof(int)*prv->numfaces);
for (i = 0, leaf = loadmodel->leafs; i < loadmodel->numleafs; i++, leaf++)
{
@ -974,12 +980,12 @@ static qboolean CM_CreatePatchesForLeafs (model_t *loadmodel, cminfo_t *prv)
for (j=0 ; j<leaf->nummarksurfaces ; j++)
{
k = leaf->firstmarksurface[j] - loadmodel->surfaces;
if (k >= numfaces)
if (k >= prv->numfaces)
{
Con_Printf (CON_ERROR "CM_CreatePatchesForLeafs: corrupt map\n");
break;
}
face = &map_faces[k];
face = &prv->faces[k];
if (face->numverts <= 0)
continue;
@ -1037,16 +1043,16 @@ static qboolean CM_CreatePatchesForLeafs (model_t *loadmodel, cminfo_t *prv)
cmesh->xyz_array = ZG_Malloc(&loadmodel->memgroup, cmesh->numverts * sizeof(*cmesh->xyz_array) + cmesh->numincidies * sizeof(*cmesh->indicies));
cmesh->indicies = (index_t*)(cmesh->xyz_array + cmesh->numverts);
VectorCopy(map_verts[face->firstvert+0], cmesh->xyz_array[0]);
VectorCopy(prv->verts[face->firstvert+0], cmesh->xyz_array[0]);
VectorCopy(cmesh->xyz_array[0], cmesh->absmaxs);
VectorCopy(cmesh->xyz_array[0], cmesh->absmins);
for (k = 1; k < cmesh->numverts; k++)
{
VectorCopy(map_verts[face->firstvert+k], cmesh->xyz_array[k]);
VectorCopy(prv->verts[face->firstvert+k], cmesh->xyz_array[k]);
AddPointToBounds(cmesh->xyz_array[k], cmesh->absmins, cmesh->absmaxs);
}
for (k = 0; k < cmesh->numincidies; k++)
cmesh->indicies[k] = map_surfindexes[face->soup.firstindex+k];
cmesh->indicies[k] = prv->surfindexes[face->soup.firstindex+k];
}
leaf->contents |= surf->c.value;
leaf->numleafcmeshes++;
@ -1092,7 +1098,7 @@ static qboolean CM_CreatePatchesForLeafs (model_t *loadmodel, cminfo_t *prv)
checkout[k] = prv->numpatches++;
//gcc warns without this cast
CM_CreatePatch (loadmodel, patch, surf, (const vec_t *)(map_verts + face->firstvert), face->patch.cp );
CM_CreatePatch (loadmodel, patch, surf, (const vec_t *)(prv->verts + face->firstvert), face->patch.cp );
}
leaf->contents |= patch->surface->c.value;
leaf->numleafpatches++;
@ -1358,7 +1364,7 @@ static qboolean CModQ2_LoadTexInfo (model_t *mod, qbyte *mod_base, lump_t *l, ch
Q_snprintfz(sname, sizeof(sname), "sky/%s", in->texture);
else
Q_snprintfz(sname, sizeof(sname), "%s", in->texture);
if (out->flags & (TI_WARP|TI_FLOWING))
if (out->flags & (TI_WARP))
Q_strncatz(sname, "#WARP", sizeof(sname));
if (out->flags & TI_FLOWING)
Q_strncatz(sname, "#FLOW", sizeof(sname));
@ -1366,14 +1372,14 @@ static qboolean CModQ2_LoadTexInfo (model_t *mod, qbyte *mod_base, lump_t *l, ch
Q_strncatz(sname, "#ALPHA=0.66", sizeof(sname));
else if (out->flags & TI_TRANS33)
Q_strncatz(sname, "#ALPHA=0.33", sizeof(sname));
else if (out->flags & (TI_WARP|TI_FLOWING))
else if (out->flags & (TI_WARP))
Q_strncatz(sname, "#ALPHA=1", sizeof(sname));
if (in->nexttexinfo != -1) //used to ensure non-looping and looping don't conflict and get confused.
Q_strncatz(sname, "#ANIMLOOP", sizeof(sname));
//in q2, 'TEX_SPECIAL' is TI_LIGHT, and that conflicts.
out->flags &= ~TI_LIGHT;
if (out->flags & (TI_SKY|TI_TRANS33|TI_TRANS66|TI_WARP|TI_FLOWING))
if (out->flags & (TI_SKY|TI_TRANS33|TI_TRANS66|TI_WARP))
out->flags |= TEX_SPECIAL;
//compact the textures.
@ -2212,6 +2218,7 @@ static qboolean CModQ3_LoadShaders (model_t *mod, qbyte *mod_base, lump_t *l)
static qboolean CModQ3_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
q3dvertex_t *in;
vecV_t *out;
vec3_t *nout;
@ -2242,17 +2249,17 @@ static qboolean CModQ3_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
nout = ZG_Malloc(&mod->memgroup, count*sizeof(*nout));
// sout = ZG_Malloc(&mod->memgroup, count*sizeof(*nout));
// tout = ZG_Malloc(&mod->memgroup, count*sizeof(*nout));
map_verts = out;
map_vertstmexcoords = stout;
prv->verts = out;
prv->vertstmexcoords = stout;
for (i = 0; i < MAXRLIGHTMAPS; i++)
{
map_vertlstmexcoords[i] = lmout;
map_colors4f_array[i] = cout;
prv->vertlstmexcoords[i] = lmout;
prv->colors4f_array[i] = cout;
}
map_normals_array = nout;
// map_svector_array = sout;
// map_tvector_array = tout;
numvertexes = count;
prv->normals_array = nout;
// prv->svector_array = sout;
// prv->tvector_array = tout;
prv->numvertexes = count;
for ( i=0 ; i<count ; i++, in++)
{
@ -2281,6 +2288,7 @@ static qboolean CModQ3_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
#ifdef RFBSPS
static qboolean CModRBSP_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
rbspvertex_t *in;
vecV_t *out;
vec3_t *nout;
@ -2311,17 +2319,17 @@ static qboolean CModRBSP_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
nout = ZG_Malloc(&mod->memgroup, count*sizeof(*nout));
// sout = ZG_Malloc(&mod->memgroup, count*sizeof(*sout));
// tout = ZG_Malloc(&mod->memgroup, count*sizeof(*tout));
map_verts = out;
map_vertstmexcoords = stout;
prv->verts = out;
prv->vertstmexcoords = stout;
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
map_vertlstmexcoords[sty] = lmout + sty*count;
map_colors4f_array[sty] = cout + sty*count;
prv->vertlstmexcoords[sty] = lmout + sty*count;
prv->colors4f_array[sty] = cout + sty*count;
}
map_normals_array = nout;
// map_svector_array = sout;
// map_tvector_array = tout;
numvertexes = count;
prv->normals_array = nout;
// prv->svector_array = sout;
// prv->tvector_array = tout;
prv->numvertexes = count;
for ( i=0 ; i<count ; i++, in++)
{
@ -2334,13 +2342,13 @@ static qboolean CModRBSP_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
{
stout[i][j] = LittleFloat ( ((float *)in->texcoords)[j] );
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
map_vertlstmexcoords[sty][i][j] = LittleFloat ( ((float *)in->texcoords)[j+2*(sty+1)] );
prv->vertlstmexcoords[sty][i][j] = LittleFloat ( ((float *)in->texcoords)[j+2*(sty+1)] );
}
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
for ( j=0 ; j < 4 ; j++)
{
map_colors4f_array[sty][i][j] = in->color[sty][j]/255.0f;
prv->colors4f_array[sty][i][j] = in->color[sty][j]/255.0f;
}
}
}
@ -2352,6 +2360,7 @@ static qboolean CModRBSP_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
#ifndef SERVERONLY
static qboolean CModQ3_LoadIndexes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
{
cminfo_t *prv = (cminfo_t*)loadmodel->meshinfo;
int i, count;
int *in;
index_t *out;
@ -2372,8 +2381,8 @@ static qboolean CModQ3_LoadIndexes (model_t *loadmodel, qbyte *mod_base, lump_t
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
map_surfindexes = out;
// map_numsurfindexes = count;
prv->surfindexes = out;
// prv->numsurfindexes = count;
for ( i=0 ; i<count ; i++)
out[i] = LittleLong (in[i]);
@ -2389,6 +2398,7 @@ CMod_LoadFaces
*/
static qboolean CModQ3_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
q3dface_t *in;
q3cface_t *out;
int i, count;
@ -2408,8 +2418,8 @@ static qboolean CModQ3_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
}
out = BZ_Malloc ( count*sizeof(*out) );
map_faces = out;
numfaces = count;
prv->faces = out;
prv->numfaces = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
@ -2439,6 +2449,7 @@ static qboolean CModQ3_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
#ifdef RFBSPS
static qboolean CModRBSP_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
rbspface_t *in;
q3cface_t *out;
int i, count;
@ -2458,8 +2469,8 @@ static qboolean CModRBSP_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
}
out = BZ_Malloc ( count*sizeof(*out) );
map_faces = out;
numfaces = count;
prv->faces = out;
prv->numfaces = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
@ -2573,7 +2584,7 @@ mfog_t *Mod_FogForOrigin(model_t *wmodel, vec3_t org)
static index_t tempIndexesArray[MAX_ARRAY_VERTS*6];
static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert)
static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert, cminfo_t *prv)
{
int patch_cp[2], step[2], size[2], flat[2];
float subdivlevel;
@ -2593,7 +2604,7 @@ static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numv
subdivlevel = 1;
// find the degree of subdivision in the u and v directions
Patch_GetFlatness ( subdivlevel, map_verts[firstvert], sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat );
Patch_GetFlatness ( subdivlevel, prv->verts[firstvert], sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat );
// allocate space for mesh
step[0] = (1 << flat[0]);
@ -2608,6 +2619,7 @@ static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numv
//mesh_t *GL_CreateMeshForPatch ( model_t *mod, q3dface_t *surf )
static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
int numindexes, patch_cp[2], step[2], size[2], flat[2], i, u, v, p;
index_t *indexes;
float subdivlevel;
@ -2628,7 +2640,7 @@ static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, i
subdivlevel = 1;
// find the degree of subdivision in the u and v directions
Patch_GetFlatness ( subdivlevel, map_verts[firstvert], sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat );
Patch_GetFlatness ( subdivlevel, prv->verts[firstvert], sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat );
// allocate space for mesh
step[0] = (1 << flat[0]);
@ -2654,24 +2666,24 @@ static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, i
// fill in
Patch_Evaluate ( map_verts[firstvert], patch_cp, step, mesh->xyz_array[0], sizeof(vecV_t)/sizeof(vec_t));
Patch_Evaluate ( prv->verts[firstvert], patch_cp, step, mesh->xyz_array[0], sizeof(vecV_t)/sizeof(vec_t));
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
if (mesh->colors4f_array[sty])
Patch_Evaluate ( map_colors4f_array[sty][firstvert], patch_cp, step, mesh->colors4f_array[sty][0], 4 );
Patch_Evaluate ( prv->colors4f_array[sty][firstvert], patch_cp, step, mesh->colors4f_array[sty][0], 4 );
}
Patch_Evaluate ( map_normals_array[firstvert], patch_cp, step, mesh->normals_array[0], 3 );
Patch_Evaluate ( map_vertstmexcoords[firstvert], patch_cp, step, mesh->st_array[0], 2 );
Patch_Evaluate ( prv->normals_array[firstvert], patch_cp, step, mesh->normals_array[0], 3 );
Patch_Evaluate ( prv->vertstmexcoords[firstvert], patch_cp, step, mesh->st_array[0], 2 );
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
if (mesh->lmst_array[sty])
Patch_Evaluate ( map_vertlstmexcoords[sty][firstvert], patch_cp, step, mesh->lmst_array[sty][0], 2 );
Patch_Evaluate ( prv->vertlstmexcoords[sty][firstvert], patch_cp, step, mesh->lmst_array[sty][0], 2 );
}
// compute new indexes avoiding adding invalid triangles
numindexes = 0;
indexes = tempIndexesArray;
for (v = 0, i = 0; v < size[1]-1; v++)
for (v = 0, i = 0; v < size[1]-1; v++)
{
for (u = 0; u < size[0]-1; u++, i += 6)
{
@ -2711,6 +2723,7 @@ static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, i
#ifdef RFBSPS
static void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
rbspface_t *in = (rbspface_t*)(bd+1);
int idx = (out - mod->surfaces) - mod->firstmodelsurface;
int sty;
@ -2725,20 +2738,20 @@ static void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *b
unsigned int fv = LittleLong(in->firstvertex), i;
for (i = 0; i < out->mesh->numvertexes; i++)
{
VectorCopy(map_verts[fv + i], out->mesh->xyz_array[i]);
Vector2Copy(map_vertstmexcoords[fv + i], out->mesh->st_array[i]);
VectorCopy(prv->verts[fv + i], out->mesh->xyz_array[i]);
Vector2Copy(prv->vertstmexcoords[fv + i], out->mesh->st_array[i]);
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
Vector2Copy(map_vertlstmexcoords[sty][fv + i], out->mesh->lmst_array[sty][i]);
Vector4Copy(map_colors4f_array[sty][fv + i], out->mesh->colors4f_array[sty][i]);
Vector2Copy(prv->vertlstmexcoords[sty][fv + i], out->mesh->lmst_array[sty][i]);
Vector4Copy(prv->colors4f_array[sty][fv + i], out->mesh->colors4f_array[sty][i]);
}
VectorCopy(map_normals_array[fv + i], out->mesh->normals_array[i]);
VectorCopy(prv->normals_array[fv + i], out->mesh->normals_array[i]);
}
fv = LittleLong(in->firstindex);
for (i = 0; i < out->mesh->numindexes; i++)
{
out->mesh->indexes[i] = map_surfindexes[fv + i];
out->mesh->indexes[i] = prv->surfindexes[fv + i];
}
}
else
@ -2785,6 +2798,7 @@ static void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *b
static void CModQ3_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
q3dface_t *in = (q3dface_t*)(bd+1);
int idx = (out - mod->surfaces) - mod->firstmodelsurface;
in += idx;
@ -2795,20 +2809,19 @@ static void CModQ3_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd)
}
else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP)
{
unsigned int fv = LittleLong(in->firstvertex), i;
unsigned int fv = LittleLong(in->firstvertex), fi = LittleLong(in->firstindex), i;
for (i = 0; i < out->mesh->numvertexes; i++)
{
VectorCopy(map_verts[fv + i], out->mesh->xyz_array[i]);
Vector2Copy(map_vertstmexcoords[fv + i], out->mesh->st_array[i]);
Vector2Copy(map_vertlstmexcoords[0][fv + i], out->mesh->lmst_array[0][i]);
Vector4Copy(map_colors4f_array[0][fv + i], out->mesh->colors4f_array[0][i]);
VectorCopy(prv->verts[fv + i], out->mesh->xyz_array[i]);
Vector2Copy(prv->vertstmexcoords[fv + i], out->mesh->st_array[i]);
Vector2Copy(prv->vertlstmexcoords[0][fv + i], out->mesh->lmst_array[0][i]);
Vector4Copy(prv->colors4f_array[0][fv + i], out->mesh->colors4f_array[0][i]);
VectorCopy(map_normals_array[fv + i], out->mesh->normals_array[i]);
VectorCopy(prv->normals_array[fv + i], out->mesh->normals_array[i]);
}
fv = LittleLong(in->firstindex);
for (i = 0; i < out->mesh->numindexes; i++)
{
out->mesh->indexes[i] = map_surfindexes[fv + i];
out->mesh->indexes[i] = prv->surfindexes[fi + i];
}
}
else
@ -2916,9 +2929,9 @@ static qboolean CModQ3_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
fv = LittleLong(in->firstvertex);
{
vec3_t v[3];
VectorCopy(map_verts[fv+0], v[0]);
VectorCopy(map_verts[fv+1], v[1]);
VectorCopy(map_verts[fv+2], v[2]);
VectorCopy(prv->verts[fv+0], v[0]);
VectorCopy(prv->verts[fv+1], v[1]);
VectorCopy(prv->verts[fv+2], v[2]);
PlaneFromPoints(v, pl);
CategorizePlane(pl);
}
@ -2944,7 +2957,7 @@ static qboolean CModQ3_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
else if (facetype == MST_PATCH)
{
out->mesh = &mesh[surfnum];
GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex));
GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv);
}
else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP)
{
@ -3027,9 +3040,9 @@ static qboolean CModRBSP_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
fv = LittleLong(in->firstvertex);
{
vec3_t v[3];
VectorCopy(map_verts[fv+0], v[0]);
VectorCopy(map_verts[fv+1], v[1]);
VectorCopy(map_verts[fv+2], v[2]);
VectorCopy(prv->verts[fv+0], v[0]);
VectorCopy(prv->verts[fv+1], v[1]);
VectorCopy(prv->verts[fv+2], v[2]);
PlaneFromPoints(v, pl);
CategorizePlane(pl);
}
@ -3055,7 +3068,7 @@ static qboolean CModRBSP_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
else if (facetype == MST_PATCH)
{
out->mesh = &mesh[surfnum];
GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex));
GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv);
}
else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP)
{
@ -4031,7 +4044,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
CMod_LoadEntityString (mod, cmod_base, &header.lumps[Q3LUMP_ENTITIES]);
*/
map_faces = NULL;
prv->faces = NULL;
Q1BSPX_Setup(mod, mod_base, filelen, header.lumps, Q3LUMPS_TOTAL);
@ -4123,8 +4136,8 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
if (!noerrors)
{
if (map_faces)
BZ_Free(map_faces);
if (prv->faces)
BZ_Free(prv->faces);
return NULL;
}
@ -4182,14 +4195,14 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
if (!CM_CreatePatchesForLeafs (mod, prv)) //for clipping
{
BZ_Free(map_faces);
BZ_Free(prv->faces);
return NULL;
}
#ifndef CLIENTONLY
CMQ3_CalcPHS(mod);
#endif
// BZ_Free(map_verts);
BZ_Free(map_faces);
BZ_Free(prv->faces);
break;
#endif
#ifdef Q2BSPS
@ -6222,6 +6235,99 @@ qbyte *CM_ClusterPHS (model_t *mod, int cluster, pvsbuffer_t *buffer)
return buffer->buffer;
}
unsigned int SV_Q2BSP_FatPVS (model_t *mod, vec3_t org, pvsbuffer_t *result, qboolean merge)
{
int leafs[64];
int i, j, count;
vec3_t mins, maxs;
for (i=0 ; i<3 ; i++)
{
mins[i] = org[i] - 8;
maxs[i] = org[i] + 8;
}
count = CM_BoxLeafnums (mod, mins, maxs, leafs, countof(leafs), NULL);
if (count < 1)
Sys_Error ("SV_Q2FatPVS: count < 1");
// convert leafs to clusters
for (i=0 ; i<count ; i++)
leafs[i] = CM_LeafCluster(mod, leafs[i]);
//grow the buffer if needed
if (result->buffersize < mod->pvsbytes)
result->buffer = BZ_Realloc(result->buffer, result->buffersize=mod->pvsbytes);
if (count == 1 && leafs[0] == -1)
{ //if the only leaf is the outside then broadcast it.
memset(result->buffer, 0xff, mod->pvsbytes);
i = count;
}
else
{
i = 0;
if (!merge)
mod->funcs.ClusterPVS(mod, leafs[i++], result, PVM_REPLACE);
// or in all the other leaf bits
for ( ; i<count ; i++)
{
for (j=0 ; j<i ; j++)
if (leafs[i] == leafs[j])
break;
if (j != i)
continue; // already have the cluster we want
mod->funcs.ClusterPVS(mod, leafs[i], result, PVM_MERGE);
}
}
return mod->pvsbytes;
}
static int clientarea;
unsigned int Q23BSP_FatPVS(model_t *mod, vec3_t org, pvsbuffer_t *buffer, qboolean merge)
{//fixme: this doesn't add areas
int leafnum;
leafnum = CM_PointLeafnum (mod, org);
clientarea = CM_LeafArea (mod, leafnum);
return SV_Q2BSP_FatPVS (mod, org, buffer, merge);
}
qboolean Q23BSP_EdictInFatPVS(model_t *mod, pvscache_t *ent, qbyte *pvs)
{
int i,l;
int nullarea = (mod->fromgame == fg_quake2)?0:-1;
if (clientarea == ent->areanum)
{
if (clientarea == nullarea)
return false;
}
else if (!CM_AreasConnected (mod, clientarea, ent->areanum))
{ // doors can legally straddle two areas, so
// we may need to check another one
if (ent->areanum2 == nullarea
|| !CM_AreasConnected (mod, clientarea, ent->areanum2))
return false; // blocked by a door
}
if (ent->num_leafs == -1)
{ // too many leafs for individual check, go by headnode
if (!CM_HeadnodeVisible (mod, ent->headnode, pvs))
return false;
}
else
{ // check individual leafs
for (i=0 ; i < ent->num_leafs ; i++)
{
l = ent->leafnums[i];
if (pvs[l >> 3] & (1 << (l&7) ))
break;
}
if (i == ent->num_leafs)
return false; // not visible
}
return true;
}
/*
===============================================================================
@ -6415,17 +6521,20 @@ Reads the portal state from a savegame file
and recalculates the area connections
===================
*/
void CM_ReadPortalState (model_t *mod, vfsfile_t *f)
qofs_t CM_ReadPortalState (model_t *mod, qbyte *ptr, qofs_t ptrsize)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
size_t result;
result = VFS_READ(f, prv->portalopen, sizeof(prv->portalopen)); // do something with result
if (ptrsize < sizeof(prv->portalopen))
Con_Printf("CM_ReadPortalState() expected %u, but only %u available\n",(unsigned int)sizeof(prv->portalopen),(unsigned int)ptrsize);
else
{
memcpy(prv->portalopen, ptr, sizeof(prv->portalopen));
if (result != sizeof(prv->portalopen))
Con_Printf("CM_ReadPortalState() fread: expected %u, result was %u\n",(unsigned int)sizeof(prv->portalopen),(unsigned int)result);
FloodAreaConnections (prv);
FloodAreaConnections (prv);
return sizeof(prv->portalopen);
}
return 0;
}
/*

View File

@ -61,7 +61,7 @@ static void QDECL Log_Name_Callback (struct cvar_s *var, char *oldvalue)
}
// Con_Log: log string to console log
void Log_String (logtype_t lognum, char *s)
void Log_String (logtype_t lognum, const char *s)
{
vfsfile_t *fi;
char *d; // directory
@ -226,7 +226,7 @@ void Log_String (logtype_t lognum, char *s)
}
}
void Con_Log (char *s)
void Con_Log (const char *s)
{
Log_String(LOG_CONSOLE, s);
}

View File

@ -14,9 +14,11 @@
static char *cvargroup_progs = "Progs variables";
cvar_t sv_gameplayfix_nolinknonsolid = CVARD("sv_gameplayfix_nolinknonsolid", "1", "When 0, setorigin et al will not link the entity into the collision nodes (which is faster, especially if you have a lot of non-solid entities. When 1, allows entities to freely switch between .solid values (except for SOLID_BSP) without relinking. A lot of DP mods assume a value of 1 and will bug out otherwise, while 0 will restore a bugs present in various mods.");
cvar_t sv_gameplayfix_blowupfallenzombies = CVARD("sv_gameplayfix_blowupfallenzombies", "0", "Allow findradius to find non-solid entities. This may break certain mods.");
cvar_t pr_droptofloorunits = CVARD("pr_droptofloorunits", "256", "Distance that droptofloor is allowed to drop to be considered successul.");
cvar_t pr_brokenfloatconvert = CVAR("pr_brokenfloatconvert", "0");
cvar_t pr_fixbrokenqccarrays = CVARFD("pr_fixbrokenqccarrays", "0", CVAR_LATCH, "As part of its nq/qw/h2/csqc support, FTE remaps QC fields to match an internal order. This is a faster way to handle extended fields. However, some QCCs are buggy and don't report all field defs.\n0: do nothing. QCC must be well behaved.\n1: Duplicate engine fields, remap the ones we can to known offsets. This is sufficient for QCCX/FrikQCC mods that use hardcoded or even occasional calculated offsets (fixes ktpro).\n2: Scan the mod for field accessing instructions, and assume those are the fields (and that they don't alias non-fields). This can be used to work around gmqcc's WTFs (fixes xonotic).");
cvar_t pr_tempstringcount = CVARD("pr_tempstringcount", "", "Obsolete. Set to 16 if you want to recycle+reuse the same 16 tempstring references and break lots of mods.");
cvar_t pr_tempstringsize = CVARD("pr_tempstringsize", "4096", "Obsolete");
cvar_t pr_sourcedir = CVARD("pr_sourcedir", "src", "Subdirectory where your qc source is located. Used by the internal compiler and qc debugging functionality.");
@ -42,6 +44,7 @@ void PF_Common_RegisterCvars(void)
Cvar_Register (&sv_gameplayfix_blowupfallenzombies, cvargroup_progs);
Cvar_Register (&sv_gameplayfix_nolinknonsolid, cvargroup_progs);
Cvar_Register (&pr_droptofloorunits, cvargroup_progs);
Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs);
Cvar_Register (&pr_tempstringcount, cvargroup_progs);
@ -51,6 +54,7 @@ void PF_Common_RegisterCvars(void)
#endif
Cvar_Register (&pr_enable_profiling, cvargroup_progs);
Cvar_Register (&pr_sourcedir, cvargroup_progs);
Cvar_Register (&pr_fixbrokenqccarrays, cvargroup_progs);
#ifdef RAGDOLL
Cmd_AddCommand("skel_info", skel_info_f);
@ -75,15 +79,18 @@ static void PF_Warningf(pubprogfuncs_t *prinst, const char *fmt, ...)
Con_Printf("%s", string);
}
char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_globals)
const char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_globals)
{
#define VARSTRINGLEN 16384+8
#define VARSTRINGLEN 65536+8
int i;
static char buffer[2][VARSTRINGLEN];
static int bufnum;
const char *s;
char *out;
if (prinst->callargc - first == 1)
return PR_GetStringOfs(prinst, OFS_PARM0+first*3); //no need to copy/etc.
out = buffer[(bufnum++)&1];
out[0] = 0;
@ -730,7 +737,6 @@ void QCBUILTIN PF_getsurfacetexture(pubprogfuncs_t *prinst, struct globalvars_s
ent = G_WEDICT(prinst, OFS_PARM0);
surfnum = G_FLOAT(OFS_PARM1);
model = w->Get_CModel(w, ent->v->modelindex);
G_INT(OFS_RETURN) = 0;
@ -852,31 +858,14 @@ static float getsurface_clippointtri(model_t *model, msurface_t *surf, vec3_t po
}
return bestdist;
}
// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
void QCBUILTIN PF_getsurfacenearpoint(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
msurface_t *Mod_GetSurfaceNearPoint(model_t *model, vec3_t point)
{
model_t *model;
wedict_t *ent;
msurface_t *surf;
int i;
float *point;
vec3_t cpoint = {0,0,0};
float bestdist = 0x7fffffff, dist;
int bestsurf = -1;
world_t *w = prinst->parms->user;
ent = G_WEDICT(prinst, OFS_PARM0);
point = G_VECTOR(OFS_PARM1);
G_FLOAT(OFS_RETURN) = -1;
model = w->Get_CModel(w, ent->v->modelindex);
if (!model || model->type != mod_brush)
return;
bestdist = 256;
msurface_t *bestsurf = NULL;
if (model->fromgame == fg_quake || model->fromgame == fg_quake2)
{
@ -888,7 +877,7 @@ void QCBUILTIN PF_getsurfacenearpoint(pubprogfuncs_t *prinst, struct globalvars_
if (dist < bestdist)
{
bestdist = dist;
bestsurf = i;
bestsurf = surf;
}
}
}
@ -902,11 +891,29 @@ void QCBUILTIN PF_getsurfacenearpoint(pubprogfuncs_t *prinst, struct globalvars_
if (dist < bestdist)
{
bestdist = dist;
bestsurf = i;
bestsurf = surf;
}
}
}
G_FLOAT(OFS_RETURN) = bestsurf;
return bestsurf;
}
// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
void QCBUILTIN PF_getsurfacenearpoint(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
wedict_t *ent = G_WEDICT(prinst, OFS_PARM0);
float *point = G_VECTOR(OFS_PARM1);
world_t *w = prinst->parms->user;
model_t *model = w->Get_CModel(w, ent->v->modelindex);
msurface_t *surf;
G_FLOAT(OFS_RETURN) = -1;
if (model && model->type == mod_brush)
{
surf = Mod_GetSurfaceNearPoint(model, point);
if (surf)
G_FLOAT(OFS_RETURN) = surf - (model->surfaces + model->firstmodelsurface);
}
}
// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
@ -1159,98 +1166,104 @@ void QCBUILTIN PF_touchtriggers(pubprogfuncs_t *prinst, struct globalvars_s *pr_
////////////////////////////////////////////////////
//Finding
/*
//entity(string field, float match) findchainflags = #450
//chained search for float, int, and entity reference fields
void PF_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
int i, ff, cf;
int s;
edict_t *ent, *chain;
wedict_t *ent, *chain;
chain = (edict_t *) *prinst->parms->sv_edicts;
chain = (wedict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
ff = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = G_FLOAT(OFS_PARM1);
if (prinst->callargc > 2)
cf = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
cf = &((comentvars_t*)NULL)->chain - (int*)NULL;
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ent->isfree)
ent = WEDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
if (!((int)((float *)ent->v)[f] & s))
if (!((int)((float *)ent->v)[ff] & s))
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
((int*)ent->v)[cf] = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
RETURN_EDICT(prinst, chain);
}
*/
/*
//entity(string field, float match) findchainfloat = #403
void PF_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
int i, ff, cf;
float s;
edict_t *ent, *chain;
wedict_t *ent, *chain;
chain = (edict_t *) *prinst->parms->sv_edicts;
chain = (wedict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
ff = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = G_FLOAT(OFS_PARM1);
if (prinst->callargc > 2)
cf = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
cf = &((comentvars_t*)NULL)->chain - (int*)NULL;
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ent->isfree)
ent = WEDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
if (((float *)ent->v)[f] != s)
if (((float *)ent->v)[ff] != s)
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
((int*)ent->v)[cf] = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
RETURN_EDICT(prinst, chain);
}
*/
/*
//entity(string field, string match) findchain = #402
//chained search for strings in entity fields
void PF_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
char *s;
int i, ff, cf;
const char *s;
string_t t;
edict_t *ent, *chain;
wedict_t *ent, *chain;
chain = (wedict_t *) *prinst->parms->sv_edicts;
chain = (edict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
ff = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = PR_GetStringOfs(prinst, OFS_PARM1);
if (prinst->callargc > 2)
cf = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
cf = &((comentvars_t*)NULL)->chain - (int*)NULL;
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ent->isfree)
ent = WEDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
t = *(string_t *)&((float*)ent->v)[f];
t = *(string_t *)&((float*)ent->v)[ff];
if (!t)
continue;
if (strcmp(PR_GetString(prinst, t), s))
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
((int*)ent->v)[cf] = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
RETURN_EDICT(prinst, chain);
}
*/
//EXTENSION: DP_QC_FINDFLAGS
//entity(entity start, float fld, float match) findflags = #449
@ -1888,14 +1901,14 @@ void QCBUILTIN PF_fopen (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
if (i == MAX_QC_FILES) //too many already open
{
Con_Printf("qcfopen: too many files open (trying %s)\n", name);
Con_Printf("qcfopen(\"%s\"): too many files open\n", name);
G_FLOAT(OFS_RETURN) = -1;
return;
}
if (!QC_FixFileName(name, &name, &fallbackread))
{
Con_Printf("qcfopen: Access denied: %s\n", name);
Con_Printf("qcfopen(\"%s\"): Access denied\n", name);
G_FLOAT(OFS_RETURN) = -1;
return;
}
@ -2167,7 +2180,7 @@ static qboolean PF_fresizebuffer_internal (pf_fopen_files_t *f, size_t newlen)
}
return true;
}
static int PF_fwrite_internal (pubprogfuncs_t *prinst, int fnum, char *msg, size_t len)
static int PF_fwrite_internal (pubprogfuncs_t *prinst, int fnum, const char *msg, size_t len)
{
if (fnum < 0 || fnum >= MAX_QC_FILES)
{
@ -2249,7 +2262,7 @@ static int PF_fread_internal (pubprogfuncs_t *prinst, int fnum, char *msg, size_
void QCBUILTIN PF_fputs (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX;
char *msg = PF_VarString(prinst, 1, pr_globals);
const char *msg = PF_VarString(prinst, 1, pr_globals);
int len = strlen(msg);
PF_fwrite_internal (prinst, fnum, msg, len);
@ -2845,6 +2858,7 @@ void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
float *org;
vec3_t eorg;
int i, j;
int f;
chain = w->edicts;
@ -2852,6 +2866,11 @@ void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
rad = G_FLOAT(OFS_PARM1);
rad = rad*rad;
if (prinst->callargc > 2)
f = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
f = &((comentvars_t*)NULL)->chain - (int*)NULL;
for (i=1 ; i<w->num_edicts ; i++)
{
ent = WEDICT_NUM(prinst, i);
@ -2864,7 +2883,7 @@ void QCBUILTIN PF_findradius (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
if (DotProduct(eorg,eorg) > rad)
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
((int*)ent->v)[f] = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
@ -3073,7 +3092,7 @@ void QCBUILTIN PF_strpad (pubprogfuncs_t *prinst, struct globalvars_s *pr_global
char destbuf[4096];
char *dest = destbuf;
int pad = G_FLOAT(OFS_PARM0);
char *src = PF_VarString(prinst, 1, pr_globals);
const char *src = PF_VarString(prinst, 1, pr_globals);
//UTF-8-FIXME: pad is chars not bytes...
@ -3220,7 +3239,7 @@ void QCBUILTIN PF_strconv (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
int ccase = G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper
int redalpha = G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate
int rednum = G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate
unsigned char *string = PF_VarString(prinst, 3, pr_globals);
const unsigned char *string = PF_VarString(prinst, 3, pr_globals);
int len = strlen(string);
int i;
unsigned char resbuf[8192];
@ -3417,7 +3436,7 @@ void QCBUILTIN PF_stoh (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_stov (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i;
char *s;
const char *s;
float *out;
s = PF_VarString(prinst, 0, pr_globals);
@ -3507,7 +3526,7 @@ void QCBUILTIN PF_strzone(pubprogfuncs_t *prinst, struct globalvars_s *pr_global
#endif
}
//string(string str1, string str2) strcat
//string(string str1, string str2, str3, etc) strcat
void QCBUILTIN PF_strcat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *buf;
@ -3740,7 +3759,7 @@ void QCBUILTIN PF_strtoupper (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
//DP_QC_STRFTIME
void QCBUILTIN PF_strftime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *in = PF_VarString(prinst, 1, pr_globals);
const char *in = PF_VarString(prinst, 1, pr_globals);
char result[8192];
char uresult[8192];
@ -3778,14 +3797,14 @@ struct strbuf {
};
#define BUFSTRBASE 1
#define NUMSTRINGBUFS 64
struct strbuf strbuflist[NUMSTRINGBUFS];
struct strbuf *strbuflist;
size_t strbufmax;
void PF_buf_shutdown(pubprogfuncs_t *prinst)
{
size_t i, bufno;
for (bufno = 0; bufno < NUMSTRINGBUFS; bufno++)
for (bufno = 0; bufno < strbufmax; bufno++)
{
if (strbuflist[bufno].prinst == prinst)
{
@ -3800,6 +3819,13 @@ void PF_buf_shutdown(pubprogfuncs_t *prinst)
strbuflist[bufno].prinst = NULL;
}
}
while (strbufmax>0 && !strbuflist[strbufmax-1].prinst)
strbufmax--;
if (!strbufmax)
{
Z_Free(strbuflist);
strbuflist = NULL;
}
}
// #440 float() buf_create (DP_QC_STRINGBUFFERS)
@ -3820,19 +3846,24 @@ void QCBUILTIN PF_buf_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
//flags&1 == saved. apparently.
for (i = 0; i < NUMSTRINGBUFS; i++)
for (i = 0; i < strbufmax; i++)
{
if (!strbuflist[i].prinst)
break;
}
if (i == strbufmax)
{
if (!ZF_ReallocElements((void**)&strbuflist, &strbufmax, strbufmax+1, sizeof(*strbuflist)))
{
strbuflist[i].prinst = prinst;
strbuflist[i].used = 0;
strbuflist[i].allocated = 0;
strbuflist[i].strings = NULL;
G_FLOAT(OFS_RETURN) = i+BUFSTRBASE;
G_FLOAT(OFS_RETURN) = -1;
return;
}
}
G_FLOAT(OFS_RETURN) = -1;
strbuflist[i].prinst = prinst;
strbuflist[i].used = 0;
strbuflist[i].allocated = 0;
strbuflist[i].strings = NULL;
G_FLOAT(OFS_RETURN) = i+BUFSTRBASE;
}
// #441 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
void QCBUILTIN PF_buf_del (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -3840,7 +3871,7 @@ void QCBUILTIN PF_buf_del (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
size_t i;
size_t bufno = G_FLOAT(OFS_PARM0)-BUFSTRBASE;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -3860,7 +3891,7 @@ void QCBUILTIN PF_buf_getsize (pubprogfuncs_t *prinst, struct globalvars_s *pr_
{
size_t bufno = G_FLOAT(OFS_PARM0)-BUFSTRBASE;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -3876,11 +3907,11 @@ void QCBUILTIN PF_buf_copy (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
if (bufto == buffrom) //err...
return;
if (buffrom >= NUMSTRINGBUFS)
if (buffrom >= strbufmax)
return;
if (strbuflist[buffrom].prinst != prinst)
return;
if (bufto >= NUMSTRINGBUFS)
if (bufto >= strbufmax)
return;
if (strbuflist[bufto].prinst != prinst)
return;
@ -3914,7 +3945,7 @@ void QCBUILTIN PF_buf_sort (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
int s,d;
char **strings;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -3951,7 +3982,7 @@ void QCBUILTIN PF_buf_implode (pubprogfuncs_t *prinst, struct globalvars_s *pr_
char **strings;
char *ret;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -3996,7 +4027,7 @@ void QCBUILTIN PF_bufstr_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
size_t bufno = G_FLOAT(OFS_PARM0)-BUFSTRBASE;
size_t index = G_FLOAT(OFS_PARM1);
if ((unsigned int)bufno >= NUMSTRINGBUFS)
if ((unsigned int)bufno >= strbufmax)
{
RETURN_CSTRING("");
return;
@ -4023,7 +4054,7 @@ void QCBUILTIN PF_bufstr_set (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
const char *string = PR_GetStringOfs(prinst, OFS_PARM2);
size_t oldcount;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -4094,7 +4125,7 @@ void QCBUILTIN PF_bufstr_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
const char *string = PR_GetStringOfs(prinst, OFS_PARM1);
int order = G_FLOAT(OFS_PARM2);
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -4107,7 +4138,7 @@ void QCBUILTIN PF_bufstr_free (pubprogfuncs_t *prinst, struct globalvars_s *pr_
size_t bufno = G_FLOAT(OFS_PARM0)-BUFSTRBASE;
size_t index = G_FLOAT(OFS_PARM1);
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -4130,7 +4161,7 @@ void QCBUILTIN PF_buf_cvarlist (pubprogfuncs_t *prinst, struct globalvars_s *pr
cvar_t *var;
extern cvar_group_t *cvar_groups;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -4165,7 +4196,7 @@ void QCBUILTIN PF_buf_loadfile (pubprogfuncs_t *prinst, struct globalvars_s *pr
G_FLOAT(OFS_RETURN) = 0;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -4200,7 +4231,7 @@ void QCBUILTIN PF_buf_writefile (pubprogfuncs_t *prinst, struct globalvars_s *p
G_FLOAT(OFS_RETURN) = 0;
if (bufno >= NUMSTRINGBUFS)
if (bufno >= strbufmax)
return;
if (strbuflist[bufno].prinst != prinst)
return;
@ -4238,7 +4269,7 @@ void QCBUILTIN PF_buf_writefile (pubprogfuncs_t *prinst, struct globalvars_s *p
void QCBUILTIN PF_crc16 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int insens = G_FLOAT(OFS_PARM0);
char *str = PF_VarString(prinst, 1, pr_globals);
const char *str = PF_VarString(prinst, 1, pr_globals);
int len = strlen(str);
if (insens)
@ -4254,27 +4285,28 @@ void QCBUILTIN PF_digest_hex (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
int digestsize, i;
unsigned char digest[64];
unsigned char hexdig[sizeof(digest)*2+1];
size_t len = strlen(str);
if (!strcmp(hashtype, "MD4"))
{
digestsize = 16;
Com_BlockFullChecksum(str, strlen(str), digest);
Com_BlockFullChecksum(str, len, digest);
}
//md5?
else if (!strcmp(hashtype, "SHA1"))
{
digestsize = SHA1(digest, sizeof(digest), str, strlen(str));
digestsize = SHA1(digest, sizeof(digest), str, len);
}
// else if (!strcmp(hashtype, "SHA256"))
// {
// digestsize = SHA2(digest, sizeof(digest), str, strlen(str));
// digestsize = SHA2(digest, sizeof(digest), str, len);
// }
//sha384
//sha512
else if (!strcmp(hashtype, "CRC16"))
{
digestsize = 2;
*(unsigned short*)digest = QCRC_Block(str, strlen(str));
*(unsigned short*)digest = QCRC_Block(str, len);
}
else
digestsize = 0;
@ -5173,7 +5205,7 @@ void QCBUILTIN PF_externset (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
{
int n = G_PROG(OFS_PARM0);
int v = G_INT(OFS_PARM1);
char *varname = PF_VarString(prinst, 2, pr_globals);
const char *varname = PF_VarString(prinst, 2, pr_globals);
eval_t *var;
var = PR_FindGlobal(prinst, varname, n, NULL);
@ -5185,7 +5217,7 @@ void QCBUILTIN PF_externset (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
void QCBUILTIN PF_externvalue (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) //return a value in annother progs
{
int n = G_PROG(OFS_PARM0);
char *varname = PF_VarString(prinst, 1, pr_globals);
const char *varname = PF_VarString(prinst, 1, pr_globals);
eval_t *var;
if (*varname == '&')
@ -5286,7 +5318,7 @@ void QCBUILTIN PF_break (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
void QCBUILTIN PF_error (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
s = PF_VarString(prinst, 0, pr_globals);
/* Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s);
@ -5318,7 +5350,7 @@ void QCBUILTIN PF_error (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
//Sends text over to the client's execution buffer
void QCBUILTIN PF_localcmd (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str;
const char *str;
str = PF_VarString(prinst, 0, pr_globals);
if (developer.ival >= 2)
@ -5785,13 +5817,41 @@ void QCBUILTIN PF_getentityfieldstring (pubprogfuncs_t *prinst, struct globalvar
eval_t *eval;
unsigned int count = 0;
fdef_t *fdef = prinst->FieldInfo(prinst, &count);
G_INT(OFS_RETURN) = 0;
if (fidx < count)
{
#if !defined(CLIENTONLY) && !defined(NOLEGACY)
qboolean isserver = (prinst == sv.world.progs);
#endif
eval = (eval_t *)&((float *)ent->v)[fdef[fidx].ofs];
#ifndef NOLEGACY //extra code to be lazy so that xonotic doesn't go crazy and spam the fuck out of e
if ((fdef->type & 0xff) == ev_vector)
{
if (eval->_vector[0]==0&&eval->_vector[1]==0&&eval->_vector[2]==0)
return;
}
#ifndef CLIENTONLY
else if (isserver && (float*)eval == &((edict_t*)ent)->xv->drawflags && eval->_float == 96)
return;
else if (isserver && (float*)eval == &((edict_t*)ent)->xv->uniquespawnid)
return;
#endif
else if (((float*)eval == &ent->xv->dimension_solid ||
(float*)eval == &ent->xv->dimension_hit
#ifndef CLIENTONLY
|| (isserver && ((float*)eval == &((edict_t*)ent)->xv->dimension_see
|| (float*)eval == &((edict_t*)ent)->xv->dimension_seen))
#endif
) && eval->_float == 255)
return;
else
{
if (!eval->_int)
return;
}
#endif
RETURN_TSTRING(prinst->UglyValueString(prinst, fdef[fidx].type, eval));
}
else
G_INT(OFS_RETURN) = 0;
}
//float(float fieldnum, entity ent, string s)
void QCBUILTIN PF_putentityfieldstring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -6227,6 +6287,7 @@ lh_extension_t QSG_Extensions[] = {
{"DP_QUAKE2_SPRITE"},
{"DP_QUAKE3_MODEL"},
{"DP_REGISTERCVAR", 1, NULL, {"registercvar"}},
{"DP_SND_SOUND7_WIP2"}, //listed only to silence xonotic, if anyone tries running that.
{"DP_SND_STEREOWAV"},
{"DP_SND_OGGVORBIS"},
{"DP_SOLIDCORPSE"},

View File

@ -65,6 +65,7 @@ char *PF_TempStr(pubprogfuncs_t *prinst); //returns a tempstring which can be fi
extern cvar_t pr_tempstringsize;
extern cvar_t pr_tempstringcount;
extern cvar_t pr_enable_profiling;
extern cvar_t pr_fixbrokenqccarrays;
extern int qcinput_scan;
extern int qcinput_unicode;
@ -176,7 +177,7 @@ void QCBUILTIN PF_htos (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_ftoi (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_itof (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void PR_fclose_progs (pubprogfuncs_t *prinst);
char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
const char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename);
void PR_AutoCvar(pubprogfuncs_t *prinst, cvar_t *var);
void QCBUILTIN PF_numentityfields (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -404,6 +405,7 @@ void QCBUILTIN PF_cl_getcursormode (pubprogfuncs_t *prinst, struct globalvars_s
void QCBUILTIN PF_cl_setwindowcaption (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_playingdemo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_runningserver (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getgamedirinfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cs_media_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cs_media_destroy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cs_media_command (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View File

@ -1567,6 +1567,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, framestate_t *framestate,
traceinfo.solidcontents = hitcontentsmask;
Q1BSP_RecursiveBrushCheck(&traceinfo, model->rootnode, 0, 1, start, end);
memcpy(trace, &traceinfo.trace, sizeof(trace_t));
trace->contents = FTECONTENTS_SOLID;
if (trace->fraction < 1)
{
float d1 = DotProduct(start, trace->plane.normal) - trace->plane.dist;
@ -1604,6 +1605,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, framestate_t *framestate,
end_l[0] = DotProduct(tmp, axis[0]);
end_l[1] = DotProduct(tmp, axis[1]);
end_l[2] = DotProduct(tmp, axis[2]);
trace->contents = FTECONTENTS_SOLID;
Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace);
if (trace->fraction == 1)

View File

@ -120,15 +120,16 @@ typedef struct q2trace_s
#define MOVE_NORMAL 0
#define MOVE_NOMONSTERS 1
#define MOVE_MISSILE 2
#define MOVE_HITMODEL 4
#define MOVE_RESERVED 8 //so we are less likly to get into tricky situations when we want to steal annother future DP extension.
#define MOVE_TRIGGERS 16 //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse)
#define MOVE_EVERYTHING 32 //can return triggers and non-solid items if they're marked with FINDABLE_NONSOLID (works even if the items are not properly linked)
#define MOVE_LAGGED 64 //trace touches current last-known-state, instead of actual ents (just affects players for now)
#define MOVE_ENTCHAIN 128 //chain of impacted ents, otherwise result shows only world
#define MOVE_OTHERONLY 256 //test the trace against a single entity, ignoring non-solid/owner/etc flags (but respecting contents).
#define MOVE_NOMONSTERS (1<<0)
#define MOVE_MISSILE (1<<1)
#define MOVE_WORLDONLY (MOVE_NOMONSTERS|MOVE_MISSILE)
#define MOVE_HITMODEL (1<<2)
#define MOVE_RESERVED (1<<3) //so we are less likly to get into tricky situations when we want to steal annother future DP extension.
#define MOVE_TRIGGERS (1<<4) //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse)
#define MOVE_EVERYTHING (1<<5) //can return triggers and non-solid items if they're marked with FINDABLE_NONSOLID (works even if the items are not properly linked)
#define MOVE_LAGGED (1<<6) //trace touches current last-known-state, instead of actual ents (just affects players for now)
#define MOVE_ENTCHAIN (1<<7) //chain of impacted ents, otherwise result shows only world
#define MOVE_OTHERONLY (1<<8) //test the trace against a single entity, ignoring non-solid/owner/etc flags (but respecting contents).
#define MOVE_IGNOREHULL (1u<<31) //used on tracelines etc to simplify the code a little
typedef struct areanode_s

View File

@ -109,7 +109,7 @@ static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int data
}
#endif
qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips)
qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mips)
{
int bytesperpixel = 4;
int bcbytes = 0;

View File

@ -25,7 +25,7 @@ void D3D8_DestroyTexture (texid_t tex)
tex->ptr = NULL;
}
qboolean D3D8_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips)
qboolean D3D8_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mips)
{
qbyte *fte_restrict out, *fte_restrict in;
int x, y, i;

View File

@ -18,7 +18,7 @@ void D3D9_DestroyTexture (texid_t tex)
tex->ptr = NULL;
}
qboolean D3D9_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips)
qboolean D3D9_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mips)
{
qbyte *fte_restrict out, *fte_restrict in;
int x, y, i;

View File

@ -354,6 +354,10 @@ static LRESULT WINAPI D3D9_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (!vid_initializing)
INS_RawInput_Read((HANDLE)lParam);
break;
case WM_DEVICECHANGE:
COM_AddWork(WG_MAIN, INS_DeviceChanged, NULL, NULL, uMsg, 0);
lRet = TRUE;
break;
case WM_SETCURSOR:
//only use a custom cursor if the cursor is inside the client area

View File

@ -492,6 +492,10 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
if (!vid_initializing)
INS_RawInput_Read((HANDLE)lParam);
break;
case WM_DEVICECHANGE:
COM_AddWork(WG_MAIN, INS_DeviceChanged, NULL, NULL, uMsg, 0);
lRet = TRUE;
break;
case WM_SETCURSOR:
//only use a custom cursor if the cursor is inside the client area

View File

@ -354,6 +354,10 @@ static LRESULT WINAPI D3D8_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (!vid_initializing)
INS_RawInput_Read((HANDLE)lParam);
break;
case WM_DEVICECHANGE:
COM_AddWork(WG_MAIN, INS_DeviceChanged, NULL, NULL, uMsg, 0);
lRet = TRUE;
break;
case WM_SETCURSOR:
//only use a custom cursor if the cursor is inside the client area

View File

@ -118,7 +118,7 @@ Global
{0018E098-B12A-4E4D-9B22-6772DA287080}.GLRelease|x64.ActiveCfg = Release|x64
{0018E098-B12A-4E4D-9B22-6772DA287080}.MDebug|Win32.ActiveCfg = Debug|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.MDebug|Win32.Build.0 = Debug|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.MDebug|x64.ActiveCfg = Release|x64
{0018E098-B12A-4E4D-9B22-6772DA287080}.MDebug|x64.ActiveCfg = Debug|x64
{0018E098-B12A-4E4D-9B22-6772DA287080}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.MinGLDebug|x64.ActiveCfg = Debug|x64
{0018E098-B12A-4E4D-9B22-6772DA287080}.MinGLRelease|Win32.ActiveCfg = Release|Win32

View File

@ -290,7 +290,7 @@ static void GL_Texturemode_Apply(GLenum targ, unsigned int flags)
}
}
qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
{
static int cubeface[] =
{
@ -303,6 +303,9 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
};
int targ, targface;
int i, j;
int nummips = mips->mipcount;
int encoding = mips->encoding;
if (gl_config.gles)
{
@ -310,10 +313,10 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
//this means we can't specify 24.0 modes with a 24.8 datatype.
//arguably we shouldn't do this anyway, but there are differences that q3 shaders can notice.
//fixme: move elsewhere?
if (mips->encoding == PTI_RGBX8)
mips->encoding = PTI_RGBA8;
if (mips->encoding == PTI_BGRX8)
mips->encoding = PTI_BGRA8;
if (encoding == PTI_RGBX8)
encoding = PTI_RGBA8;
if (encoding == PTI_BGRX8)
encoding = PTI_BGRA8;
}
if (!tex->num)
@ -350,15 +353,15 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
qglTexParameteri(targ, GL_TEXTURE_WRAP_R, GL_REPEAT);
}
if (targ == GL_TEXTURE_2D && mips->mipcount > 1)
if (targ == GL_TEXTURE_2D && nummips > 1)
{ //npot mipmapped textures are awkward.
//opengl floors.
for (i = 1; i < mips->mipcount; i++)
for (i = 1; i < nummips; i++)
{
if (mips->mip[i].width != (mips->mip[i-1].width>>1) ||
mips->mip[i].height != (mips->mip[i-1].height>>1))
if (mips->mip[i].width != max(1,(mips->mip[i-1].width>>1)) ||
mips->mip[i].height != max(1,(mips->mip[i-1].height>>1)))
{ //okay, this mip looks like it was sized wrongly. this can easily happen with dds files made for direct3d.
mips->mipcount = i;
nummips = i;
break;
}
}
@ -374,13 +377,13 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
{
if (tex->flags & IF_MIPCAP)
{
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(mips->mipcount-1, gl_mipcap_min));
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(mips->mipcount-1, gl_mipcap_max));
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(nummips-1, gl_mipcap_min));
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(nummips-1, gl_mipcap_max));
}
else
{
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, 0);
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, mips->mipcount-1);
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, nummips-1);
}
}
}
@ -391,10 +394,10 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
if (targ == GL_TEXTURE_3D)
{
targface = targ;
for (i = 0; i < mips->mipcount; i++)
for (i = 0; i < nummips; i++)
{
int size = mips->mip[i].height;
switch(mips->encoding)
switch(encoding)
{
case PTI_RGBX8:
qglTexImage3D(targface, i, GL_RGB, size, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
@ -424,7 +427,7 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
else
{
//2d or cubemaps
for (i = 0; i < mips->mipcount; i++)
for (i = 0; i < nummips; i++)
{
if (tex->flags & IF_TEXTYPE)
{
@ -436,7 +439,7 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips)
targface = targ;
j = i;
}
switch(mips->encoding)
switch(encoding)
{
#ifdef FTE_TARGET_WEB
case PTI_WHOLEFILE:

View File

@ -1093,8 +1093,14 @@ int CM_HeadnodeForBox (struct model_s *mod, vec3_t mins, vec3_t maxs);
//struct trace_s CM_TransformedBoxTrace (struct model_s *mod, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles);
struct model_s *CM_TempBoxModel(vec3_t mins, vec3_t maxs);
//for gamecode to control portals/areas
void CMQ2_SetAreaPortalState (model_t *mod, unsigned int portalnum, qboolean open);
void CMQ3_SetAreaPortalState (model_t *mod, unsigned int area1, unsigned int area2, qboolean open);
//for saved games to write the raw state.
void CM_WritePortalState (model_t *mod, vfsfile_t *f);
qofs_t CM_ReadPortalState (model_t *mod, qbyte *ptr, qofs_t ptrsize);
#endif

View File

@ -2480,6 +2480,9 @@ static shaderkey_t shaderkeys[] =
{"water", Shader_DP_Water, "dp"},
{"reflect", Shader_DP_Reflect, "dp"},
{"refract", Shader_DP_Refract, "dp"},
{"offsetmapping", NULL, "dp"},
{"glossintensitymod",NULL, "dp"},
{"glossexponentmod",NULL, "dp"},
/*doom3 compat*/
{"diffusemap", Shader_DiffuseMap, "doom3"}, //macro for "{\nstage diffusemap\nmap <map>\n}"
@ -3178,6 +3181,12 @@ static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr)
tcmod->args[i] = Shader_ParseFloat (shader, ptr, 0);
tcmod->type = SHADER_TCMOD_TURB;
}
else if (!Q_stricmp (token, "page"))
{
for (i = 0; i < 3; i++)
tcmod->args[i] = Shader_ParseFloat (shader, ptr, 0);
tcmod->type = SHADER_TCMOD_PAGE;
}
else
{
return;
@ -4138,12 +4147,15 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey
{
shaderkey_t *key;
char *prefix;
qboolean toolchainprefix = false;
//handle known prefixes.
if (!Q_strncasecmp(token, "fte", 3)) {prefix = token; token += 3; }
else if (!Q_strncasecmp(token, "dp", 2)) {prefix = token; token += 2; }
else if (!Q_strncasecmp(token, "doom3", 5)) {prefix = token; token += 5; }
else if (!Q_strncasecmp(token, "rscript", 7)) {prefix = token; token += 7; }
else if (!Q_strncasecmp(token, "qer_", 4)) {prefix = token; token += 3; toolchainprefix = true; }
else if (!Q_strncasecmp(token, "q3map_", 6)) {prefix = token; token += 5; toolchainprefix = true; }
else prefix = NULL;
if (prefix && *token == '_')
token++;
@ -4162,10 +4174,13 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey
}
}
if (prefix)
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", shader->name, prefix);
else
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", shader->name, token);
if (!toolchainprefix) //we don't really give a damn about prefixes owned by various toolchains - they shouldn't affect us.
{
if (prefix)
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", shader->name, prefix);
else
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", shader->name, token);
}
// Next Line
while (ptr)
@ -6555,7 +6570,14 @@ char *Shader_Decompose(shader_t *s)
switch(p[j].texgen)
{
default:
case T_GEN_SINGLEMAP: sprintf(o, "singlemap "); break;
case T_GEN_SINGLEMAP:
if (p[j].anim_frames[0])
{
sprintf(o, "singlemap \"%s\" %ix%i", p[j].anim_frames[0]->ident, p[j].anim_frames[0]->width, p[j].anim_frames[0]->height);
}
else
sprintf(o, "singlemap ");
break;
case T_GEN_ANIMMAP: sprintf(o, "animmap "); break;
case T_GEN_LIGHTMAP: sprintf(o, "lightmap "); break;
case T_GEN_DELUXMAP: sprintf(o, "deluxmap "); break;

View File

@ -883,10 +883,10 @@ static void Win32NVVK_DoPresent(struct vkframe *theframe)
// qwglMakeCurrent(maindc, baseRC);
//get the gl driver to wait for the vk driver to finish rendering the frame
qglWaitVkSemaphoreNV(theframe->backbuf->presentsemaphore);
qglWaitVkSemaphoreNV((GLuint64)theframe->backbuf->presentsemaphore);
//tell the gl driver to copy it over now
qglDrawVkImageNV(theframe->backbuf->colour.image, theframe->backbuf->colour.sampler,
qglDrawVkImageNV((GLuint64)theframe->backbuf->colour.image, (GLuint64)theframe->backbuf->colour.sampler,
0, 0, vid.pixelwidth, vid.pixelheight, //xywh (window coords)
0, //z
0, 1, 1, 0); //stst (remember that gl textures are meant to be upside down)
@ -896,7 +896,7 @@ static void Win32NVVK_DoPresent(struct vkframe *theframe)
fence = vk.acquirefences[vk.aquirelast%ACQUIRELIMIT];
vk.aquirelast++;
//and actually signal it, so our code can wake up.
qglSignalVkFenceNV(fence);
qglSignalVkFenceNV((GLuint64)fence);
//and the gl driver has its final image and should do something with it now.
@ -2928,6 +2928,10 @@ static LONG WINAPI GLMainWndProc (
lRet = 0;
}
break;
case WM_DEVICECHANGE:
COM_AddWork(WG_MAIN, INS_DeviceChanged, NULL, NULL, uMsg, 0);
lRet = TRUE;
break;
#ifdef VKQUAKE
case WM_USER_VKPRESENT:

View File

@ -100,7 +100,7 @@ qboolean R_DrawSkyChain (batch_t *batch)
else
skyshader = batch->shader;
if (skyshader->prog)
if (skyshader->prog || !skyboxface)
return false;
if (skyshader->skydome)

View File

@ -243,7 +243,7 @@ extern gl_config_t gl_config;
extern float gldepthmin, gldepthmax;
void GL_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips);
qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips);
void GL_DestroyTexture(texid_t tex);
/*

View File

@ -83,7 +83,8 @@ typedef struct
SHADER_TCMOD_STRETCH, //constant factor
SHADER_TCMOD_ROTATE,
SHADER_TCMOD_TRANSFORM,
SHADER_TCMOD_TURB
SHADER_TCMOD_TURB,
SHADER_TCMOD_PAGE //use a texture atlas. horizontal frames, vertical frames, time divisor
} type;
float args[6];
} tcmod_t;

View File

@ -72,7 +72,7 @@ int main(void)
j = 0;
while (line[j] == ' ' || line[j] == '\t')
j++;
if ((line[j] == '/' && line[j] == '/') || line[j] == '\r' || line[j] == '\n')
if ((line[j] == '/' && line[j+1] == '/') || line[j] == '\r' || line[j] == '\n')
{
while (line[j])
fputc(line[j++], c);

View File

@ -18,6 +18,22 @@ r_part pe_default
scalefactor 0.8
}
r_part placeholder
{ //FIXME: fix the things that assoc this!
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0 255 //something that makes it obviously a placeholder.
}
r_part te_splashsparks
{
texture "classicparticle"
@ -421,6 +437,22 @@ r_part teq2_flechette
lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0
}
r_part teq2_bluehyperblaster
{ //misnamed - just the regular orangey particles without sound/puff
texture "classicparticle"
tcoords 0 0 16 16 32
count 60
scale 1
alpha 1
die 0.3 0.8
randomvel 40
orgadd 0 15
veladd 30
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0xe0 7
}
r_part TR_BLASTERTRAIL
{
texture "classicparticle"
@ -471,9 +503,25 @@ r_part teq2_bubbletrail
spawnvel 5
die 1 1.2
colorindex 4 7
velbias 0 0 6
}
r_part teq2_bubbletrail2
{
texture "classicparticle"
tcoords 0 0 16 16 32
scale 0.5
alpha 1
scalefactor 0.8
step 8
spawnorg 2
spawnvel 10
die 1 1.1
colorindex 4 7
velbias 0 0 20
sound "weapons/lashit.wav" 1 1 0 0
}
r_part TEQ2_RAILTRAIL
r_part teq2_railtrail
{
//blue spiral
texture "classicparticle"
@ -490,7 +538,7 @@ r_part TEQ2_RAILTRAIL
sound "weapons/railgf1a.wav" 1 1 0 0
}
r_part +TEQ2_RAILTRAIL
r_part +teq2_railtrail
{
//grey filler
texture "classicparticle"
@ -505,6 +553,25 @@ r_part +TEQ2_RAILTRAIL
colorindex 0 15
}
r_part teq2_railtrail2
{ //This is not implemented in vanilla, so we've no idea what it should really look like.
//we just use the blue spiral with no core.
//blue spiral
texture "classicparticle"
tcoords 0 0 16 16 32
scale 0.5
alpha 1
scalefactor 0.8
step 1
spawnmode spiral 64
spawnorg 3
spawnvel 6
die 1 1.2
colorindex 116 7
sound "weapons/railgf1a.wav" 1 1 0 0
}
//regular explosion particles
r_part std_explosion_particles
{
@ -600,6 +667,81 @@ r_part teq2_grenade_explosion_water
model "models/objects/r_explode/tris.md2" framestart=30 frames=19 skin=-1 fullbright noshadow
}
r_part teq2_plain_explosion
{ //basically like regular explosions, but with no particle effect.
lighttime 0.5
lightradius 350
lightradiusfade 300
lightrgb 1.0 0.5 0.4
lightrgbfade 0.36 0.19 0.19
sound "weapons/rocklx1a.wav" 1 1 0 0
model "models/objects/r_explode/tris.md2" framestart=0 frames=15 skin=-1 fullbright noshadow
model "models/objects/r_explode/tris.md2" framestart=15 frames=15 skin=-1 fullbright noshadow
}
r_part teq2_plasma_explosion
{ //not actually any different
assoc teq2_explosion1
}
r_part teq2_tracker_explosion
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 128
scale 1
alpha 1
die 1.5 2
randomvel 128
orgadd 0 31
spawnorg 16
gravity 40
scalefactor 0.8
colorindex 0 1
lighttime 0.1 //this is kinda too short.
lightradius 150
lightradiusfade 300
lightrgb -1.0 -1.0 -1.0
sound "weapons/disrupthit.wav" 1 1 0 0
}
r_part teq2_teleport_effect
{ //FIXME
assoc placeholder
}
r_part teq2_dball_goal
{ //FIXME
assoc placeholder
}
r_part teq2_widowsplash
{ //FIXME
assoc placeholder
}
r_part teq2_debugtrail
{ //FIXME
assoc placeholder
}
r_part teq2_chainfist_smoke
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 20
scale 1
alpha 1
die 0.5 0.8
spawnorg 2
randomvel 6.66 20
gravity 40
scalefactor 0.8
colorindex 0 7
}
r_part teq2_flashlight
{ //JUST a light.
lightradius 400
lighttime 0.15
lightrgb 1.0 1.0 1.0
lightshadows 1
}
r_part trq2_rocket
{
texture "particles/quake"
@ -651,36 +793,66 @@ r_part TR_PLASMA
assoc TR_BLASTERTRAIL
}
//FIXME: add particles
r_part tr_ionripper
{
texture "classicparticle"
tcoords 0 0 16 16 32
step 3
scale 1
alpha 0.5
die 0.15 0.25
colorindex 0xe4 3
spawnmode tracer
spawnorg 0
spawnvel 10
lighttime 0
lightradius 100
lightrgb 1.0 0.5 0.5
}
//FIXME: add particles
r_part tr_tracker
{
{ //FIXME: doesn't match vanilla. works well enough though I guess.
texture "classicparticle"
tcoords 0 0 16 16 32
step 3
scale 1
alpha 1
die 0.5
spawnmode spiral 8.34
spawnorg 1
spawnvel 32
veladd 32
scalefactor 0
colorindex 0
lighttime 0
lightradius 200
lightrgb -1.0 -1.0 -1.0
}
//FIXME: add particles
r_part tr_tagtrail
{
texture "classicparticle"
tcoords 0 0 16 16 32
step 5
scale 1
alpha 1
die 1.0 0.8
spawnorg 16
spawnvel 5
scalefactor 0
colorindex 220
lighttime 0
lightradius 225
lightrgb 1.0 1.0 0.0
}
//FIXME: add particles
r_part tr_trap
{
{ //FIXME: add particles
lighttime 0
lightradius 100 200
lightrgb 1.0 0.8 0.25
assoc placeholder
}
//flags do NOT use coronas, because it obscures the holding player's skin colour
@ -842,6 +1014,14 @@ r_part TEQ2_BOSSTPORT
sound "misc/bigtele.wav" 1 0 0 0 1
}
r_part teq2_heatbeam_sparks
{ //FIXME
assoc placeholder
}
r_part teq2_heatbeam_steam
{ //FIXME
assoc placeholder
}
/*
r_part teq2_heatbeam_steam
{

View File

@ -2348,6 +2348,9 @@ QCC_ddef_t *GetField(const char *name)
if (!*name)
return NULL;
if (*name == '.')
name++; //some idiot _intentionally_ decided to fuck shit up. go them!
for (i = 0; i < numfielddefs; i++)
{
d = &fields[i];

View File

@ -140,13 +140,15 @@ reeval:
break;
case OP_DIV_F:
/* errorif (!OPB->_float)
/* errorif (OPB->_float == 0)
{
pr_xstatement = st-pr_statements;
printf ("Division by 0 in %s\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
PR_StackTrace (&progfuncs->funcs);
PR_StackTrace (&progfuncs->funcs, 1);
OPC->_float = 0.0;
}
*/ OPC->_float = OPA->_float / OPB->_float;
else
*/ OPC->_float = OPA->_float / OPB->_float;
break;
case OP_DIV_VF:
tmpf = OPB->_float;
@ -154,7 +156,7 @@ reeval:
{
pr_xstatement = st-pr_statements;
printf ("Division by 0 in %s\n", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
PR_StackTrace (&progfuncs->funcs);
PR_StackTrace (&progfuncs->funcs, 1);
}
*/
OPC->_vector[0] = OPA->_vector[0] / tmpf;
@ -437,11 +439,13 @@ reeval:
//boot it over to the debugger
{
ddef16_t *d16;
fdef_t *f;
d16 = ED_GlobalAtOfs16(progfuncs, st->a);
f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->funcs.fieldadjust);
if (PR_ExecRunWarning(&progfuncs->funcs, st-pr_statements, "assignment to read-only entity %i in %s (%s.%s)\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), d16?PR_StringToNative(&progfuncs->funcs, d16->s_name):NULL, f?f->name:NULL))
#if INTSIZE == 16
ddef16_t *d = ED_GlobalAtOfs16(progfuncs, st->a);
#else
ddef32_t *d = ED_GlobalAtOfs32(progfuncs, st->a);
#endif
fdef_t *f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->funcs.fieldadjust);
if (PR_ExecRunWarning(&progfuncs->funcs, st-pr_statements, "assignment to read-only entity %i in %s (%s.%s)\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), d?PR_StringToNative(&progfuncs->funcs, d->s_name):NULL, f?f->name:NULL))
return pr_xstatement;
OPC->_int = ~0;
break;

View File

@ -128,7 +128,7 @@ void *PRAddressableExtend(progfuncs_t *progfuncs, void *src, size_t srcsize, int
}
if (prinst.addressableused + ammount > prinst.addressablesize)
Sys_Error("Not enough addressable memory for progs VM");
Sys_Error("Not enough addressable memory for progs VM (using %gmb)", prinst.addressablesize/(1024.0*1024));
}
prinst.addressableused += ammount;

View File

@ -408,6 +408,10 @@ enum qcop_e {
OP_BITXOR_F,
OP_RSHIFT_F,
OP_LSHIFT_F,
OP_RSHIFT_IF,
OP_LSHIFT_IF,
OP_RSHIFT_FI,
OP_LSHIFT_FI,
OP_AND_ANY,
OP_OR_ANY,
@ -422,6 +426,11 @@ enum qcop_e {
OP_BITNOT_V,
OP_BITXOR_V,
OP_POW_F,
OP_EQ_FLD,
OP_NE_FLD,
//special/fake opcodes used by the decompiler.
OPD_GOTO_FORSTART,
OPD_GOTO_WHILE1,

View File

@ -740,8 +740,11 @@ char *PDECL PR_UglyValueString (pubprogfuncs_t *ppf, etype_t type, eval_t *val)
}
break;
case ev_field:
fielddef = ED_FieldAtOfs (progfuncs, val->_int );
sprintf (line, "%s", fielddef->name);
fielddef = ED_FieldAtOfs (progfuncs, val->_int + progfuncs->funcs.fieldadjust);
if (fielddef)
sprintf (line, "%s", fielddef->name);
else
sprintf (line, "bad field %i", type);
break;
case ev_void:
sprintf (line, "void");
@ -806,7 +809,7 @@ char *PR_UglyOldValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
QC_snprintfz (line, sizeof(line), "%s", f->s_name+progfuncs->funcs.stringtable);
break;
case ev_field:
fielddef = ED_FieldAtOfs (progfuncs, val->_int );
fielddef = ED_FieldAtOfs (progfuncs, val->_int + progfuncs->funcs.fieldadjust);
QC_snprintfz (line, sizeof(line), "%s", fielddef->name);
break;
case ev_void:
@ -1403,17 +1406,18 @@ const char *ED_ParseEdict (progfuncs_t *progfuncs, const char *data, edictrun_t
if (keyname[0] == '_')
continue;
if (!strcmp(keyname, "angle")) //Quake anglehack - we've got to leave it in cos it doesn't work for quake otherwise, and this is a QuakeC lib!
{
if ((key = ED_FindField (progfuncs, "angles")))
{
QC_snprintfz (qcc_token, sizeof(qcc_token), "0 %f 0", atof(qcc_token)); //change it from yaw to 3d angle
goto cont;
}
}
key = ED_FindField (progfuncs, keyname);
if (!key)
{
if (!strcmp(keyname, "angle")) //Quake anglehack - we've got to leave it in cos it doesn't work for quake otherwise, and this is a QuakeC lib!
{
if ((key = ED_FindField (progfuncs, "angles")))
{
QC_snprintfz (qcc_token, sizeof(qcc_token), "0 %f 0", atof(qcc_token)); //change it from yaw to 3d angle
goto cont;
}
}
if (!strcmp(keyname, "light")) //Quake lighthack - allows a field name and a classname to go by the same thing in the level editor
if ((key = ED_FindField (progfuncs, "light_lev")))
goto cont;
@ -1487,7 +1491,7 @@ char *ED_WriteGlobals(progfuncs_t *progfuncs, char *buf, size_t *bufofs, size_t
len = strlen(name);
if (!*name)
continue;
if (name[len-2] == '_' && (name[len-1] == 'x' || name[len-1] == 'y' || name[len-1] == 'z'))
if (len >= 2 && name[len-2] == '_' && (name[len-1] == 'x' || name[len-1] == 'y' || name[len-1] == 'z'))
continue; // skip _x, _y, _z vars (vector components, which are saved as one vector not 3 floats)
type = def16->type;
@ -2531,6 +2535,8 @@ int PR_ReallyLoadProgs (progfuncs_t *progfuncs, const char *filename, progstate_
int stringadjust;
int *basictypetable;
current_progstate = progstate;
strcpy(current_progstate->filename, filename);
@ -2959,7 +2965,7 @@ retry:
type = fld16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
if (progfuncs->funcs.fieldadjust && !prinst.pr_typecurrent) //we need to make sure all fields appear in their original place.
QC_RegisterFieldVar(&progfuncs->funcs, type, fld16[i].s_name+pr_strings, 4*(fld16[i].ofs+progfuncs->funcs.fieldadjust), -1);
QC_RegisterFieldVar(&progfuncs->funcs, type, fld16[i].s_name+pr_strings, 4*(fld16[i].ofs+progfuncs->funcs.fieldadjust), fld16[i].ofs);
else if (type == ev_vector) //emit vector vars early, so their fields cannot be alocated before the vector itself. (useful against scramblers)
{
QC_RegisterFieldVar(&progfuncs->funcs, type, fld16[i].s_name+pr_strings, -1, fld16[i].ofs);
@ -3147,6 +3153,47 @@ retry:
if (!prinst.pr_typecurrent) //progs 0 always acts as string stripped.
isfriked = -1; //partly to avoid some bad/optimised progs.
basictypetable = NULL;
if (prinst.reorganisefields == 2)
{
switch(current_progstate->structtype)
{ //gmqcc fucks up the globals. it writes FLOAT defs instead of field defs. stupid stupid stupid.
case PST_DEFAULT:
{
dstatement16_t *st = current_progstate->statements;
basictypetable = externs->memalloc(sizeof(*basictypetable) * pr_progs->numglobals);
memset(basictypetable, 0, sizeof(*basictypetable) * pr_progs->numglobals);
for (i = 0; i < pr_progs->numstatements; i++)
{
switch(st[i].op)
{
case OP_ADDRESS:
case OP_LOAD_F:
case OP_LOAD_V:
case OP_LOAD_S:
case OP_LOAD_ENT:
case OP_LOAD_FLD:
case OP_LOAD_FNC:
case OP_LOAD_I:
case OP_LOAD_P:
if (st[i].b < pr_progs->numglobals)
basictypetable[st[i].b] = ev_field;
break;
}
}
for (i = 0; i < pr_progs->numglobals; i++)
{
if (basictypetable[i] == ev_field)
QC_AddFieldGlobal(&progfuncs->funcs, (int *)glob + i);
}
externs->memfree(basictypetable);
}
break;
}
}
// len = 0;
switch(current_progstate->structtype)
{
@ -3170,7 +3217,7 @@ retry:
switch(type)
{
case ev_field:
if (reorg)
if (reorg && !basictypetable)
QC_AddSharedFieldVar(&progfuncs->funcs, i, pr_strings - stringadjust);
break;
case ev_string:

View File

@ -362,7 +362,7 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
const mfunction_t *f;
int i;
int progs;
int arg;
int ofs;
int *globalbase;
int tracing = progfuncs->funcs.debug_trace;
progs = -1;
@ -414,19 +414,39 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals)
//locals:2 = ALL locals.
if ((i == pr_depth && showlocals == 1) || showlocals >= 2)
{
for (arg = 0; arg < f->locals; arg++)
for (ofs = 0; ofs < f->locals; ofs++)
{
ddef16_t *local;
local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
local = ED_GlobalAtOfs16(progfuncs, f->parm_start+ofs);
if (!local)
{
//printf(" ofs %i: %f : %i\n", f->parm_start+arg, *(float *)(globalbase - f->locals+arg), *(int *)(globalbase - f->locals+arg) );
int arg, aofs;
for (arg = 0, aofs = 0; arg < f->numparms; arg++)
{
if (ofs >= aofs && ofs < aofs + f->parm_size[arg])
break;
aofs += f->parm_size[arg];
}
if (arg < f->numparms)
{
if (f->parm_size[arg] == 3)
{ //looks like a vector. print it as such
printf(" arg%i(%i): [%g, %g, %g]\n", arg, f->parm_start+ofs, *(float *)(globalbase+ofs), *(float *)(globalbase+ofs+1), *(float *)(globalbase+ofs+2));
ofs += 2;
}
else
printf(" arg%i(%i): %g===%i\n", arg, f->parm_start+ofs, *(float *)(globalbase+ofs), *(int *)(globalbase+ofs) );
}
else
{
printf(" unk(%i): %g===%i\n", f->parm_start+ofs, *(float *)(globalbase+ofs), *(int *)(globalbase+ofs) );
}
}
else
{
printf(" %s: %s\n", local->s_name+progfuncs->funcs.stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase+arg), false));
printf(" %s: %s\n", local->s_name+progfuncs->funcs.stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase+ofs), false));
if (local->type == ev_vector)
arg+=2;
ofs+=2;
}
}
}
@ -778,7 +798,7 @@ pbool PDECL PR_SetWatchPoint(pubprogfuncs_t *ppf, char *key)
prinst.watch_name = strdup(key);
prinst.watch_ptr = val;
prinst.watch_old = *prinst.watch_ptr;
prinst.watch_type = type;
prinst.watch_type = type &~ DEF_SAVEGLOBAL;
return true;
}
@ -1523,6 +1543,20 @@ static casecmprange_t casecmprange[] =
return -1; \
}
#if defined(FTE_TARGET_WEB) || defined(SIMPLE_QCVM)
static int PR_NoDebugVM(progfuncs_t *fte_restrict progfuncs)
{
char stack[4*1024];
int ofs;
strcpy(stack, "This platform does not support QC debugging\nStack Trace:");
ofs = strlen(stack);
PR_SaveCallStack (progfuncs, stack, &ofs, sizeof(stack));
PR_RunError (&progfuncs->funcs, stack);
free(stack);
return -1;
}
#endif
static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *fte_restrict runaway)
{
unsigned int switchcomparison = 0;
@ -1552,14 +1586,7 @@ static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
reeval16:
//this can generate huge functions, so disable it on systems that can't realiably cope with such things (IE initiates an unwanted denial-of-service attack when pointed our javascript, and firefox prints a warning too)
pr_xstatement = st-pr_statements16;
char *stack = malloc(4*1024); //this'll leak, but whatever, we're dead anyway.
int ofs;
strcpy(stack, "This platform does not support QC debugging\nStack Trace:");
ofs = strlen(stack);
PR_SaveCallStack (progfuncs, stack, &ofs, 4*1024);
PR_RunError (&progfuncs->funcs, stack);
free(stack);
return -1;
return PR_NoDebugVM(progfuncs);
#else
#define DEBUGABLE
#ifdef SEPARATEINCLUDES

View File

@ -240,15 +240,19 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
if (!name) //engine can use this to offset all progs fields
{ //which fixes constant field offsets (some ktpro arrays)
progfuncs->funcs.fieldadjust = prinst.fields_size/4;
if (engineofs == 2)
prinst.reorganisefields = 2;
else if (engineofs)
{
progfuncs->funcs.fieldadjust = prinst.fields_size/4;
#ifdef MAPPING_DEBUG
printf("FIELD ADJUST: %i %i %i\n", progfuncs->funcs.fieldadjust, prinst.fields_size, (int)prinst.fields_size/4);
printf("FIELD ADJUST: %i %i %i\n", progfuncs->funcs.fieldadjust, prinst.fields_size, (int)prinst.fields_size/4);
#endif
}
return 0;
}
prinst.reorganisefields = true;
else if (!prinst.reorganisefields)
prinst.reorganisefields = true;
//look for an existing match
for (i = 0; i < prinst.numfields; i++)
@ -395,7 +399,7 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
}
//called if a global is defined as a field
//called for each global defined as a field
void PDECL QC_AddSharedFieldVar(pubprogfuncs_t *ppf, int num, char *stringtable)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
@ -422,65 +426,78 @@ void PDECL QC_AddSharedFieldVar(pubprogfuncs_t *ppf, int num, char *stringtable)
{
case PST_KKQWSV:
case PST_DEFAULT:
for (i=1 ; i<pr_progs->numfielddefs; i++)
{
if (!strcmp(pr_fielddefs16[i].s_name+stringtable, pr_globaldefs16[num].s_name+stringtable))
{
#ifdef MAPPING_DEBUG
int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
#endif
*(int *)&pr_globals[pr_globaldefs16[num].ofs] = QC_RegisterFieldVar(&progfuncs->funcs, pr_fielddefs16[i].type, pr_globaldefs16[num].s_name+stringtable, -1, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
#ifdef MAPPING_DEBUG
printf("Field=%s global %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(volatile int *)&pr_globals[pr_globaldefs16[num].ofs]);
#endif
return;
}
}
ddef16_t *gd = pr_globaldefs16;
ddef16_t *fld = pr_fielddefs16;
char *gname = gd[num].s_name+stringtable;
int *eval = (int*)&pr_globals[gd[num].ofs];
if (*gname == '.')
gname++;
for (i = 0; i < prinst.numfields; i++)
{
o = prinst.field[i].progsofs;
if (o == *(unsigned int *)&pr_globals[pr_globaldefs16[num].ofs])
for (i=1 ; i<pr_progs->numfielddefs; i++)
{
if (!strcmp(fld[i].s_name+stringtable, gname))
{
#ifdef MAPPING_DEBUG
int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
int old = *eval;
#endif
*(int *)&pr_globals[pr_globaldefs16[num].ofs] = prinst.field[i].ofs-progfuncs->funcs.fieldadjust;
*eval = QC_RegisterFieldVar(&progfuncs->funcs, fld[i].type, gname, -1, *eval);
#ifdef MAPPING_DEBUG
printf("Field global=%s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(volatile int *)&pr_globals[pr_globaldefs16[num].ofs]);
printf("Field=%s global %i -> %i\n", gd[num].s_name+stringtable, old, *eval);
#endif
return;
return;
}
}
}
//oh well, must be a parameter.
// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
// Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
for (i = 0; i < prinst.numfields; i++)
{
o = prinst.field[i].progsofs;
if (o == *eval)
{
#ifdef MAPPING_DEBUG
int old = *eval;
#endif
*eval = prinst.field[i].ofs-progfuncs->funcs.fieldadjust;
#ifdef MAPPING_DEBUG
printf("Field global=%s %i -> %i\n", gname, old, *eval);
#endif
return;
}
}
//oh well, must be a parameter.
// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
// Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
}
return;
case PST_FTE32:
case PST_QTEST:
for (i=1 ; i<pr_progs->numfielddefs; i++)
{
if (!strcmp(pr_fielddefs32[i].s_name+stringtable, pr_globaldefs32[num].s_name+stringtable))
ddef32_t *gd = pr_globaldefs32;
ddef32_t *fld = pr_fielddefs32;
for (i=1 ; i<pr_progs->numfielddefs; i++)
{
*(int *)&pr_globals[pr_globaldefs32[num].ofs] = QC_RegisterFieldVar(&progfuncs->funcs, pr_fielddefs32[i].type, pr_globaldefs32[num].s_name+stringtable, -1, *(int *)&pr_globals[pr_globaldefs32[num].ofs]);
return;
if (!strcmp(fld[i].s_name+stringtable, gd[num].s_name+stringtable))
{
*(int *)&pr_globals[gd[num].ofs] = QC_RegisterFieldVar(&progfuncs->funcs, fld[i].type, gd[num].s_name+stringtable, -1, *(int *)&pr_globals[gd[num].ofs]);
return;
}
}
}
for (i = 0; i < prinst.numfields; i++)
{
o = prinst.field[i].progsofs;
if (o == *(unsigned int *)&pr_globals[pr_globaldefs32[num].ofs])
for (i = 0; i < prinst.numfields; i++)
{
*(int *)&pr_globals[pr_globaldefs32[num].ofs] = prinst.field[i].ofs-progfuncs->funcs.fieldadjust;
return;
o = prinst.field[i].progsofs;
if (o == *(unsigned int *)&pr_globals[gd[num].ofs])
{
*(int *)&pr_globals[gd[num].ofs] = prinst.field[i].ofs-progfuncs->funcs.fieldadjust;
return;
}
}
}
//oh well, must be a parameter.
if (*(int *)&pr_globals[pr_globaldefs32[num].ofs])
Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs32[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs32[num].ofs]);
//oh well, must be a parameter.
if (*(int *)&pr_globals[gd[num].ofs])
Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", gd[num].s_name+stringtable, *(int *)&pr_globals[gd[num].ofs]);
}
return;
default:
Sys_Error("Bad bits");
@ -489,3 +506,25 @@ void PDECL QC_AddSharedFieldVar(pubprogfuncs_t *ppf, int num, char *stringtable)
Sys_Error("Should be unreachable");
}
void QC_AddFieldGlobal(pubprogfuncs_t *ppf, int *globdata)
{
unsigned int i;
int o;
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
for (i = 0; i < prinst.numfields; i++)
{
o = prinst.field[i].progsofs;
if (o == *globdata)
{
#ifdef MAPPING_DEBUG
int old = *globdata;
#endif
*globdata = prinst.field[i].ofs-progfuncs->funcs.fieldadjust;
#ifdef MAPPING_DEBUG
printf("Field global %i -> %i\n", old, *globdata);
#endif
return;
}
}
printf("Unable to map fieldglobal\n");
}

View File

@ -235,6 +235,7 @@ void QC_InitShares(progfuncs_t *progfuncs);
void QC_StartShares(progfuncs_t *progfuncs);
void PDECL QC_AddSharedVar(pubprogfuncs_t *progfuncs, int num, int type);
void PDECL QC_AddSharedFieldVar(pubprogfuncs_t *progfuncs, int num, char *stringtable);
void QC_AddFieldGlobal(pubprogfuncs_t *ppf, int *globdata);
int PDECL QC_RegisterFieldVar(pubprogfuncs_t *progfuncs, unsigned int type, char *name, signed long requestedpos, signed long originalofs);
pbool PDECL QC_Decompile(pubprogfuncs_t *progfuncs, char *fname);
int PDECL PR_ToggleBreakpoint(pubprogfuncs_t *progfuncs, char *filename, int linenum, int flag);

View File

@ -78,11 +78,10 @@ enum {
typedef struct fdef_s
{
unsigned int type; // if DEF_SAVEGLOBAL bit is set
// the variable needs to be saved in savegames
int ofs; //runtime offset. add fieldadj to get the real array index.
unsigned int type; //if DEF_SAVEGLOBAL bit is set then the variable needs to be saved in savegames
int ofs; //runtime offset. add fieldadj to get the real array index.
unsigned int progsofs; //used at loading time, so maching field offsets (unions/members) are positioned at the same runtime offset.
char * name;
char * name; //proper name for the field.
} fdef_t;
//the number of pointers to variables (as opposed to functions - those are fine) in these structures is excessive.
@ -156,7 +155,7 @@ struct pubprogfuncs_s
char *stringtable; //qc strings are all relative. add to a qc string. this is required for support of frikqcc progs that strip string immediates.
int stringtablesize;
int stringtablemaxsize;
int fieldadjust; //FrikQCC style arrays can cause problems due to field remapping. This causes us to leave gaps but offsets identical.
int fieldadjust; //FrikQCC style arrays can cause problems due to field remapping. This causes us to leave gaps but offsets identical. except for system fields, qc-addressable variables use their old offsets, this is the bias so that the offset pokes the correct memory.
struct qcthread_s *(PDECL *Fork) (pubprogfuncs_t *prinst); //returns a pointer to a thread which can be resumed via RunThread.
void (PDECL *RunThread) (pubprogfuncs_t *prinst, struct qcthread_s *thread);

View File

@ -475,6 +475,7 @@ struct QCC_function_s
struct QCC_type_s *type; //same as the def's type
struct QCC_def_s *def;
struct QCC_def_s *firstlocal;
QCC_sref_t returndef; //default return value
pbool privatelocals; //false means locals may overlap with other functions, true is needed for compat if stuff is uninitialised.
// unsigned int parm_ofs[MAX_PARMS]; // always contiguous, right?
};
@ -507,10 +508,12 @@ typedef struct
char *value;
char params[MAXCONSTANTPARAMS][MAXCONSTANTPARAMLENGTH];
int numparams;
int inside:10; //cuts off at some point
pbool used:1;
pbool inside:1;
pbool evil:1;
pbool varg:1;
char *fromfile;
int fromline;
int namelen;
} CompilerConstant_t;
@ -602,6 +605,9 @@ extern pbool flag_brokenarrays;
extern pbool flag_rootconstructor;
extern pbool flag_guiannotate;
extern pbool flag_qccx;
extern pbool flag_attributes;
extern pbool flag_assumevar;
extern pbool flag_dblstarexp;
extern pbool flag_embedsrc;
extern pbool opt_overlaptemps;
@ -770,6 +776,7 @@ enum {
WARN_POINTERASSIGNMENT, //&somefloat = 5; disabled for qccx compat sanity.
WARN_COMPATIBILITYHACK, //work around old defs.qc or invalid dpextensions.qc
WARN_REDECLARATIONMISMATCH,
WARN_PARAMWITHNONAME,
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
@ -847,7 +854,6 @@ enum {
ERR_THINKTIMETYPEMISMATCH,
ERR_STATETYPEMISMATCH,
ERR_BADBUILTINIMMEDIATE,
ERR_PARAMWITHNONAME,
ERR_BADPARAMORDER,
ERR_ILLEGALCONTINUES,
ERR_ILLEGALBREAKS,
@ -1041,11 +1047,12 @@ extern precache_t *precache_file;
extern int numfiles;
typedef struct qcc_includechunk_s {
struct qcc_includechunk_s *prev;
char *filename;
struct qcc_includechunk_s *prev;//chunk it was expanded/included from
const char *currentfilename; //filename it was expended from
int currentlinenumber; //line it was expanded from
char *currentdatapoint;
int currentlinenumber;
CompilerConstant_t *cnst;
CompilerConstant_t *cnst; //define we're expanding from
char *datastart; //the start of the expanded data
} qcc_includechunk_t;
extern qcc_includechunk_t *currentchunk;

View File

@ -511,7 +511,7 @@ skipwhite:
qcc_token[len++] = c;
data++;
c = *data;
} while ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '_');
} while ((c>= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || (c>= '0' && c <= '9') || c == '_');
qcc_token[len] = 0;
return data;

View File

@ -120,6 +120,9 @@ pbool flag_guiannotate;
pbool flag_brokenarrays; //return array; returns array[0] instead of &array;
pbool flag_rootconstructor; //if true, class constructors are ordered to call the super constructor first, rather than the child constructor
pbool flag_qccx;
pbool flag_attributes;
pbool flag_assumevar;
pbool flag_dblstarexp;
pbool flag_embedsrc;
pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation)
@ -252,7 +255,7 @@ unsigned int locals_marshalled; // largest local block size that needs to be a
jmp_buf pr_parse_abort; // longjump with this on parse error
void QCC_PR_ParseDefs (char *classname);
void QCC_PR_ParseDefs (char *classname, pbool fatal);
pbool qcc_usefulstatement;
@ -677,22 +680,31 @@ QCC_opcode_t pr_opcodes[] =
{7, "%", "MOD_I", 6, ASSOC_LEFT, &type_integer, &type_integer, &type_integer},
{7, "%", "MOD_V", 6, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "^", "BITXOR_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, ">>", "RSHIFT_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, "<<", "LSHIFT_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, "^", "BITXOR_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, ">>", "RSHIFT_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, "<<", "LSHIFT_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{7, ">>", "RSHIFT_IF", 3, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
{7, "<<", "LSHIFT_IF", 3, ASSOC_LEFT, &type_integer, &type_float, &type_integer},
{7, ">>", "RSHIFT_FI", 3, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
{7, "<<", "LSHIFT_FI", 3, ASSOC_LEFT, &type_float, &type_integer, &type_integer},
{7, "&&", "AND_ANY", 7, ASSOC_LEFT, &type_variant, &type_variant, &type_float},
{7, "||", "OR_ANY", 7, ASSOC_LEFT, &type_variant, &type_variant, &type_float},
{7, "&&", "AND_ANY", 7, ASSOC_LEFT, &type_variant, &type_variant, &type_float},
{7, "||", "OR_ANY", 7, ASSOC_LEFT, &type_variant, &type_variant, &type_float},
{7, "+", "ADD_EI", 4, ASSOC_LEFT, &type_entity, &type_integer, &type_entity},
{7, "+", "ADD_EF", 4, ASSOC_LEFT, &type_entity, &type_float, &type_entity},
{7, "-", "SUB_EI", 4, ASSOC_LEFT, &type_entity, &type_integer, &type_entity},
{7, "-", "SUB_EF", 4, ASSOC_LEFT, &type_entity, &type_float, &type_entity},
{7, "&", "BITAND_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "|", "BITOR_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "~", "BITNOT_V", -1, ASSOC_LEFT, &type_vector, &type_void, &type_vector},
{7, "^", "BITXOR_V", 3, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "&", "BITAND_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "|", "BITOR_V", 5, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "~", "BITNOT_V", -1, ASSOC_LEFT, &type_vector, &type_void, &type_vector},
{7, "^", "BITXOR_V", 3, ASSOC_LEFT, &type_vector, &type_vector, &type_vector},
{7, "^^", "POW_F", 3, ASSOC_LEFT, &type_float, &type_float, &type_float},
{6, "==", "EQ_FLD", 5, ASSOC_LEFT, &type_field, &type_field, &type_float},
{6, "==", "NE_FLD", 5, ASSOC_LEFT, &type_field, &type_field, &type_float},
{0, NULL}
};
@ -1068,14 +1080,20 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
&pr_opcodes[OP_RSHIFT_I],
&pr_opcodes[OP_RSHIFT_F],
&pr_opcodes[OP_RSHIFT_IF],
&pr_opcodes[OP_RSHIFT_FI],
&pr_opcodes[OP_LSHIFT_I],
&pr_opcodes[OP_LSHIFT_F],
&pr_opcodes[OP_LSHIFT_IF],
&pr_opcodes[OP_LSHIFT_FI],
&pr_opcodes[OP_MOD_F],
&pr_opcodes[OP_MOD_I],
&pr_opcodes[OP_MOD_V],
&pr_opcodes[OP_POW_F],
NULL
}, { //4
@ -1114,6 +1132,7 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
&pr_opcodes[OP_EQ_I],
&pr_opcodes[OP_EQ_IF],
&pr_opcodes[OP_EQ_FI],
&pr_opcodes[OP_EQ_FLD],
&pr_opcodes[OP_EQ_P],
&pr_opcodes[OP_NE_F],
@ -1124,6 +1143,7 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] =
&pr_opcodes[OP_NE_I],
&pr_opcodes[OP_NE_IF],
&pr_opcodes[OP_NE_FI],
&pr_opcodes[OP_NE_FLD],
&pr_opcodes[OP_NE_P],
&pr_opcodes[OP_LE_F],
@ -2361,10 +2381,26 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
return QCC_MakeFloatConst(QCC_PR_RoundFloatConst(eval_a) >> QCC_PR_RoundFloatConst(eval_b));
case OP_RSHIFT_IF:
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
return QCC_MakeIntConst(eval_a->_int >> QCC_PR_RoundFloatConst(eval_b));
case OP_RSHIFT_FI:
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
return QCC_MakeIntConst(QCC_PR_RoundFloatConst(eval_a) >> eval_b->_int);
case OP_LSHIFT_F:
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
return QCC_MakeFloatConst(QCC_PR_RoundFloatConst(eval_a) << QCC_PR_RoundFloatConst(eval_b));
case OP_LSHIFT_IF:
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
return QCC_MakeIntConst(eval_a->_int << QCC_PR_RoundFloatConst(eval_b));
case OP_LSHIFT_FI:
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
return QCC_MakeIntConst(QCC_PR_RoundFloatConst(eval_a) << eval_b->_int);
case OP_BITOR_F:
QCC_FreeTemp(var_a); QCC_FreeTemp(var_b);
optres_constantarithmatic++;
@ -3390,6 +3426,17 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
var_b.sym->referenced = true;
break;
case OP_POW_F:
{
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "pow", NULL, false, 0, 0);
if (!fnc.cast)
QCC_PR_ParseError(0, "pow function not defined: cannot emulate int^^int");
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
var_c.cast = type_float;
return var_c;
}
break;
case OP_CONV_ITOF:
case OP_STORE_IF:
{
@ -3895,6 +3942,49 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
QCC_FreeTemp(var_b);
break;
#endif
case OP_LSHIFT_IF:
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_RSHIFT_I], var_a, var_b, NULL, flags&STFL_PRESERVEA);
case OP_LSHIFT_FI:
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_RSHIFT_I], var_a, var_b, NULL, flags&STFL_PRESERVEB);
case OP_RSHIFT_IF:
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_RSHIFT_I], var_a, var_b, NULL, flags&STFL_PRESERVEA);
case OP_RSHIFT_FI:
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_RSHIFT_I], var_a, var_b, NULL, flags&STFL_PRESERVEB);
//convert both to ints
case OP_LSHIFT_F:
if (QCC_OPCodeValid(&pr_opcodes[OP_LSHIFT_I]))
{
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_LSHIFT_I], var_a, var_b, NULL, 0);
}
else
{
QCC_sref_t fnc = QCC_PR_GetSRef(NULL, "bitshift", NULL, false, 0, 0);
if (!fnc.cast)
QCC_PR_ParseError(0, "bitshift function not defined: cannot emulate OP_LSHIFT_F*");
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
var_c.cast = *op->type_c;
return var_c;
}
case OP_RSHIFT_F:
if (QCC_OPCodeValid(&pr_opcodes[OP_RSHIFT_I]))
{
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_RSHIFT_I], var_a, var_b, NULL, 0);
}
else
{
}
//statements where the rhs is an input int and can be swapped with a float
case OP_ADD_FI:
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
@ -3991,8 +4081,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
case OP_GT_I:
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
return QCC_PR_StatementFlags(&pr_opcodes[OP_GT_FI], var_a, var_b, NULL, flags&STFL_PRESERVEB);
case OP_EQ_FLD:
case OP_EQ_I:
return QCC_PR_StatementFlags(&pr_opcodes[OP_EQ_FNC], var_a, var_b, NULL, flags&(STFL_PRESERVEA|STFL_PRESERVEB));
case OP_NE_FLD:
case OP_NE_I:
return QCC_PR_StatementFlags(&pr_opcodes[OP_NE_FNC], var_a, var_b, NULL, flags&(STFL_PRESERVEA|STFL_PRESERVEB));
@ -9131,26 +9223,69 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
{
qcc_usefulstatement=true;
lhsd = QCC_PR_ParseFunctionCall (lhsr);
lhsd = QCC_PR_ParseArrayPointer(lhsd, true, true);
lhsr = QCC_DefToRef(retbuf, lhsd);
lhsr = QCC_DefToRef(&rhsbuf, lhsd);
lhsr = QCC_PR_ParseRefArrayPointer(retbuf, lhsr, true, true);
if (lhsr == &rhsbuf)
{
*retbuf = rhsbuf;
lhsr = retbuf;
}
}
if (priority == TERNARY_PRIORITY && QCC_PR_CheckToken ("?"))
{
//if we have no int types, force all ints to floats here, just to ensure that we don't end up with non-constant ints that we then can't cope with.
QCC_sref_t val, r;
QCC_sref_t r;
QCC_statement_t *fromj, *elsej, *truthstore;
QCC_sref_t val = QCC_RefToDef(lhsr, true);
const QCC_eval_t *eval = QCC_SRef_EvalConst(val);
if (pr_scope)
eval = NULL; //FIXME: we need the gotos to avoid sideeffects, which is annoying.
if (QCC_PR_CheckToken(":"))
{
if (eval)
{
if (eval->_int)
{
QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA));
return QCC_DefToRef(retbuf, val);
}
else
{
QCC_FreeTemp(val);
val = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
return QCC_DefToRef(retbuf, val);
}
}
eval = NULL;
//r=a?:b -> if (a) r=a else r=b;
val = QCC_RefToDef(lhsr, true);
fromj = QCC_Generate_OP_IFNOT(val, true);
r = QCC_GetTemp(val.cast);
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[(r.cast->size>=3)?OP_STORE_V:OP_STORE_F], val, r, &truthstore, STFL_PRESERVEB));
}
else
{
fromj = QCC_Generate_OP_IFNOT(QCC_RefToDef(lhsr, true), false);
if (eval)
{
if (eval->_int)
{
QCC_FreeTemp(val);
val = QCC_PR_Expression(TOP_PRIORITY, 0);
QCC_PR_Expect(":");
QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA));
return QCC_DefToRef(retbuf, val);
}
else
{
QCC_FreeTemp(val);
QCC_FreeTemp(QCC_PR_Expression(TOP_PRIORITY, 0));
QCC_PR_Expect(":");
val = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
return QCC_DefToRef(retbuf, val);
}
}
fromj = QCC_Generate_OP_IFNOT(val, false);
val = QCC_PR_Expression(TOP_PRIORITY, 0);
if (val.cast->type == ev_integer && !QCC_OPCodeValid(&pr_opcodes[OP_STORE_I]))
@ -9161,8 +9296,11 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
QCC_PR_Expect(":");
}
QCC_PR_Statement(&pr_opcodes[OP_GOTO], nullsref, nullsref, &elsej);
fromj->b.ofs = &statements[numstatements] - fromj;
if (fromj)
{
QCC_PR_Statement(&pr_opcodes[OP_GOTO], nullsref, nullsref, &elsej);
fromj->b.ofs = &statements[numstatements] - fromj;
}
val = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
if (val.cast->type == ev_integer && !QCC_OPCodeValid(&pr_opcodes[OP_STORE_I]))
val = QCC_SupplyConversion(val, ev_float, true);
@ -9180,8 +9318,21 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
if (typecmp(val.cast, r.cast) != 0)
{
//if they're mixed int/float, cast to floats.
QCC_PR_ParseError(0, "Ternary operator with mismatching types\n");
if (QCC_SRef_IsNull(val))
val = QCC_EvaluateCast(val, r.cast, true);
else if (QCC_SRef_IsNull(r))
r = QCC_EvaluateCast(r, val.cast, true);
else if (typecmp_lax(val.cast, r.cast) != 0)
{
char typebuf1[256];
char typebuf2[256];
QCC_PR_ParseWarning(0, "Type mismatch on ternary operator: %s vs %s", TypeName(r.cast, typebuf1, sizeof(typebuf1)), TypeName(val.cast, typebuf2, sizeof(typebuf2)));
}
else
{
//if they're mixed int/float, cast to floats.
QCC_PR_ParseError(0, "Ternary operator with mismatching types\n");
}
}
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[(r.cast->size>=3)?OP_STORE_V:OP_STORE_F], val, r, NULL, STFL_PRESERVEB));
@ -9737,20 +9888,18 @@ void QCC_PR_ParseStatement_For(void)
QCC_PR_Expect("(");
if (!QCC_PR_CheckToken(";"))
{
QCC_type_t *lt = NULL, *type;
do
{
QCC_type_t *type = QCC_PR_ParseType (false, true);
if (type)
{
d = QCC_PR_GetDef (type, QCC_PR_ParseName(), pr_scope, true, 0, 0);
QCC_PR_Expect("=");
QCC_PR_ParseInitializerDef(d, 0);
QCC_FreeDef(d);
QCC_FreeDef(d);
}
else
QCC_PR_DiscardExpression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
type = QCC_PR_ParseType (false, true);
if (!type)
type = lt;
pr_assumetermtype = lt = type;
pr_assumetermscope = pr_scope;
pr_assumetermflags = 0;
QCC_PR_DiscardExpression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
} while(QCC_PR_CheckToken(","));
pr_assumetermtype = NULL;
QCC_PR_Expect(";");
}
subscopestop = pr_subscopedlocals?NULL:pr.local_tail->nextlocal;
@ -9902,6 +10051,20 @@ void QCC_PR_ParseStatement (void)
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], nullsref, nullsref, NULL));
return;
}
if (QCC_PR_CheckToken ("="))
{
QCC_ref_t r;
if (!pr_scope->returndef.cast)
pr_scope->returndef = QCC_PR_GetSRef(pr_scope->type->aux_type, "return", pr_scope, true, 0, GDF_NONE);
e = QCC_PR_Expression(TOP_PRIORITY, 0);
QCC_PR_Expect (";");
QCC_StoreSRefToRef(QCC_PR_BuildRef(&r, REF_GLOBAL, pr_scope->returndef, nullsref, pr_scope->type->aux_type, false), e, false, false);
return;
}
e = QCC_PR_Expression (TOP_PRIORITY, 0);
QCC_PR_Expect (";");
if (QCC_SRef_IsNull(e))
@ -10102,7 +10265,7 @@ void QCC_PR_ParseStatement (void)
{
// if (locals_end != numpr_globals) //is this breaking because of locals?
// QCC_PR_ParseWarning("local vars after temp vars\n");
QCC_PR_ParseDefs (NULL);
QCC_PR_ParseDefs (NULL, true);
return;
}
@ -10113,26 +10276,32 @@ void QCC_PR_ParseStatement (void)
{
if (strncmp(pr_file_p, "::", 2))
{
QCC_PR_ParseDefs (NULL);
QCC_PR_ParseDefs (NULL, false);
return;
}
}
if ((keyword_var && !STRCMP ("var", pr_token)) ||
(keyword_noref && !STRCMP ("noref", pr_token)) ||
(keyword_string && !STRCMP ("string", pr_token)) ||
(keyword_float && !STRCMP ("float", pr_token)) ||
(keyword_entity && !STRCMP ("entity", pr_token)) ||
(keyword_vector && !STRCMP ("vector", pr_token)) ||
(keyword_integer && !STRCMP ("integer", pr_token)) ||
(keyword_int && !STRCMP ("int", pr_token)) ||
(keyword_static && !STRCMP ("static", pr_token)) ||
(keyword_class && !STRCMP ("class", pr_token)) ||
(keyword_class && !STRCMP ("static", pr_token)) ||
(keyword_const && !STRCMP ("const", pr_token)))
{
QCC_PR_ParseDefs (NULL);
QCC_PR_ParseDefs (NULL, true);
return;
}
}
if (pr_token_type == tt_punct && QCC_PR_PeekToken ("."))
{ //for local .entity without var/local
QCC_PR_ParseDefs (NULL, true);
return;
}
if (QCC_PR_CheckKeyword(keyword_state, "state"))
{
@ -10714,7 +10883,8 @@ void QCC_PR_ParseStatement (void)
pr_source_line = statementstart;
if (!expandedemptymacro)
{
QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Hanging ';'");
if (!currentchunk || !currentchunk->cnst)
QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Hanging ';'");
while (QCC_PR_CheckToken(";"))
;
}
@ -10898,7 +11068,7 @@ void QCC_PR_ParseAsm(void)
if (QCC_PR_CheckKeyword(keyword_local, "local"))
{
QCC_PR_ParseDefs (NULL);
QCC_PR_ParseDefs (NULL, true);
return;
}
@ -11942,7 +12112,10 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
{
unsigned int o;
if (!*pr_parm_names[u])
QCC_PR_ParseError(ERR_PARAMWITHNONAME, "Parameter is not named");
{
QC_snprintfz(pr_parm_names[u], sizeof(pr_parm_names[u]), "$arg_%u", u);
QCC_PR_ParseWarning(WARN_PARAMWITHNONAME, "Parameter %u of %s is not named", u+1, pr_scope->name);
}
parm = QCC_PR_GetSRef (type->params[u].type, pr_parm_names[u], pr_scope, 2, 0, false);
parm.sym->used = true; //make sure system parameters get seen by the engine, even if the names are stripped..
parm.sym->referenced = true;
@ -12102,6 +12275,12 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
QCC_FreeTemps();
}
}
if (f->returndef.cast)
{
PR_GenerateReturnOuts();
QCC_ForceUnFreeDef(f->returndef.sym);
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_RETURN], f->returndef, nullsref, NULL));
}
QCC_FreeTemps();
if (prior && !prior->referenced)
@ -12469,6 +12648,11 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
}
else
errmsg = QCC_MakeStringConst("bounds check failed\n");
if (!errfnc.cast)
{
errfnc = QCC_MakeIntConst(0);
errfnc.cast = type_function;
}
QCC_FreeTemp(QCC_PR_GenerateFunctionCall1(nullsref, errfnc, errmsg, type_string));
}
QCC_FreeTemp(index);
@ -12597,6 +12781,11 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
{
QCC_sref_t errfnc = QCC_PR_GetSRef(NULL, "error", NULL, false, 0, false);
QCC_sref_t errmsg = QCC_MakeStringConst("bounds check failed\n");
if (!errfnc.cast)
{
errfnc = QCC_MakeIntConst(0);
errfnc.cast = type_function;
}
QCC_FreeTemp(QCC_PR_GenerateFunctionCall1(nullsref, errfnc, errmsg, type_string));
}
@ -12914,6 +13103,11 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name);
if (allocate && scope && !(flags & GDF_STATIC))
{
if (pr_subscopedlocals)
{ //subscopes mean that the later one replaces the first, hopefully.
def = pHash_GetNext(&localstable, name, def);
continue;
}
if (allocate == 2)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Duplicate definition of %s.", name);
if (def->isstatic)
@ -13003,6 +13197,11 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "%s builtin was redefined as %s. ignoring alternative definition",name, TypeName(type, typebuf1, sizeof(typebuf1)));
QCC_PR_ParsePrintDef(WARN_COMPATIBILITYHACK, def);
}
else if (1)//def->initialized == 3)
{ //previous def was norefed
def = pHash_GetNext(&localstable, name, def);
continue; // in a different function
}
else
{
//unequal even when we're lax
@ -13490,13 +13689,14 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
if (basedef && (!basedef->scope || basedef->constant || basedef->isstatic))
{
tmp.sym->referenced = true;
if (!tmp.sym->constant)
{
QCC_PR_ParseWarning(ERR_BADIMMEDIATETYPE, "initializer is not constant");
if (basedef->scope && !basedef->isstatic)
goto finalnotconst;
QCC_PR_ParseWarning(ERR_BADIMMEDIATETYPE, "initializer for '%s' is not constant", basedef->name);
QCC_PR_ParsePrintSRef(ERR_BADIMMEDIATETYPE, tmp);
}
tmp.sym->referenced = true;
if (!tmp.sym->initialized)
{
//FIXME: we NEED to support relocs somehow
@ -13510,7 +13710,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
if (def.sym->symboldata[def.ofs+i]._int != tmp.sym->symboldata[tmp.ofs+i]._int)
{
if (!def.sym->arraysize && def.cast->type == ev_function && !strcmp(def.sym->name, "parseentitydata") && (functions[def.sym->symboldata[def.ofs+i]._int].builtin == 608 || functions[def.sym->symboldata[def.ofs+i]._int].builtin == 613))
{ //dpextensions is WRONG, and claims it to be 608.
{ //dpextensions is WRONG, and claims it to be 608. its also too common, so lets try working around that.
if (functions[def.sym->symboldata[def.ofs+i]._int].builtin == 608)
functions[def.sym->symboldata[def.ofs+i]._int].builtin = 613;
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "incompatible redeclaration. Please validate builtin numbers. parseentitydata is #613");
@ -13533,7 +13733,9 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
}
else
{
QCC_sref_t rhs = tmp;
QCC_sref_t rhs;
finalnotconst:
rhs = tmp;
if (def.sym->initialized)
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "%s initialised twice", basedef->name);
@ -13749,7 +13951,7 @@ PR_ParseDefs
Called at the outer layer and when a local statement is hit
================
*/
void QCC_PR_ParseDefs (char *classname)
void QCC_PR_ParseDefs (char *classname, pbool fatal)
{
char *name;
QCC_type_t *basetype, *type, *defclass;
@ -13778,7 +13980,7 @@ void QCC_PR_ParseDefs (char *classname)
pr_assumetermtype = NULL;
while (QCC_PR_CheckToken(";"))
;
fatal = false;
//FIXME: these should be moved into parsetype
if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
@ -14026,6 +14228,44 @@ void QCC_PR_ParseDefs (char *classname)
dowrap = true;
else if (QCC_PR_CheckKeyword(keyword_weak, "weak"))
doweak = true;
else if (flag_attributes && !pr_scope && QCC_PR_CheckToken("["))
{
QCC_PR_Expect("[");
while(pr_token_type != tt_eof)
{
if (QCC_PR_CheckToken(","))
continue;
else if (QCC_PR_CheckToken("]"))
break;
else if (QCC_PR_CheckName("alias"))
{
QCC_PR_Expect("(");
if (pr_token_type == tt_name)
/*aliasof =*/ QCC_PR_ParseName();
else if (pr_token_type == tt_immediate)
{
/*aliasof =*/ pr_immediate_string;
QCC_PR_Lex();
}
QCC_PR_Expect(")");
}
else if (QCC_PR_CheckName("accumulate"))
doweak = dowrap = true;
else
{
QCC_PR_ParseWarning(0, "Unknown attribute \"%s\"", pr_token);
while(pr_token_type != tt_eof)
{
if (QCC_PR_PeekToken("]"))
break;
if (QCC_PR_PeekToken(","))
break;
QCC_PR_Lex();
}
}
}
QCC_PR_Expect("]");
}
else
break;
}
@ -14397,7 +14637,10 @@ void QCC_PR_ParseDefs (char *classname)
parentclass = pr_classtype;
pr_classtype = defclass?defclass:pr_classtype;
def->constant = (isconstant || (!isvar && !pr_scope));
if (flag_assumevar)
def->constant = isconstant || (!isvar && !pr_scope && type->type == ev_function);
else
def->constant = (isconstant || (!isvar && !pr_scope));
QCC_PR_ParseInitializerDef(def, (dowrap?PIF_WRAP:0)|(def->weak?PIF_STRONGER:0));
if (doweak)
def->weak = true;
@ -14424,7 +14667,7 @@ void QCC_PR_ParseDefs (char *classname)
}
if (def->constant != c)
{
QCC_PR_ParseWarning(WARN_REDECLARATIONMISMATCH, "Redeclaration changes const.");
QCC_PR_ParseWarning(WARN_REDECLARATIONMISMATCH, "Redeclaration of %s changes const.", def->name);
}
}
@ -14555,7 +14798,7 @@ pbool QCC_PR_CompileFile (char *string, char *filename)
pr_scope = NULL; // outside all functions
QCC_PR_ParseDefs (NULL);
QCC_PR_ParseDefs (NULL, true);
#ifdef _DEBUG
if (!pr_error_count)

View File

@ -20,6 +20,11 @@ void QCC_FreeDef(QCC_def_t *def);
#define MAXINCLUDEDIRS 8
char qccincludedir[MAXINCLUDEDIRS][256]; //the -src path, for #includes
struct qccincludeonced_s
{
struct qccincludeonced_s *next;
char name[1];
} *qccincludeonced; //the -src path, for #includes
char *compilingfile;
@ -66,13 +71,13 @@ static void Q_strlcpy(char *dest, const char *src, int sizeofdest)
char *pr_punctuation[] =
// longer symbols must be before a shorter partial match
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "&=", "++", "--", "->", "^=", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^", "~", ":", NULL};
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "&=", "++", "--", "->", "^=", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "><", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^^", "^", "~", ":", NULL};
char *pr_punctuationremap[] = //a nice bit of evilness.
//(+) -> |=
//-> -> .
//(-) -> &~=
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "&=", "++", "--", ".", "^=", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^", "~", ":", NULL};
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "&=", "++", "--", ".", "^=", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "><", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^^", "^", "~", ":", NULL};
// simple types. function types are dynamically allocated
QCC_type_t *type_void; //void
@ -109,6 +114,7 @@ void QCC_PR_CloseProcessor(void)
for (i = 0; i < MAXINCLUDEDIRS; i++)
*qccincludedir[i] = 0;
currentchunk = NULL;
qccincludeonced = NULL;
}
void QCC_PR_AddIncludePath(const char *newinc)
{
@ -116,10 +122,11 @@ void QCC_PR_AddIncludePath(const char *newinc)
if (!*newinc)
{
QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Invalid include path.");
return;
newinc = ".";
// QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Invalid include path.");
// return;
}
for (i = 0; i < MAXINCLUDEDIRS; i++)
{
if (!*qccincludedir[i])
@ -145,10 +152,23 @@ static void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename,
currentchunk = chunk;
chunk->currentdatapoint = pr_file_p;
chunk->currentfilename = s_filen;
chunk->currentlinenumber = pr_source_line;
chunk->cnst = cnst;
if( cnst )
{
#if 0
s_filen = cnst->fromfile;
pr_source_line = cnst->fromline;
#else
int b = strlen(s_filen)+1+8+strlen(cnst->name);
char *p;
if (b > 128)
b = 128;
s_filen = p = qccHunkAlloc(b);
QC_snprintfz(p, b, "%s:%i:%s", chunk->currentfilename, chunk->currentlinenumber, cnst->name);
pr_source_line = 1;
#endif
cnst->inside++;
}
@ -159,6 +179,7 @@ static void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename,
}
else
pr_file_p = data;
chunk->datastart = pr_file_p;
}
void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename)
{
@ -175,6 +196,7 @@ pbool QCC_PR_UnInclude(void)
pr_file_p = currentchunk->currentdatapoint;
pr_source_line = currentchunk->currentlinenumber;
s_filen = currentchunk->currentfilename;
currentchunk = currentchunk->prev;
@ -187,11 +209,19 @@ static void QCC_Canonicalize(char *fullname, size_t fullnamesize, char *newfile,
char *end = fullname;
doubledots = 0;
/*count how far up we need to go*/
while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
while(1)
{
newfile+=3;
doubledots++;
if (!strncmp(newfile, "./", 2) || !strncmp(newfile, ".\\", 2))
newfile+=2;
else if(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
{
newfile+=3;
doubledots++;
}
else
break;
}
if (base)
@ -228,6 +258,7 @@ extern char qccmsourcedir[];
//also meant to include it.
void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose)
{
struct qccincludeonced_s *onced;
int includepath = 0;
char fullname[1024];
@ -257,6 +288,12 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose)
break;
}
for(onced = qccincludeonced; onced; onced = onced->next)
{
if (!strcmp(onced->name, fullname))
return;
}
if (verbose)
{
if (verbose == 2)
@ -1069,6 +1106,19 @@ pbool QCC_PR_Precompiler(void)
{
ForcedCRC = atoi(msg);
}
else if (!QC_strcasecmp(qcc_token, "once"))
{
struct qccincludeonced_s *onced = qccHunkAlloc(sizeof(*onced) + strlen(compilingfile));
strcpy(onced->name, compilingfile);
onced->next = qccincludeonced;
qccincludeonced = onced;
}
else if (!QC_strcasecmp(qcc_token, "file"))
{
}
else if (!QC_strcasecmp(qcc_token, "line"))
{
}
else if (!QC_strcasecmp(qcc_token, "includedir"))
{
char newinc[1024];
@ -1384,37 +1434,37 @@ void QCC_PR_LexString (void)
text++;
if (fromfile) pr_file_p++;
}
do
{
c = *text++;
if (fromfile) pr_file_p++;
if (!c)
QCC_PR_ParseError ("EOF inside quote");
if (c=='\n')
QCC_PR_ParseError ("newline inside quote");
if (c=='\\')
{ // escape char
do
{
c = *text++;
if (fromfile) pr_file_p++;
if (!c)
QCC_PR_ParseError ("EOF inside quote");
if (c == 'n')
c = '\n';
else if (c == '"')
c = '"';
else if (c == '\\')
c = '\\';
else
QCC_PR_ParseError ("Unknown escape char");
}
else if (c=='\"')
{
if (fromfile) pr_file_p++;
break;
}
tmpbuf[len] = c;
len++;
} while (1);
if (c=='\n')
QCC_PR_ParseError ("newline inside quote");
if (c=='\\')
{ // escape char
c = *text++;
if (fromfile) pr_file_p++;
if (!c)
QCC_PR_ParseError ("EOF inside quote");
if (c == 'n')
c = '\n';
else if (c == '"')
c = '"';
else if (c == '\\')
c = '\\';
else
QCC_PR_ParseError ("Unknown escape char");
}
else if (c=='\"')
{
if (fromfile) pr_file_p++;
break;
}
tmpbuf[len] = c;
len++;
} while (1);
tmpbuf[len] = 0;
// if (fromfile) pr_file_p++;
@ -2192,6 +2242,13 @@ void QCC_PR_LexPunctuation (void)
pr_token_type = tt_punct;
if (pr_file_p[0] == '*' && pr_file_p[1] == '*' && flag_dblstarexp)
{
strcpy (pr_token, "**");
pr_file_p += 2;
return;
}
for (i=0 ; (p = pr_punctuation[i]) != NULL ; i++)
{
len = strlen(p);
@ -2207,11 +2264,18 @@ void QCC_PR_LexPunctuation (void)
}
}
if ((unsigned char)*pr_file_p == (unsigned char)0xa0)
QCC_PR_ParseWarning (ERR_UNKNOWNPUCTUATION, "Unsupported punctuation: '\\x%x' - non-breaking space", (unsigned char)*pr_file_p);
if ((unsigned char)*pr_file_p == (unsigned char)'\\' && pr_file_p[1] == '\r' && pr_file_p[2] == '\n')
pr_file_p+=3;
else if ((unsigned char)*pr_file_p == (unsigned char)'\\' && (pr_file_p[1] == '\r' || pr_file_p[1] == '\n'))
pr_file_p+=2;
else
QCC_PR_ParseWarning (ERR_UNKNOWNPUCTUATION, "Unknown punctuation: '\\x%x'", *pr_file_p);
pr_file_p++;
{
if ((unsigned char)*pr_file_p == (unsigned char)0xa0)
QCC_PR_ParseWarning (ERR_UNKNOWNPUCTUATION, "Unsupported punctuation: '\\x%x' - non-breaking space", (unsigned char)*pr_file_p);
else
QCC_PR_ParseWarning (ERR_UNKNOWNPUCTUATION, "Unknown punctuation: '\\x%x'", *pr_file_p);
pr_file_p++;
}
QCC_PR_Lex();
}
@ -2742,6 +2806,11 @@ void QCC_PR_PreProcessor_Define(pbool append)
{
memcpy(cnst->params[cnst->numparams], s, nl);
cnst->params[cnst->numparams][nl] = '\0';
for (nl = 0; nl < cnst->numparams; nl++)
{
if (!strcmp(cnst->params[nl], cnst->params[cnst->numparams]))
QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "duplicate macro paramter name '%s'", cnst->params[nl]);
}
cnst->numparams++;
}
if (*pr_file_p++ == ')')
@ -2804,6 +2873,9 @@ void QCC_PR_PreProcessor_Define(pbool append)
*d++ = ' ';
}
cnst->fromfile = s_filen;
cnst->fromline = pr_source_line;
while(*s == ' ' || *s == '\t')
s++;
while(1)
@ -2859,7 +2931,7 @@ so if present, the preceeding \\\n and following \\\n must become an actual \n i
cnst->evil = true;
preprocessorhack = true;
}
else if (preprocessorhack)
else// if (preprocessorhack)
{
*d++ = '\n';
preprocessorhack = false;
@ -2921,6 +2993,7 @@ so if present, the preceeding \\\n and following \\\n must become an actual \n i
static void QCC_PR_ExpandStrCat(char **buffer, size_t *bufferlen, size_t *buffermax, char *newdata, size_t newlen)
{
size_t newmax = *bufferlen + newlen;
if (newmax < *bufferlen)//check for overflow
{
QCC_PR_ParseWarning(ERR_INTERNAL, "exceeds 4gb");
@ -2953,6 +3026,75 @@ static void QCC_PR_ExpandStrCat(char **buffer, size_t *bufferlen, size_t *buffer
*bufferlen += newlen;
/*no null terminator, remember to cat one if required*/
}
/* *buffer, *bufferlen and *buffermax should be NULL/0 at the start */
static void QCC_PR_ExpandStrCatMarkup(char **buffer, size_t *bufferlen, size_t *buffermax, char *newdata, size_t newlen)
{
size_t newmax = *bufferlen + newlen*2;
if (newmax < *bufferlen)//check for overflow
{
QCC_PR_ParseWarning(ERR_INTERNAL, "exceeds 4gb");
return;
}
if (newmax > *buffermax)
{
char *newbuf;
if (newmax < 64)
newmax = 64;
if (newmax < *bufferlen * 2)
{
newmax = *bufferlen * 2;
if (newmax < *bufferlen) /*overflowed?*/
{
QCC_PR_ParseWarning(ERR_INTERNAL, "exceeds 4gb");
return;
}
}
newbuf = realloc(*buffer, newmax);
if (!newbuf)
{
QCC_PR_ParseWarning(ERR_INTERNAL, "out of memory");
return; /*OOM*/
}
*buffer = newbuf;
*buffermax = newmax;
}
while (newlen--)
{
if (*newdata == '\n')
{
(*buffer)[*bufferlen+0] = '\\';
(*buffer)[*bufferlen+1] = '\n';
*bufferlen += 2;
}
else if (*newdata == '\\')
{
(*buffer)[*bufferlen+0] = '\\';
(*buffer)[*bufferlen+1] = '\\';
*bufferlen += 2;
}
else if (*newdata == '\0')
{
(*buffer)[*bufferlen+0] = '\\';
(*buffer)[*bufferlen+1] = '0';
*bufferlen += 2;
}
else if (*newdata == '\"')
{
(*buffer)[*bufferlen+0] = '\\';
(*buffer)[*bufferlen+1] = '\"';
*bufferlen += 2;
}
else
{
(*buffer)[*bufferlen] = *newdata;
*bufferlen += 1;
}
newdata++;
}
/*no null terminator, remember to cat one if required*/
}
static char *QCC_PR_CheckBuiltinCompConst(char *constname, char *retbuf, size_t retbufsize)
{
@ -3017,7 +3159,8 @@ static char *QCC_PR_CheckBuiltinCompConst(char *constname, char *retbuf, size_t
int QCC_PR_CheckCompConst(void)
{
char *oldpr_file_p = pr_file_p;
char *initial_file_p = pr_file_p;
int initial_line = pr_source_line;
int whitestart = 5;
CompilerConstant_t *c;
@ -3060,9 +3203,9 @@ int QCC_PR_CheckCompConst(void)
// printf("%s\n", pr_token);
c = pHash_Get(&compconstantstable, pr_token);
if (c && !c->inside)
if (c && (!currentchunk || currentchunk->cnst != c)) //macros don't expand themselves
{
pr_file_p = oldpr_file_p+strlen(c->name);
pr_file_p = initial_file_p+strlen(c->name);
while(*pr_file_p == ' ' || *pr_file_p == '\t')
pr_file_p++;
if (c->numparams>=0)
@ -3073,10 +3216,12 @@ int QCC_PR_CheckCompConst(void)
char *start;
char *starttok;
char *buffer;
char *argsend;
int argsendline;
size_t buffermax;
size_t bufferlen;
char *paramoffset[MAXCONSTANTPARAMS+1];
int param=0;
int param=0, extraparam=0;
int plevel=0;
pbool noargexpand;
@ -3097,7 +3242,7 @@ int QCC_PR_CheckCompConst(void)
else if (!plevel && (*pr_file_p == ',' || *pr_file_p == ')'))
{
if (*pr_file_p == ',' && c->varg && param >= c->numparams)
; //skip extra trailing , arguments if we're varging.
extraparam++; //skip extra trailing , arguments if we're varging.
else
{
paramoffset[param++] = start;
@ -3135,7 +3280,9 @@ int QCC_PR_CheckCompConst(void)
bufferlen = 0;
buffermax = 0;
oldpr_file_p = pr_file_p;
// QCC_PR_LexWhitespace(false);
argsend = pr_file_p;
argsendline = pr_source_line;
pr_file_p = c->value;
for(;;)
{
@ -3187,7 +3334,7 @@ int QCC_PR_CheckCompConst(void)
if (!STRCMP(qcc_token, c->params[p]))
{
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\"", 1);
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[p], strlen(paramoffset[p]));
QCC_PR_ExpandStrCatMarkup(&buffer, &bufferlen, &buffermax, paramoffset[p], strlen(paramoffset[p]));
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "\"", 1);
break;
}
@ -3253,7 +3400,23 @@ int QCC_PR_CheckCompConst(void)
}
}
if (c->varg && !STRCMP(qcc_token, "__VA_ARGS__"))
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[c->numparams], strlen(paramoffset[c->numparams]));
{
if (param-1 == c->numparams)
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[c->numparams], strlen(paramoffset[c->numparams]));
else if (noargexpand)
{
if(bufferlen>0 && buffer[bufferlen-1] == ',')
bufferlen--;
}
}
else if (c->varg && !STRCMP(qcc_token, "__VA_COUNT__"))
{
char tmp[64];
if (param < c->numparams)
QCC_PR_ParseError(ERR_TOOFEWPARAMS, "__VA_COUNT__ without any variable args");
QC_snprintfz(tmp, sizeof(tmp), "%i", param-1+extraparam);
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, tmp, strlen(tmp));
}
else if (p == c->numparams)
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token));
}
@ -3262,7 +3425,16 @@ int QCC_PR_CheckCompConst(void)
paramoffset[p][strlen(paramoffset[p])] = ',';
paramoffset[p][strlen(paramoffset[p])] = ')';
pr_file_p = oldpr_file_p;
if (c->inside>8)
{
pr_file_p = initial_file_p;
pr_source_line = initial_line;
free(buffer);
return false;
}
pr_file_p = argsend;
pr_source_line = argsendline;
if (!bufferlen)
expandedemptymacro = true;
else
@ -3286,6 +3458,13 @@ int QCC_PR_CheckCompConst(void)
}
else
{
if (c->inside >= 8)
{
pr_file_p = initial_file_p;
pr_source_line = initial_line;
return false;
}
if (*c->value)
QCC_PR_IncludeChunkEx(c->value, false, NULL, c);
expandedemptymacro = true;
@ -3539,8 +3718,25 @@ void QCC_PR_ParsePrintSRef (int type, QCC_sref_t def)
}
void *errorscope;
static void QCC_PR_PrintMacro (qcc_includechunk_t *chunk)
{
extern pbool verbose;
if (chunk)
{
QCC_PR_PrintMacro(chunk->prev);
if (chunk->cnst)
{
printf ("%s:%i: expanding %s\n", chunk->currentfilename, chunk->currentlinenumber, chunk->cnst->name);
if (verbose)
printf ("%s\n", chunk->datastart);
}
else
printf ("%s:%i:\n", chunk->currentfilename, chunk->currentlinenumber);
}
}
void QCC_PR_PrintScope (void)
{
QCC_PR_PrintMacro(currentchunk);
if (pr_scope)
{
if (errorscope != pr_scope)
@ -4390,6 +4586,10 @@ For error recovery, also pops out of nested braces
*/
void QCC_PR_SkipToSemicolon (void)
{
//escape out of any #define
while (currentchunk && currentchunk->cnst)
QCC_PR_UnInclude();
do
{
if (!pr_bracelevel && QCC_PR_CheckToken (";"))
@ -5519,7 +5719,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (i == numtypeinfos)
{
if (!*name)
{
QCC_PR_ParseError(ERR_NOTANAME, "type missing name");
return NULL;
}
//some reacc types...
if (!stricmp("Void", name))

View File

@ -4967,7 +4967,7 @@ static void GUI_CreateInstaller_Windows(void)
fprintf(f, "///downloadsurl is a list of optional updates, including engine updates, displayed via the updates menu. should always be https\n");
fprintf(f, "//downloadsurl \"https://fte.triptohell.info/downloadables.php\"\n");
fprintf(f, "///eula displayed when first installing\n");
fprintf(f, "//eula \"By using this game software, you assign your eternal soul to me for me to do as I wish, including but not limited to trading it for a pint of beer.\"\n");
fprintf(f, "//eula \"By using this game software, you assign your eternal soul to me for me to do as I wish, including but not limited to trading it for a pint of beer. This example is not legally binding.\"\n");
fclose(f);
EditFile(tmp, -1, false);
return;
@ -6792,6 +6792,9 @@ void AddSourceFile(const char *parentpath, const char *filename)
char parentstring[256];
char *slash;
while (!strncmp(filename, "./", 2))
filename += 2;
QC_strlcpy(string, filename, sizeof(string));
@ -6939,7 +6942,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
strcpy(enginebasedir, "");
strcpy(enginecommandline, "");
if(strstr(lpCmdLine, "-stdout"))
if(strstr(lpCmdLine, "-stdout") || strstr(lpCmdLine, "--version"))
{
GUI_ParseCommandLine(lpCmdLine);
RunCompiler(lpCmdLine, false);
@ -7113,7 +7116,6 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
fread(buf, 1, size, f);
fclose(f);
QCC_CloseAllVFiles();
strcpy(progssrcname, "progs.src");
if (!QC_EnumerateFilesFromBlob(buf, size, QCC_EnumerateFilesResult) && !QC_strcasecmp(ext, ".dat"))
{
char *c = ReadProgsCopyright(buf, size);
@ -7132,6 +7134,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
}
}
free(buf);
strcpy(progssrcname, "progs.src");
}
else
strcpy(progssrcname, "progs.src");

View File

@ -211,6 +211,8 @@ struct {
{" F316", WARN_IDENTICALPRECOMPILER},
{" F317", WARN_STALEMACRO},
{" F318", WARN_DUPLICATEMACRO},
{" F319", WARN_CONSTANTCOMPARISON},
{" F320", WARN_PARAMWITHNONAME},
{" F208", WARN_NOTREFERENCEDCONST},
{" F209", WARN_EXTRAPRECACHE},
@ -362,6 +364,10 @@ compiler_flag_t compiler_flag[] = {
{&flag_typeexplicit, FLAG_MIDCOMPILE,"typeexplicit", "Explicit types", "All type conversions must be explicit or directly supported by instruction set."},
{&flag_noboundchecks, FLAG_MIDCOMPILE,"noboundchecks","Disable Bound Checks", "Disable array index checks, speeding up array access but can result in your code misbehaving."},
{&flag_qccx, FLAG_MIDCOMPILE,"qccx", "QCCX syntax", "WARNING: This syntax makes mods inherantly engine specific.\nDo NOT use unless you know what you're doing.This is provided for compatibility only\nAny entity hacks will be unsupported in FTEQW, DP, and others, resulting in engine crashes if the code in question is executed."},
{&flag_attributes, FLAG_MIDCOMPILE|FLAG_HIDDENINGUI,"attributes", "[[attributes]]", "WARNING: This syntax conflicts with vector constructors."},
{&flag_assumevar, FLAG_MIDCOMPILE|FLAG_HIDDENINGUI,"assumevar", "explicit consts", "Initialised globals will be considered non-const by default."},
{&flag_dblstarexp, FLAG_MIDCOMPILE|FLAG_HIDDENINGUI,"ssp","** exponent", "Treat ** as an operator for exponents, instead of multiplying by a dereferenced pointer."},
{&flag_embedsrc, FLAG_MIDCOMPILE,"embedsrc", "Embed Sources", "Write the sourcecode into the output file."},
// {&flag_noreflection, FLAG_MIDCOMPILE,"omitinternals","Omit Reflection Info", "Keeps internal symbols private (equivelent to unix's hidden visibility). This has the effect of reducing filesize, thwarting debuggers, and breaking saved games. This allows you to use arrays without massively bloating the size of your progs.\nWARNING: The bit about breaking saved games was NOT a joke, but does not apply to menuqc or csqc. It also interferes with FTE_MULTIPROGS."},
{NULL}
@ -3903,7 +3909,14 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
strcat (qccmsourcedir, "/");
}
else if ( !strcmp(myargv[i], "-o") )
; //explicit output file
{ //explicit output file
i++;
strcpy(destfile, myargv[i]);
}
else if ( !strncmp(myargv[i], "-o", 2) )
{ //explicit output file
strcpy(destfile, myargv[i]+2);
}
else if ( !strcmp(myargv[i], "-qc") )
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Argument %s is experimental", myargv[i]); //compile without linking. output cannot be read by engines.
else if ( !strcmp(myargv[i], "-progdefs") )
@ -4005,6 +4018,59 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
if (!compiler_flag[p].enabled)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised keyword parameter (%s)", myargv[i]);
}
else if ( !strnicmp(myargv[i], "-std=", 5))
{
for (p = 0; compiler_flag[p].enabled; p++)
{
if (compiler_flag[p].flags & FLAG_ASDEFAULT)
*compiler_flag[p].enabled = true;
else
*compiler_flag[p].enabled = false;
}
if (!strcmp(myargv[i]+5, "fteqcc"))
; //as above, its the default.
else if (!strcmp(myargv[i]+5, "id"))
{
flag_ifvector = flag_vectorlogic = false;
keyword_asm = keyword_break = keyword_continue = keyword_for = keyword_goto = false;
keyword_const = keyword_var = keyword_inout = keyword_optional = keyword_state = keyword_inline = keyword_nosave = keyword_extern = keyword_shared = keyword_noref = keyword_unused = keyword_used = keyword_static = keyword_nonstatic = keyword_ignore = keyword_strip = false;
keyword_switch = keyword_case = keyword_default = keyword_class = keyword_const = false;
keyword_vector = keyword_entity = keyword_float = keyword_string = false; //not to be confused with actual types, but rather the absence of the keyword local.
keyword_int = keyword_integer = keyword_typedef = keyword_struct = keyword_union = keyword_enum = keyword_enumflags = false;
keyword_thinktime = keyword_until = keyword_loop = false;
keyword_wrap = keyword_weak = false;
}
else if (!strcmp(myargv[i]+5, "gmqcc"))
{
flag_ifvector = flag_vectorlogic = true;
flag_dblstarexp = flag_attributes = flag_assumevar = pr_subscopedlocals = true;
qccwarningaction[WARN_CONSTANTCOMPARISON] = WA_IGNORE;
qccwarningaction[WARN_POINTLESSSTATEMENT] = WA_IGNORE;
qccwarningaction[WARN_OVERFLOW] = WA_IGNORE;
qccwarningaction[WARN_STRICTTYPEMISMATCH] = WA_IGNORE;
qccwarningaction[WARN_PARAMWITHNONAME] = WA_IGNORE;
keyword_asm = false;
keyword_inout = keyword_optional = keyword_state = keyword_inline = keyword_nosave = keyword_extern = keyword_shared = keyword_unused = keyword_used = keyword_nonstatic = keyword_ignore = keyword_strip = false;
keyword_class = false;
keyword_vector = keyword_entity = keyword_float = keyword_string = false; //not to be confused with actual types, but rather the absence of the keyword local.
keyword_int = keyword_integer = keyword_struct = keyword_union = keyword_enum = keyword_enumflags = false;
keyword_thinktime = keyword_until = keyword_loop = false;
keyword_wrap = keyword_weak = true; //wrong, but needed because we don't accept useless function bodies without weak
keyword_enum = true;
keyword_break = keyword_continue = keyword_for = keyword_goto = true;
keyword_typedef = true;
keyword_switch = keyword_case = keyword_default = true;
keyword_const = keyword_var = keyword_static = keyword_noref = true;
}
else
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised std parameter (%s)", myargv[i]);
}
else if ( !strnicmp(myargv[i], "-F", 2) || WINDOWSARG(!strnicmp(myargv[i], "/F", 2)) )
{
pbool state;
@ -4137,8 +4203,21 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised warning parameter (%s)", myargv[i]);
}
}
else if ( !strcmp(myargv[i], "-stdout") )
{
}
else if ( !strcmp(myargv[i], "--version") )
{
printf("%s\n", QCC_VersionString());
exit(EXIT_SUCCESS);
}
else if (*myargv[i] == '-' || WINDOWSARG(*myargv[i] == '/'))
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised parameter (%s)", myargv[i]);
else
{
if (numsourcefiles < MAXSOURCEFILESLIST)
strcpy(sourcefileslist[numsourcefiles++], myargv[i]);
}
}
if (werror)
@ -4459,7 +4538,7 @@ pbool QCC_main (int argc, char **argv) //as part of the quake engine
MAX_FIELDS = 1<<12;
MAX_STATEMENTS = 0x80000;
MAX_FUNCTIONS = 16384;
maxtypeinfos = 16384;
maxtypeinfos = 32768;
MAX_CONSTANTS = 4096;
compressoutput = 0;

View File

@ -67,9 +67,6 @@ cvar_t pr_ssqc_memsize = CVARD("pr_ssqc_memsize", "-1", "The ammount of memory a
/*cvars purely for compat with others*/
cvar_t pr_imitatemvdsv = CVARFD("pr_imitatemvdsv", "0", CVAR_LATCH, "Enables mvdsv-specific builtins, and fakes identifiers so that mods made for mvdsv can run properly and with the full feature set.");
/*compat with frikqcc's arrays (ensures that unknown fields are at the same offsets*/
cvar_t pr_fixbrokenqccarrays = CVARFD("pr_fixbrokenqccarrays", "0", CVAR_LATCH, "When set, ensures that fields are not relocated unless remapped, working around stripped/immediate field offsets. This results in higher memory usage, but may be needed for compat with certain mods, namely ktpro.");
/*other stuff*/
cvar_t pr_maxedicts = CVARAFD("pr_maxedicts", "32768", "max_edicts", CVAR_LATCH, "Maximum number of entities spawnable on the map at once. Low values will crash the server on some maps/mods. High values will result in excessive memory useage (see pr_ssqc_memsize). Illegible server messages may occur with old/other clients above 32k. FTE's network protocols have a maximum at a little over 4 million. Please don't ever make a mod that actually uses that many...");
@ -795,6 +792,12 @@ void PR_LoadGlabalStruct(qboolean muted)
globalint (false, trace_surface_id);
globalint (false, trace_bone_id);
globalint (false, trace_triangle_id);
#ifndef NOLEGACY
globalstring (false, trace_dphittexturename);
globalfloat (false, trace_dpstartcontents);
globalfloat (false, trace_dphitcontents);
globalfloat (false, trace_dphitq3surfaceflags);
#endif
globalfloat (false, cycle_wrapped);
globalint (false, msg_entity);
globalfunc (false, main);
@ -1379,7 +1382,6 @@ void PR_Init(void)
#endif
*/
Cvar_Register(&pr_imitatemvdsv, cvargroup_progs);
Cvar_Register(&pr_fixbrokenqccarrays, cvargroup_progs);
Cvar_Register(&pr_maxedicts, cvargroup_progs);
Cvar_Register(&pr_no_playerphysics, cvargroup_progs);
@ -1476,7 +1478,11 @@ struct spawnents_s
{
int killonspawnflags;
eval_t *fulldata;
func_t CheckSpawn;
qboolean foundfuncs;
func_t CheckSpawn; //fte's alternative to spawn functions.
func_t SV_OnEntityPreSpawnFunction; //dp's more clumsy crap
func_t SV_OnEntityNoSpawnFunction; //dp's more clumsy crap
func_t SV_OnEntityPostSpawnFunction; //dp's more clumsy crap
const char *spawnwarned[32];
};
static void PDECL PR_DoSpawnInitialEntity(pubprogfuncs_t *progfuncs, struct edict_s *ed, void *vctx, const char *start, const char *end)
@ -1492,8 +1498,23 @@ static void PDECL PR_DoSpawnInitialEntity(pubprogfuncs_t *progfuncs, struct edic
return;
}
if (!ctx->CheckSpawn)
if (!ctx->foundfuncs)
{
ctx->foundfuncs = true;
ctx->CheckSpawn = PR_FindFunction(progfuncs, "CheckSpawn", -2);
ctx->SV_OnEntityPreSpawnFunction = PR_FindFunction(progfuncs, "SV_OnEntityPreSpawnFunction", -2);
ctx->SV_OnEntityNoSpawnFunction = PR_FindFunction(progfuncs, "SV_OnEntityNoSpawnFunction", -2);
ctx->SV_OnEntityPostSpawnFunction = PR_FindFunction(progfuncs, "SV_OnEntityPostSpawnFunction", -2);
}
if (ctx->SV_OnEntityPreSpawnFunction)
{
void *pr_globals = PR_globals(progfuncs, PR_CURRENT);
*sv.world.g.self = EDICT_TO_PROG(progfuncs, ed);
PR_ExecuteProgram(progfuncs, ctx->SV_OnEntityPreSpawnFunction);
if (ed->ereftype == ER_FREE)
return;
}
eclassname = PR_GetString(progfuncs, ed->v->classname);
if (!*eclassname)
@ -1538,6 +1559,8 @@ static void PDECL PR_DoSpawnInitialEntity(pubprogfuncs_t *progfuncs, struct edic
f = PR_FindFunction(progfuncs, spawnfuncname, PR_ANYBACK);
if (!f)
f = PR_FindFunction(progfuncs, eclassname, PR_ANYBACK);
if (!f)
f = ctx->SV_OnEntityNoSpawnFunction;
if (f)
{
if (ctx->CheckSpawn)
@ -1548,7 +1571,16 @@ static void PDECL PR_DoSpawnInitialEntity(pubprogfuncs_t *progfuncs, struct edic
//call the spawn func or remove.
}
else
{
if (developer.value)
{
int argcount;
progfuncs->GetFunctionInfo(progfuncs, f, &argcount, NULL, spawnfuncname, sizeof(spawnfuncname));
if (argcount != 0)
Con_Printf("Spawn function %s defined with unsatisfied arguments\n", spawnfuncname);
}
PR_ExecuteProgram(progfuncs, f);
}
}
else if (ctx->CheckSpawn)
{
@ -1578,6 +1610,15 @@ static void PDECL PR_DoSpawnInitialEntity(pubprogfuncs_t *progfuncs, struct edic
ED_Free(progfuncs, ed);
}
}
if (ctx->SV_OnEntityPostSpawnFunction)
{
void *pr_globals = PR_globals(progfuncs, PR_CURRENT);
if (ed->ereftype == ER_FREE)
return;
*sv.world.g.self = EDICT_TO_PROG(progfuncs, ed);
PR_ExecuteProgram(progfuncs, ctx->SV_OnEntityPreSpawnFunction);
}
}
void PR_SpawnInitialEntities(const char *file)
{
@ -1640,6 +1681,18 @@ void PR_SpawnInitialEntities(const char *file)
sv.world.edict_size = 0;
}
static qofs_t PR_ReadBytesString(char *str)
{
size_t u = strtoul(str, &str, 0);
if (*str == 'g')
u *= 1024*1024*1024;
if (*str == 'm')
u *= 1024*1024;
if (*str == 'k')
u *= 1024;
return u;
}
void SV_RegisterH2CustomTents(void);
void Q_InitProgs(void)
{
@ -1660,7 +1713,7 @@ void Q_InitProgs(void)
memset(pr_builtin, 0, sizeof(pr_builtin));
// load progs to get entity field count
PR_Configure(svprogfuncs, pr_ssqc_memsize.ival, MAX_PROGS, pr_enable_profiling.ival);
PR_Configure(svprogfuncs, PR_ReadBytesString(pr_ssqc_memsize.string), MAX_PROGS, pr_enable_profiling.ival);
PR_RegisterFields();
@ -2008,11 +2061,15 @@ void Q_InitProgs(void)
}
}
// svprogfuncs->ToggleBreak(svprogfuncs, "", 0, 2);
// svprogfuncs->SetWatchPoint(svprogfuncs, "");
sv.world.edict_size = PR_InitEnts(svprogfuncs, sv.world.max_edicts);
/* {
char watch[] = "something";
svprogfuncs->SetWatchPoint(svprogfuncs, watch);
}
*/
// svprogfuncs->ToggleBreak(svprogfuncs, "something", 0, 2);
#ifdef HEXEN2
SV_RegisterH2CustomTents();
#endif
@ -2109,7 +2166,7 @@ qboolean PR_GameCodePacket(char *s)
return G_FLOAT(OFS_RETURN);
}
qboolean PR_ParseClusterEvent(char *dest, char *source, char *cmd, char *info)
qboolean PR_ParseClusterEvent(const char *dest, const char *source, const char *cmd, const char *info)
{
globalvars_t *pr_globals;
@ -2134,7 +2191,7 @@ void SSQC_MapEntityEdited(int modelidx, int idx, const char *newdata)
{
}
qboolean PR_KrimzonParseCommand(char *s)
qboolean PR_KrimzonParseCommand(const char *s)
{
globalvars_t *pr_globals;
@ -2163,8 +2220,8 @@ qboolean PR_KrimzonParseCommand(char *s)
return false;
}
int tokenizeqc(char *str, qboolean dpfuckage);
qboolean PR_UserCmd(char *s)
int tokenizeqc(const char *str, qboolean dpfuckage);
qboolean PR_UserCmd(const char *s)
{
globalvars_t *pr_globals;
#ifdef Q2SERVER
@ -2511,7 +2568,7 @@ objerror(value)
*/
static void QCBUILTIN PF_objerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
edict_t *ed;
s = PF_VarString(prinst, 0, pr_globals);
@ -2824,7 +2881,7 @@ bprint(value)
*/
static void QCBUILTIN PF_bprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
int level;
#ifdef SERVER_DEMO_PLAYBACK
@ -2858,7 +2915,7 @@ sprint(clientent, value)
*/
static void QCBUILTIN PF_sprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
client_t *client;
int entnum;
int level;
@ -2996,7 +3053,7 @@ void PF_centerprint_Internal (int entnum, qboolean plaque, const char *s)
static void QCBUILTIN PF_centerprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s;
const char *s;
int entnum;
entnum = G_EDICTNUM(prinst, OFS_PARM0);
@ -3283,14 +3340,15 @@ void PF_ambientsound_Internal (float *pos, const char *samp, float vol, float at
int soundnum;
// check to see if samp was properly precached
for (soundnum=1 ; *sv.strings.sound_precache[soundnum] ; soundnum++)
for (soundnum=1 ; ; soundnum++)
{
if (soundnum == MAX_PRECACHE_SOUNDS || !sv.strings.sound_precache[soundnum])
{
Con_TPrintf ("no precache: %s\n", samp);
return;
}
if (!strcmp(sv.strings.sound_precache[soundnum],samp))
break;
if (!*sv.strings.sound_precache[soundnum])
{
Con_TPrintf ("no precache: %s\n", samp);
return;
}
if (sv.num_static_sounds == sv_max_staticsounds)
@ -3421,6 +3479,38 @@ static void QCBUILTIN PF_ss_LocalSound(pubprogfuncs_t *prinst, struct globalvars
#define PF_ss_LocalSound PF_Fixme
#endif
unsigned int FTEToDPContents(unsigned int contents)
{
unsigned int r = 0;
if (contents & FTECONTENTS_SOLID)
r |= DPCONTENTS_SOLID;
if (contents & FTECONTENTS_WATER)
r |= DPCONTENTS_WATER;
if (contents & FTECONTENTS_SLIME)
r |= DPCONTENTS_SLIME;
if (contents & FTECONTENTS_LAVA)
r |= DPCONTENTS_LAVA;
if (contents & FTECONTENTS_SKY)
r |= DPCONTENTS_SKY;
if (contents & FTECONTENTS_BODY)
r |= DPCONTENTS_BODY;
if (contents & FTECONTENTS_CORPSE)
r |= DPCONTENTS_CORPSE;
if (contents & Q3CONTENTS_NODROP)
r |= DPCONTENTS_NODROP;
if (contents & FTECONTENTS_PLAYERCLIP)
r |= DPCONTENTS_PLAYERCLIP;
if (contents & FTECONTENTS_MONSTERCLIP)
r |= DPCONTENTS_MONSTERCLIP;
if (contents & Q3CONTENTS_DONOTENTER)
r |= DPCONTENTS_DONOTENTER;
if (contents & Q3CONTENTS_BOTCLIP)
r |= DPCONTENTS_BOTCLIP;
// if (contents & FTECONTENTS_OPAQUE)
// r |= DPCONTENTS_OPAQUE;
return r;
}
static void set_trace_globals(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals, trace_t *trace)
{
pr_global_struct->trace_allsolid = trace->allsolid;
@ -3440,6 +3530,17 @@ static void set_trace_globals(pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
pr_global_struct->trace_bone_id = trace->bone_id;
pr_global_struct->trace_triangle_id = trace->triangle_id;
#ifndef NOLEGACY
if (pr_global_ptrs->trace_dphittexturename)
prinst->SetStringField(prinst, NULL, &pr_global_struct->trace_dphittexturename, trace->surface?trace->surface->name:NULL, true);
if (pr_global_ptrs->trace_dpstartcontents)
pr_global_struct->trace_dpstartcontents = FTEToDPContents(0); //fixme, maybe
if (pr_global_ptrs->trace_dphitcontents)
pr_global_struct->trace_dphitcontents = FTEToDPContents(pr_global_struct->trace_endcontentsi);
if (pr_global_ptrs->trace_dphitq3surfaceflags)
pr_global_struct->trace_dphitq3surfaceflags = pr_global_struct->trace_surfaceflagsf;
#endif
// if (trace.fraction != 1)
// VectorMA (trace->endpos, 4, trace->plane.normal, P_VEC(trace_endpos));
// else
@ -3536,6 +3637,8 @@ static void QCBUILTIN PF_traceboxdp (pubprogfuncs_t *prinst, struct globalvars_s
nomonsters = G_FLOAT(OFS_PARM4);
ent = G_EDICT(prinst, OFS_PARM5);
// PR_StackTrace(prinst, 2);
trace = World_Move (&sv.world, v1, mins, maxs, v2, nomonsters|MOVE_IGNOREHULL, (wedict_t*)ent);
set_trace_globals(prinst, pr_globals, &trace);
@ -3695,7 +3798,10 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
{
if (cl->state != cs_spawned || cl->controller != cl)
continue;
SV_StuffcmdToClient(cl, str);
if (flags & STUFFCMD_UNRELIABLE)
SV_StuffcmdToClient_Unreliable(cl, str);
else
SV_StuffcmdToClient(cl, str);
}
if (!(flags & STUFFCMD_IGNOREINDEMO))
if (sv.mvdrecording)
@ -3760,7 +3866,12 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
slen = strlen(str);
if (!(flags & STUFFCMD_DEMOONLY))
SV_StuffcmdToClient(cl, str);
{
if (flags & STUFFCMD_UNRELIABLE)
SV_StuffcmdToClient_Unreliable(cl, str);
else
SV_StuffcmdToClient(cl, str);
}
if (!(flags & STUFFCMD_IGNOREINDEMO))
if (sv.mvdrecording)
@ -3781,7 +3892,12 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
if (spec->state != cs_spawned || !spec->spectator)
continue;
if (spec->spec_track == entnum && (spec->spec_print & SPECPRINT_STUFFCMD))
SV_StuffcmdToClient(spec, str);
{
if (flags & STUFFCMD_UNRELIABLE)
SV_StuffcmdToClient_Unreliable(spec, str);
else
SV_StuffcmdToClient(spec, str);
}
}
}
}
@ -3833,13 +3949,16 @@ static void QCBUILTIN PF_dropclient (pubprogfuncs_t *prinst, struct globalvars_s
//entity() spawnclient = #454;
static void QCBUILTIN PF_spawnclient (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
extern int nextuserid;
int i;
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (!*svs.clients[i].name && !svs.clients[i].protocol && svs.clients[i].state == cs_free)
{
svs.clients[i].userid = ++nextuserid;
svs.clients[i].protocol = SCP_BAD; //marker for bots
svs.clients[i].state = cs_spawned;
svs.clients[i].spawned = true;
sv.spawned_client_slots++;
svs.clients[i].netchan.message.allowoverflow = true;
svs.clients[i].netchan.message.maxsize = 0;
@ -4111,7 +4230,8 @@ int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s)
if (s[0] <= ' ')
{
PR_BIError (prinst, "PF_precache_sound: Bad string");
if (*s)
PR_BIError (prinst, "PF_precache_sound: Bad string");
return 0;
}
@ -5204,7 +5324,7 @@ void PF_WriteString_Internal (int target, const char *str)
static void QCBUILTIN PF_WriteString (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 1, pr_globals);
const char *str = PF_VarString(prinst, 1, pr_globals);
PF_WriteString_Internal(G_FLOAT(OFS_PARM0), str);
}
@ -5280,7 +5400,7 @@ void QCBUILTIN PF_WriteEntity (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
static void QCBUILTIN PF_WriteString2 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int old;
char *str;
const char *str;
if (G_FLOAT(OFS_PARM0) != MSG_CSQC && (pr_nonetaccess.value
#ifdef SERVER_DEMO_PLAYBACK
@ -6079,7 +6199,7 @@ void QCBUILTIN PF_sqlopenquery (pubprogfuncs_t *prinst, struct globalvars_s *pr_
sqlserver_t *server;
int callfunc = G_INT(OFS_PARM1);
int querytype = G_FLOAT(OFS_PARM2);
char *querystr = PF_VarString(prinst, 3, pr_globals);
const char *querystr = PF_VarString(prinst, 3, pr_globals);
if (SQL_Available())
{
@ -6810,7 +6930,8 @@ void log(string name, float console, string text)
static void QCBUILTIN PF_logtext(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char name[MAX_OSPATH], *text;
char name[MAX_OSPATH];
const char *text;
vfsfile_t *file;
snprintf(name, MAX_OSPATH, "%s.log", PR_GetStringOfs(prinst, OFS_PARM0));
@ -6940,101 +7061,6 @@ static void QCBUILTIN PF_OpenPortal (pubprogfuncs_t *prinst, struct globalvars_s
#endif
}
//EXTENSION: DP_QC_FINDCHAIN
//entity(string field, string match) findchain = #402
//chained search for strings in entity fields
static void QCBUILTIN PF_sv_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
const char *s;
string_t t;
edict_t *ent, *chain;
chain = (edict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = PR_GetStringOfs(prinst, OFS_PARM1);
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
t = *(string_t *)&((float*)ent->v)[f];
if (!t)
continue;
if (strcmp(PR_GetString(prinst, t), s))
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
RETURN_EDICT(prinst, chain);
}
//EXTENSION: DP_QC_FINDCHAINFLOAT
//entity(string field, float match) findchainfloat = #403
//chained search for float, int, and entity reference fields
static void QCBUILTIN PF_sv_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
float s;
edict_t *ent, *chain;
chain = (edict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = G_FLOAT(OFS_PARM1);
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
if (((float *)ent->v)[f] != s)
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
RETURN_EDICT(prinst, chain);
}
//EXTENSION: DP_QC_FINDCHAINFLAGS
//entity(string field, float match) findchainflags = #450
//chained search for float, int, and entity reference fields
static void QCBUILTIN PF_sv_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, f;
int s;
edict_t *ent, *chain;
chain = (edict_t *) *prinst->parms->sv_edicts;
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
s = G_FLOAT(OFS_PARM1);
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
{
ent = EDICT_NUM(prinst, i);
if (ED_ISFREE(ent))
continue;
if (!((int)((float *)ent->v)[f] & s))
continue;
ent->v->chain = EDICT_TO_PROG(prinst, chain);
chain = ent;
}
RETURN_EDICT(prinst, chain);
}
//EXTENSION: KRIMZON_SV_PARSECLIENTCOMMAND
//void(entity e, string s) clientcommand = #440
@ -9072,7 +9098,7 @@ int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *v
{
int ns = !!atoi(value);
if (svs.clients[entnum-1].state == cs_spawned)
if (svs.clients[entnum-1].spawned && svs.clients[entnum-1].state == cs_spawned)
{
if (svs.clients[entnum-1].spectator)
sv.spawned_observer_slots--;
@ -9331,7 +9357,7 @@ static void QCBUILTIN PF_clientstat(pubprogfuncs_t *prinst, struct globalvars_s
//void(float num, float type, string name) globalstat
static void QCBUILTIN PF_globalstat(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *name = PF_VarString(prinst, 2, pr_globals);
const char *name = PF_VarString(prinst, 2, pr_globals);
#if 0 //this is the old code
SV_QCStatName(G_FLOAT(OFS_PARM0), name, G_FLOAT(OFS_PARM1));
#else
@ -9955,7 +9981,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"precache_model", PF_precache_model, 20, 20, 20, 0, D("string(string s)", "Precaches a model, making it known to clients and loading it from disk if it has a .bsp extension. This builtin (strongly) should be called during spawn functions. This must be called for each model name before setmodel may use that model name.\nModelindicies precached in SSQC will always be positive. CSQC precaches will be negative if they are not also on the server.")},
{"stuffcmd", PF_stuffcmd, 21, 21, 21, 0, D("void(entity client, string s)", "Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \\n.\nThis builtin is generally considered evil.")},
{"stuffcmdflags", PF_stuffcmdflags, 0, 0, 0, 0, D("void(entity client, float flags, string s)", "Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \\n.\nThis (just as evil) variant allows specifying some flags too. See the STUFFCMD_* constants.")},
{"findradius", PF_findradius, 22, 22, 22, 0, D("entity(vector org, float rad)", "Finds all entities within a distance of the 'org' specified. One entity is returned directly, while other entities are returned via that entity's .chain field.")},
{"findradius", PF_findradius, 22, 22, 22, 0, D("entity(vector org, float rad, optional .entity chainfield)", "Finds all entities within a distance of the 'org' specified. One entity is returned directly, while other entities are returned via that entity's .chain field.")},
//both bprint and sprint accept different arguments in QW vs NQ/H2
{"bprint", PF_bprint, 23, 0, 23, 0, D("void(string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8)", "NQ: Concatenates all arguments, and prints the messsage on the console of all connected clients.")},
{"bprint", PF_bprint, 0, 23, 0, 0, D("void(float msglvl, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "QW: Concatenates all string arguments, and prints the messsage on the console of only all clients who's 'msg' infokey is set lower or equal to the supplied 'msglvl' argument.")},
@ -10520,9 +10546,9 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
//DP_SV_SETCOLOR
{"setcolors", PF_setcolors, 0, 0, 0, 401, D("void(entity ent, float colours)", "Changes a player's colours. The bits 0-3 are the lower/trouser colour, bits 4-7 are the upper/shirt colours.")},//DP_SV_SETCOLOR
//DP_QC_FINDCHAIN
{"findchain", PF_sv_findchain, 0, 0, 0, 402, "entity(.string field, string match)"},// (DP_QC_FINDCHAIN)
{"findchain", PF_findchain, 0, 0, 0, 402, "entity(.string field, string match, optional .entity chainfield)"},// (DP_QC_FINDCHAIN)
//DP_QC_FINDCHAINFLOAT
{"findchainfloat", PF_sv_findchainfloat,0, 0, 0, 403, "entity(.float fld, float match)"},// (DP_QC_FINDCHAINFLOAT)
{"findchainfloat", PF_findchainfloat,0, 0, 0, 403, "entity(.float fld, float match, optional .entity chainfield)"},// (DP_QC_FINDCHAINFLOAT)
//DP_SV_EFFECT
{"effect", PF_effect, 0, 0, 0, 404, D("void(vector org, string modelname, float startframe, float endframe, float framerate)", "Spawns a self-animating sprite")},// (DP_SV_EFFECT)
//DP_TE_BLOOD
@ -10619,7 +10645,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"search_getfilemtime", PF_search_getfilemtime,0,0, 0, 0, D("string(searchhandle handle, float num)", "Retrieves modification time of one of the files.")},
{"cvar_string", PF_cvar_string, 0, 0, 0, 448, "string(string cvarname)"},//DP_QC_CVAR_STRING
{"findflags", PF_FindFlags, 0, 0, 0, 449, "entity(entity start, .float fld, float match)"},//DP_QC_FINDFLAGS
{"findchainflags", PF_sv_findchainflags,0, 0, 0, 450, "entity(.float fld, float match)"},//DP_QC_FINDCHAINFLAGS
{"findchainflags", PF_findchainflags,0, 0, 0, 450, "entity(.float fld, float match, optional .entity chainfield)"},//DP_QC_FINDCHAINFLAGS
{"gettagindex", PF_gettagindex, 0, 0, 0, 451, "float(entity ent, string tagname)"},// (DP_MD3_TAGSINFO)
{"gettaginfo", PF_gettaginfo, 0, 0, 0, 452, D("vector(entity ent, float tagindex)", "Obtains the current worldspace position+orientation of the bone or tag from the given entity. The return value is the world coord, v_forward, v_right, v_up are also set according to the bone/tag's orientation.")},// (DP_MD3_TAGSINFO)
{"dropclient", PF_dropclient, 0, 0, 0, 453, "void(entity player)"},//DP_SV_BOTCLIENT
@ -10767,7 +10793,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"addwantedhostcachekey",PF_Fixme, 0, 0, 0, 623, "void(string key)"},
{"getextresponse", PF_Fixme, 0, 0, 0, 624, "string()"},
{"netaddress_resolve",PF_netaddress_resolve,0, 0, 0, 625, "string(string dnsname, optional float defport)"},
// {"getgamedirinfo", PF_Fixme, 0, 0, 0, 626, "string(float n, float prop)"},
{"getgamedirinfo", PF_Fixme, 0, 0, 0, 626, "string(float n, float prop)" STUB},
{"sprintf", PF_sprintf, 0, 0, 0, 627, "string(string fmt, ...)"},
{"getsurfacenumtriangles",PF_getsurfacenumtriangles,0,0,0, 628, "float(entity e, float s)"},
{"getsurfacetriangle",PF_getsurfacetriangle,0, 0, 0, 629, "vector(entity e, float s, float n)"},
@ -11219,8 +11245,10 @@ svextqcfields
//Tell the qc library to split the entity fields each side.
//the fields above become < 0, the remaining fields specified by the qc stay where the mod specified, as far as possible (with addons at least).
//this means that custom array offsets still work in mods like ktpro.
if (pr_fixbrokenqccarrays.ival || pr_imitatemvdsv.ival)
PR_RegisterFieldVar(svprogfuncs, 0, NULL, 0,0);
if (!pr_fixbrokenqccarrays.ival && pr_imitatemvdsv.ival)
PR_RegisterFieldVar(svprogfuncs, 0, NULL, 1,0);
else
PR_RegisterFieldVar(svprogfuncs, 0, NULL, pr_fixbrokenqccarrays.ival,0);
}
//targets
@ -11410,8 +11438,8 @@ void PR_DumpPlatform_f(void)
{"button1", ".float", QW|NQ},
{"button2", ".float", QW|NQ},
{"impulse", ".float", QW|NQ},
{"fixangle", ".float", QW|NQ},
{"v_angle", ".vector", QW|NQ, "The angles a player is viewing. +x is DOWN (pitch, yaw, roll)"},
{"fixangle", ".float", QW|NQ, "Forces the clientside view angles to change to the value of .angles (has some lag). If set to 1/TRUE, the server will guess whether to send a delta or an explicit angle. If 2, will always send a delta (due to lag between transmission and acknowledgement, this cannot be spammed reliably). If 3, will always send an explicit angle."},
{"v_angle", ".vector", QW|NQ, "The angles a player is viewing. +x is DOWN (pitch, yaw, roll)"},
{"idealpitch", ".float", NQ},
{"netname", ".string", QW|NQ},
{"enemy", ".entity", QW|NQ|CS},
@ -11709,8 +11737,8 @@ void PR_DumpPlatform_f(void)
{"SOUNDFLAG_FORCELOOP", "const float", QW|NQ|CS, D("The sound will restart once it reaches the end of the sample."), CF_FORCELOOP},
{"SOUNDFLAG_NOSPACIALISE", "const float", /*QW|NQ|*/CS,D("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},
{"SOUNDFLAG_NOREVERB", "const float", QW|NQ|CS, D("Disables the use of underwater/reverb effects on this sound effect."), CF_NOREVERB},
{"SOUNDFLAG_UNICAST", "const float", QW|NQ, D("The sound will be heard only by the player specified by msg_entity."), CF_UNICAST},
{"SOUNDFLAG_FOLLOW", "const float", QW|NQ|CS, D("The sound's origin will updated to follow the emitting entity."), CF_FOLLOW},
{"SOUNDFLAG_UNICAST", "const float", QW|NQ, D("The sound will be heard only by the player specified by msg_entity."), CF_UNICAST},
{"SOUNDFLAG_SENDVELOCITY", "const float", QW|NQ, D("The entity's current velocity will be sent to the client, only useful if doppler is enabled."), CF_SENDVELOCITY},
{"ATTN_NONE", "const float", QW|NQ|CS, D("Sounds with this attenuation can be heard throughout the map"), ATTN_NONE},
@ -11795,6 +11823,7 @@ void PR_DumpPlatform_f(void)
{"STUFFCMD_IGNOREINDEMO","const float", QW|NQ, D("This stuffcmd will NOT be written to mvds/qtv."), STUFFCMD_IGNOREINDEMO},
{"STUFFCMD_DEMOONLY", "const float", QW|NQ, D("This stuffcmd will ONLY be written into mvds/qtv streams."), STUFFCMD_DEMOONLY},
{"STUFFCMD_BROADCAST", "const float", QW|NQ, D("The stuffcmd will be broadcast server-wide (according to the mvd filters)."), STUFFCMD_BROADCAST},
{"STUFFCMD_UNRELIABLE", "const float", QW|NQ, D("The stuffcmd might not arrive. It might also get there faster than ones sent over the reliable channel."), STUFFCMD_UNRELIABLE},
/* {"SOUND_RELIABLE", "const float", QW|NQ, D("The sound will be sent reliably, and without regard to phs."), CF_RELIABLE},
{"SOUND_FORCELOOP", "const float", QW|NQ|CS,D("The sound will restart once it reaches the end of the sample."), CF_FORCELOOP},

View File

@ -76,6 +76,12 @@ typedef struct nqglobalvars_s
int *trace_ent;
float *trace_inopen;
float *trace_inwater;
#ifndef NOLEGACY
string_t*trace_dphittexturename;
float *trace_dpstartcontents;
float *trace_dphitcontents;
float *trace_dphitq3surfaceflags;
#endif
int *msg_entity;
func_t *main;
func_t *StartFrame;
@ -203,7 +209,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldstring(noise1,NULL)\
comfieldstring(noise2,NULL)\
comfieldstring(noise3,NULL)
/*DO NOT ADD TO THE ABOVE STRUCTURE*/
/*DO NOT ADD TO THE ABOVE STRUCTURE (unless you want to break qvms)*/
#ifdef HEXEN2
#define comextqcfieldshexen2 \
@ -231,6 +237,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldfloat(dimension_hit,"This is the bitmask of dimensions which the entity will be blocked by. If other.dimension_solid & self.dimension_hit, our traces will impact and not proceed. If its false, the traces will NOT impact, allowing self to pass straight through.")/*EXT_DIMENSION_PHYSICS*/\
/*comfieldfloat_legacy(hitcontentsmask,"Traces performed for this entity will impact against surfaces that match this contents mask.")*/ \
comfieldint(hitcontentsmaski,"Traces performed for this entity will impact against surfaces that match this contents mask.")\
comfieldfloat_legacy(dphitcontentsmask, "Some crappy field that inefficiently requires translating to the native contents flags. Ditch the 'dp', do it properly.")\
comfieldfloat(scale,"Multiplier that resizes the entity. 1 is normal sized, 2 is double sized. scale 0 is remapped to 1. In SSQC, this is limited to 1/16th precision, with a maximum just shy of 16.")/*DP_ENT_SCALE*/\
comfieldfloat(fatness,"How many QuakeUnits to push the entity's verticies along their normals by.")/*FTE_PEXT_FATNESS*/\
comfieldfloat(alpha,"The transparency of the entity. 1 means opaque, 0.0001 means virtually invisible. 0 is remapped to 1, for compatibility.")/*DP_ENT_ALPHA*/\
@ -269,9 +276,9 @@ and the extension fields are added on the end and can have extra vm-specific stu
#define svextqcfields \
comfieldfloat(maxspeed,NULL)/*added in quake 1.09*/\
comfieldentity(view2,NULL)/*FTE_PEXT_VIEW2*/\
comfieldentity(view2,"defines a second viewpoint, typically displayed in a corner of the screen (also punches open pvs).")/*FTE_PEXT_VIEW2*/\
comfieldvector(movement,"These are the directions that the player is currently trying to move in (ie: which +forward/+moveright/+moveup etc buttons they have held), expressed relative to that player's angles. Order is forward, right, up.")\
comfieldfloat(vw_index,NULL)\
comfieldfloat(vw_index,"This acts as a second modelindex, using the same frames etc.")\
comfieldentity(nodrawtoclient,"This entity will not be sent to the player named by this field. They will be invisible and not emit dlights/particles. Does not work in MVD-recorded game.")\
comfieldentity(drawonlytoclient,"This entity will be sent *only* to the player named by this field. To other players they will be invisible and not emit dlights/particles. Does not work in MVD-recorded game.")\
comfieldentity(viewmodelforclient,"This entity will be sent only to the player named by this field, and this entity will be attached to the player's view as an additional weapon model.")/*DP_ENT_VIEWMODEL*/\

View File

@ -37,9 +37,9 @@ void PR_Init(void);
void QDECL ED_Spawned (struct edict_s *ent, int loading);
void SSQC_MapEntityEdited(int modelidx, int idx, const char *newdata);
qboolean SV_RunFullQCMovement(struct client_s *client, usercmd_t *ucmd);
qboolean PR_KrimzonParseCommand(char *s);
qboolean PR_ParseClusterEvent(char *dest, char *source, char *cmd, char *info);
qboolean PR_UserCmd(char *cmd);
qboolean PR_KrimzonParseCommand(const char *s);
qboolean PR_ParseClusterEvent(const char *dest, const char *source, const char *cmd, const char *info);
qboolean PR_UserCmd(const char *cmd);
qboolean PR_ConsoleCmd(const char *cmd);
void PRSV_RunThreads(void);

View File

@ -257,6 +257,9 @@ typedef struct
void (VARGS *AddCommandString) (const char *text);
void (VARGS *DebugGraph) (float value, int color);
//kmq2 adds pak file stuff, which is certainly useful, but is only half the solution when homedirs are involved.
} game_import_t;
//

View File

@ -141,7 +141,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
cl->name = cl->namebuf;
cl->state = cs_loadzombie;
cl->connection_started = realtime+20;
cl->istobeloaded = true;
cl->spawned = cl->istobeloaded = true;
for (i=0 ; i<16 ; i++)
{
@ -167,6 +167,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
cl = &svs.clients[clnum];
VFS_GETS(f, plname, sizeof(plname));
cl->spawned = false;
cl->istobeloaded = false;
cl->state = cs_free;
@ -332,6 +333,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
World_ClearWorld(&sv.world, true);
sv.spawned_client_slots = 0;
sv.spawned_observer_slots = 0;
for (i=0 ; i<svs.allocated_client_slots ; i++)
{
cl = &svs.clients[i];
@ -344,6 +346,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
else
ent = NULL;
cl->edict = ent;
cl->spawned = false;
cl->name = PR_AddString(svprogfuncs, cl->namebuf, sizeof(cl->namebuf), false);
cl->team = PR_AddString(svprogfuncs, cl->teambuf, sizeof(cl->teambuf), false);
@ -570,7 +573,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
int modelpos;
int filelen, filepos;
qofs_t filelen, filepos;
char *file;
gametype_e gametype;
@ -607,6 +610,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
#ifdef Q2SERVER
if (gametype == GT_QUAKE2)
{
char *s;
flocation_t loc;
SV_SpawnServer (level, startspot, false, false);
@ -627,6 +631,59 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
Con_Printf("%s is inside a package and cannot be used by the quake2 gamecode.\n", name);
return false;
}
if (savename)
Q_snprintfz (name, sizeof(name), "saves/%s/%s.lvx", savename, level);
else
Q_snprintfz (name, sizeof(name), "saves/%s.lvx", level);
file = FS_MallocFile(name, FS_GAME, &filelen);
if (file)
{
s = file;
//Read config strings
for (i = 0; i < countof(sv.strings.configstring) && s < file+filelen; i++)
{
Z_Free((char*)sv.strings.configstring[i]);
sv.strings.configstring[i] = Z_StrDup(s);
s += strlen(s)+1;
}
for (i = 0; s < file+filelen; i++)
{
if (!*s)
break;
if (i < countof(sv.strings.q2_extramodels))
{
Z_Free((char*)sv.strings.q2_extramodels[i]);
sv.strings.q2_extramodels[i] = Z_StrDup(s);
}
s += strlen(s)+1;
}
for (; i < countof(sv.strings.q2_extramodels); i++)
{
Z_Free((char*)sv.strings.q2_extramodels[i]);
sv.strings.q2_extramodels[i] = NULL;
}
for (i = 0; s < file+filelen; i++)
{
if (!*s)
break;
if (i < countof(sv.strings.q2_extrasounds))
{
Z_Free((char*)sv.strings.q2_extrasounds[i]);
sv.strings.q2_extrasounds[i] = Z_StrDup(s);
}
s += strlen(s)+1;
}
for (; i < countof(sv.strings.q2_extrasounds); i++)
{
Z_Free((char*)sv.strings.q2_extrasounds[i]);
sv.strings.q2_extrasounds[i] = NULL;
}
//Read portal state
CM_ReadPortalState(sv.world.worldmodel, s, (file+filelen)-s);
FS_FreeFile(file);
}
ge->ReadLevel(loc.rawname);
for (i=0 ; i<100 ; i++) //run for 10 secs to iron out a few bugs.
@ -776,6 +833,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
svs.clients[i].name = PR_AddString(svprogfuncs, svs.clients[i].namebuf, sizeof(svs.clients[i].namebuf), false);
svs.clients[i].team = PR_AddString(svprogfuncs, svs.clients[i].teambuf, sizeof(svs.clients[i].teambuf), false);
svs.clients[i].spawned = (svs.clients[i].state == cs_loadzombie);
#ifdef HEXEN2
if (ent)
svs.clients[i].playerclass = ent->xv->playerclass;
@ -910,6 +968,44 @@ void SV_SaveLevelCache(const char *savedir, qboolean dontharmgame)
if (!FS_NativePath(name, FS_GAMEONLY, syspath, sizeof(syspath)))
return;
ge->WriteLevel(syspath);
if (savedir)
Q_snprintfz (name, sizeof(name), "saves/%s/%s.lvx", savedir, svs.name);
else
Q_snprintfz (name, sizeof(name), "saves/%s.lvx", svs.name);
//write configstrings
f = FS_OpenVFS (name, "wbp", FS_GAMEONLY);
if (f)
{
for (i = 0; i < countof(sv.strings.configstring); i++)
{
if (sv.strings.configstring[i])
VFS_WRITE(f, sv.strings.configstring[i], strlen(sv.strings.configstring[i])+1);
else
VFS_WRITE(f, "", 1);
}
for (i = 0; i < countof(sv.strings.q2_extramodels); i++)
{
if (!sv.strings.q2_extramodels[i])
break;
VFS_WRITE(f, sv.strings.q2_extramodels[i], strlen(sv.strings.q2_extramodels[i])+1);
}
VFS_WRITE(f, "", 1);
for (i = 0; i < countof(sv.strings.q2_extrasounds); i++)
{
if (!sv.strings.q2_extrasounds[i])
break;
VFS_WRITE(f, sv.strings.q2_extrasounds[i], strlen(sv.strings.q2_extrasounds[i])+1);
}
VFS_WRITE(f, "", 1);
CM_WritePortalState(sv.world.worldmodel, f);
VFS_CLOSE(f);
}
FS_FlushFSHashFull();
return;
}
@ -946,7 +1042,7 @@ void SV_SaveLevelCache(const char *savedir, qboolean dontharmgame)
continue;
else if (progstype == PROG_H2)
cl->edict->ereftype = ER_FREE; //hexen2 has some annoying prints. it never formally dropped clients on map changes (we'll reset this later, so they'll just not appear in the saved game).
else if (cl->state < cs_spawned && !cl->istobeloaded) //don't drop if they are still connecting
else if (!cl->spawned) //don't drop if they are still connecting
{
cl->edict->v->solid = 0;
}
@ -1315,7 +1411,7 @@ static int QDECL CompleteSaveListLegacy (const char *name, qofs_t flags, time_t
ctx->cb(stripped, ctx);
return true;
}
void SV_Savegame_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx)
void SV_Savegame_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
if (argn == 1)
{
@ -1503,7 +1599,7 @@ void SV_Loadgame_f (void)
{
cl->state = cs_loadzombie;
cl->connection_started = realtime+20;
cl->istobeloaded = true;
cl->spawned = cl->istobeloaded = true;
cl->userid = 0;
loadzombies++;
memset(&cl->netchan, 0, sizeof(cl->netchan));

View File

@ -433,6 +433,7 @@ enum
#define STUFFCMD_IGNOREINDEMO ( 1<<0) // do not put in mvd demo
#define STUFFCMD_DEMOONLY ( 1<<1) // put in mvd demo only
#define STUFFCMD_BROADCAST ( 1<<2) // everyone sees it.
#define STUFFCMD_UNRELIABLE ( 1<<3) // someone might not see it. oh well.
typedef struct client_s
{
@ -567,6 +568,7 @@ typedef struct client_s
//true/false/persist
unsigned int penalties;
qbyte istobeloaded; //loadgame creates place holders for clients to connect to. Effectivly loading a game reconnects all clients, but has precreated ents.
qboolean spawned; //the player's entity was spawned.
double floodprotmessage;
double lastspoke;
@ -1139,7 +1141,7 @@ qboolean SV_LoadLevelCache(const char *savename, const char *level, const char *
void SV_Physics_Client (edict_t *ent, int num);
void SV_ExecuteUserCommand (char *s, qboolean fromQC);
void SV_ExecuteUserCommand (const char *s, qboolean fromQC);
void SV_InitOperatorCommands (void);
void SV_SendServerinfo (client_t *client);
@ -1242,7 +1244,7 @@ void SV_CalcNetRates(client_t *cl, double *ftime, int *frames, double *minf, dou
qboolean SV_ChallengePasses(int challenge);
void SV_QCStatName(int type, char *name, int statnum);
void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum);
void SV_QCStatGlobal(int type, char *globalname, int statnum);
void SV_QCStatGlobal(int type, const char *globalname, int statnum);
void SV_QCStatPtr(int type, void *ptr, int statnum);
void SV_ClearQCStats(void);
@ -1258,6 +1260,7 @@ void QDECL SVQ1_StartSound (float *origin, wedict_t *entity, int channel, const
void SV_PrintToClient(client_t *cl, int level, const char *string);
void SV_TPrintToClient(client_t *cl, int level, const char *string);
void SV_StuffcmdToClient(client_t *cl, const char *string);
void SV_StuffcmdToClient_Unreliable(client_t *cl, const char *string);
void VARGS SV_ClientPrintf (client_t *cl, int level, const char *fmt, ...) LIKEPRINTF(3);
void VARGS SV_ClientTPrintf (client_t *cl, int level, translation_t text, ...);
void VARGS SV_BroadcastPrintf (int level, const char *fmt, ...) LIKEPRINTF(2);
@ -1566,7 +1569,7 @@ int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *heade
// savegame.c
void SV_LegacySavegame_f(void);
void SV_Savegame_f (void);
void SV_Savegame_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx);
void SV_Savegame_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx);
void SV_Loadgame_f (void);
void SV_AutoSave(void);
void SV_FlushLevelCache(void);

View File

@ -423,7 +423,7 @@ static int QDECL CompleteMapListExt (const char *name, qofs_t flags, time_t mtim
ctx->cb(name+5, ctx);
return true;
}
static void SV_Map_c(int argn, char *partial, struct xcommandargcompletioncb_s *ctx)
static void SV_Map_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx)
{
if (argn == 1)
{

View File

@ -67,57 +67,6 @@ int needcleanup;
//int fatbytes;
#if defined(Q2BSPS) || defined(Q3BSPS)
unsigned int SV_Q2BSP_FatPVS (model_t *mod, vec3_t org, pvsbuffer_t *result, qboolean merge)
{
int leafs[64];
int i, j, count;
vec3_t mins, maxs;
for (i=0 ; i<3 ; i++)
{
mins[i] = org[i] - 8;
maxs[i] = org[i] + 8;
}
count = CM_BoxLeafnums (mod, mins, maxs, leafs, countof(leafs), NULL);
if (count < 1)
Sys_Error ("SV_Q2FatPVS: count < 1");
// convert leafs to clusters
for (i=0 ; i<count ; i++)
leafs[i] = CM_LeafCluster(mod, leafs[i]);
//grow the buffer if needed
if (result->buffersize < mod->pvsbytes)
result->buffer = BZ_Realloc(result->buffer, result->buffersize=mod->pvsbytes);
if (count == 1 && leafs[0] == -1)
{ //if the only leaf is the outside then broadcast it.
memset(result->buffer, 0xff, mod->pvsbytes);
i = count;
}
else
{
i = 0;
if (!merge)
mod->funcs.ClusterPVS(mod, leafs[i++], result, PVM_REPLACE);
// or in all the other leaf bits
for ( ; i<count ; i++)
{
for (j=0 ; j<i ; j++)
if (leafs[i] == leafs[j])
break;
if (j != i)
continue; // already have the cluster we want
mod->funcs.ClusterPVS(mod, leafs[i], result, PVM_MERGE);
}
}
return mod->pvsbytes;
}
#endif
void SV_ExpandNackFrames(client_t *client, int require)
{
client_frame_t *newframes;
@ -3105,56 +3054,6 @@ qboolean SV_GibFilter(edict_t *ent)
return false;
}
#if defined(Q2BSPS) || defined(Q3BSPS)
static int clientarea;
unsigned int Q23BSP_FatPVS(model_t *mod, vec3_t org, pvsbuffer_t *buffer, qboolean merge)
{//fixme: this doesn't add areas
int leafnum;
leafnum = CM_PointLeafnum (mod, org);
clientarea = CM_LeafArea (mod, leafnum);
return SV_Q2BSP_FatPVS (mod, org, buffer, merge);
}
qboolean Q23BSP_EdictInFatPVS(model_t *mod, pvscache_t *ent, qbyte *pvs)
{
int i,l;
int nullarea = (mod->fromgame == fg_quake2)?0:-1;
if (clientarea == ent->areanum)
{
if (clientarea == nullarea)
return false;
}
else if (!CM_AreasConnected (mod, clientarea, ent->areanum))
{ // doors can legally straddle two areas, so
// we may need to check another one
if (ent->areanum2 == nullarea
|| !CM_AreasConnected (mod, clientarea, ent->areanum2))
return false; // blocked by a door
}
if (ent->num_leafs == -1)
{ // too many leafs for individual check, go by headnode
if (!CM_HeadnodeVisible (mod, ent->headnode, pvs))
return false;
}
else
{ // check individual leafs
for (i=0 ; i < ent->num_leafs ; i++)
{
l = ent->leafnums[i];
if (pvs[l >> 3] & (1 << (l&7) ))
break;
}
if (i == ent->num_leafs)
return false; // not visible
}
return true;
}
#endif
#ifdef SERVER_DEMO_PLAYBACK
static void SV_Snapshot_Build_Playback(client_t *client, packet_entities_t *pack)
{

View File

@ -1264,6 +1264,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
for (i=0 ; i<svs.allocated_client_slots ; i++)
{
svs.clients[i].spawned = false;
svs.clients[i].edict = NULL;
svs.clients[i].name = svs.clients[i].namebuf;
svs.clients[i].team = svs.clients[i].teambuf;
@ -1394,6 +1395,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
ent->v->movetype = MOVETYPE_PUSH;
VectorCopy(sv.world.worldmodel->mins, ent->v->mins);
VectorCopy(sv.world.worldmodel->maxs, ent->v->maxs);
VectorCopy(sv.world.worldmodel->mins, ent->v->absmin);
VectorCopy(sv.world.worldmodel->maxs, ent->v->absmax);
if (progstype == PROG_QW && pr_imitatemvdsv.value>0)
{
@ -1685,6 +1688,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
host_client->sendinfo = true;
host_client->state = cs_spawned;
host_client->spawned = true;
SV_UpdateToReliableMessages(); //so that we don't flood too much with 31 bots and one player.
}

View File

@ -536,7 +536,7 @@ void SV_DropClient (client_t *drop)
case GT_PROGS:
if (svprogfuncs)
{
if ((drop->state == cs_spawned || drop->istobeloaded) && host_initialized)
if (drop->spawned && host_initialized)
{
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
@ -569,6 +569,7 @@ void SV_DropClient (client_t *drop)
if (progstype == PROG_NQ)
ED_Clear(svprogfuncs, drop->edict);
}
drop->spawned = false;
if (svprogfuncs && drop->edict && drop->edict->v)
drop->edict->v->frags = 0;
@ -1486,8 +1487,21 @@ qboolean SVC_GetChallenge (qboolean respond_dp)
const qboolean respond_qwoverq3 = false;
#endif
respond_std &= !!sv_listen_qw.value;
respond_dp &= !!sv_listen_dp.value;
if (sv_listen_qw.value && !sv_listen_dp.value)
{
respond_std = true;
respond_dp = false;
}
else if (sv_listen_dp.value && !sv_listen_qw.value)
{
respond_std = false;
respond_dp = true;
}
else
{
respond_std &= !!sv_listen_qw.value;
respond_dp &= !!sv_listen_dp.value;
}
if (progstype == PROG_H2)
respond_dp = false; //don't bother. dp doesn't support the maps anyway.
@ -1627,7 +1641,7 @@ qboolean SVC_GetChallenge (qboolean respond_dp)
if (sv_listen_qw.value)
dp = va("challenge FTE%i", challenge); //an FTE prefix will cause FTE clients to ignore the packet, to give preference to the qw challenge + protocols
else
dp = va("challenge %iFTE", challenge); //we still need to add a postfix to prevent it from being interpreted as a Q2 server
dp = va("challenge %iDP", challenge); //we still need to add a postfix to prevent it from being interpreted as a Q2 server
Netchan_OutOfBand(NS_SERVER, &net_from, strlen(dp)+1, dp);
}
@ -2050,6 +2064,8 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
client_t *cl, *prev;
int i;
int curclients;
qboolean loadgame;
const char *name;
if (!(controller->fteprotocolextensions & PEXT_SPLITSCREEN))
{
@ -2075,20 +2091,57 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
if (!sv_allow_splitscreen.ival && controller->netchan.remote_address.type != NA_LOOPBACK)
return NULL; //FIXME: allow spectators to do this anyway?
/* if (cl->state == cs_loadzombie)
{
if (!newcl)
{
if (((!strcmp(cl->name, name) || !*cl->name) && (!*cl->guid || !strcmp(guid, cl->guid))) || sv.allocated_client_slots <= 1) //named, or first come first serve.
{
if (cl->istobeloaded)
Con_DPrintf("%s:Using loadzombie\n", svs.name);
else
Con_DPrintf("%s:Using parmzombie\n", svs.name);
newcl = cl;
preserveparms = true;
temp.istobeloaded = cl->istobeloaded;
memcpy(temp.spawn_parms, cl->spawn_parms, sizeof(temp.spawn_parms));
if (cl->userid)
temp.userid = cl->userid;
break;
}
}
}
*/
name = Info_ValueForKey(info, "name");
for (i=0,cl=svs.clients ; i<sv.allocated_client_slots ; i++,cl++)
{
if (cl->state == cs_free)
{
break;
if (cl->state == cs_loadzombie && !controller->spectator)
{ //if this is a loadzombie with the same name as the new seat is trying to use then lets use that slot.
if (!strcmp(cl->name, name))
break;
}
}
if (i == sv.allocated_client_slots)
{
SV_PrintToClient(controller, PRINT_HIGH, "not enough free player slots\n");
return NULL;
for (i=0,cl=svs.clients ; i<sv.allocated_client_slots ; i++,cl++)
{
if (cl->state == cs_free)
{
break;
}
}
if (i == sv.allocated_client_slots)
{
SV_PrintToClient(controller, PRINT_HIGH, "not enough free player slots\n");
return NULL;
}
}
cl->spectator = controller->spectator;
loadgame = (cl->state == cs_loadzombie);
if (!loadgame)
cl->spectator = controller->spectator;
cl->netchan.remote_address = controller->netchan.remote_address;
cl->netchan.message.prim = controller->netchan.message.prim;
cl->zquake_extensions = controller->zquake_extensions;
@ -2107,8 +2160,8 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
cl->name = cl->namebuf;
cl->team = cl->teambuf;
nextuserid++; // so every client gets a unique id
cl->userid = nextuserid;
if (!cl->userid || !loadgame)
cl->userid = ++nextuserid;
cl->playerclass = 0;
cl->pendingdeltabits = NULL;
@ -2154,17 +2207,13 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id)
Q_strncpyS (cl->userinfo, info, sizeof(cl->userinfo)-1);
cl->userinfo[sizeof(cl->userinfo)-1] = '\0';
if (controller->spectator)
{
Info_RemoveKey (cl->userinfo, "spectator");
//this is a hint rather than a game breaker should it fail.
Info_SetValueForStarKey (cl->userinfo, "*spectator", "1", sizeof(cl->userinfo));
}
else
Info_RemoveKey (cl->userinfo, "*spectator");
Info_RemoveKey (cl->userinfo, "spectator");
//this is a hint rather than a game breaker should it fail.
Info_SetValueForStarKey (cl->userinfo, "*spectator", va("%i", cl->spectator), sizeof(cl->userinfo));
SV_ExtractFromUserinfo (cl, true);
SV_GetNewSpawnParms(cl);
if (!loadgame)
SV_GetNewSpawnParms(cl);
cl->state = controller->state;

View File

@ -411,6 +411,52 @@ void SV_StuffcmdToClient(client_t *cl, const char *string)
break;
}
}
void SV_StuffcmdToClient_Unreliable(client_t *cl, const char *string)
{
switch (cl->protocol)
{
case SCP_BAD: //bot
break;
case SCP_QUAKE2:
#ifdef Q2SERVER
ClientReliableWrite_Begin (cl, svcq2_stufftext, strlen(string)+3);
ClientReliableWrite_String (cl, string);
#endif
break;
case SCP_QUAKE3:
break;
case SCP_QUAKEWORLD:
case SCP_DARKPLACES6:
case SCP_DARKPLACES7:
case SCP_NETQUAKE:
case SCP_BJP3:
case SCP_FITZ666:
if (cl->controller)
{ //this is a slave client.
//find the right number and send.
int pnum = 0;
client_t *sp;
for (sp = cl->controller; sp; sp = sp->controlled)
{
if (sp == cl)
break;
pnum++;
}
sp = cl->controller;
MSG_WriteByte (&sp->datagram, svcfte_choosesplitclient);
MSG_WriteByte (&sp->datagram, pnum);
MSG_WriteByte (&sp->datagram, svc_stufftext);
MSG_WriteString (&sp->datagram, string);
}
else
{
MSG_WriteByte(&cl->datagram, svc_stufftext);
MSG_WriteString(&cl->datagram, string);
}
break;
}
}
/*
@ -1613,6 +1659,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
}
else if (ent->v->fixangle)
{
int fix = ent->v->fixangle;
if (!client->lockangles)
{
//try to keep them vaugely reliable.
@ -1625,7 +1672,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
MSG_WriteByte(msg, svcfte_choosesplitclient);
MSG_WriteByte(msg, pnum);
}
if (!client->lockangles && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && controller->delta_sequence != -1 && !client->viewent)
if (((!client->lockangles && fix!=3) || fix==2) && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && controller->delta_sequence != -1 && !client->viewent)
{
MSG_WriteByte (msg, svcfte_setangledelta);
for (i=0 ; i < 3 ; i++)
@ -1989,7 +2036,7 @@ typedef struct {
} qcstat_t;
qcstat_t qcstats[MAX_CL_STATS];
int numqcstats;
void SV_QCStatEval(int type, char *name, evalc_t *field, eval_t *global, int statnum)
void SV_QCStatEval(int type, const char *name, evalc_t *field, eval_t *global, int statnum)
{
int i;
if (numqcstats == sizeof(qcstats)/sizeof(qcstats[0]))
@ -2023,7 +2070,7 @@ void SV_QCStatEval(int type, char *name, evalc_t *field, eval_t *global, int sta
memcpy(&qcstats[i].eval.c, field, sizeof(evalc_t));
}
void SV_QCStatGlobal(int type, char *globalname, int statnum)
void SV_QCStatGlobal(int type, const char *globalname, int statnum)
{
eval_t *glob;
@ -2259,7 +2306,7 @@ void SV_UpdateClientStats (client_t *client, int pnum, sizebuf_t *msg, client_fr
SV_CalcClientStats(client, statsi, statsf, statss);
m = MAX_QW_STATS;
if (client->fteprotocolextensions & (PEXT_HEXEN2|PEXT_CSQC))
if ((client->fteprotocolextensions & (PEXT_HEXEN2|PEXT_CSQC)) || client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7)
m = MAX_CL_STATS;
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
@ -2566,6 +2613,7 @@ qboolean SV_SendClientDatagram (client_t *client)
{
qbyte buf[MAX_OVERALLMSGLEN];
sizebuf_t msg;
size_t clientlimit;
unsigned int sentbytes;
unsigned int outframeseq = client->netchan.incoming_sequence; //this is so weird... but at least covers nq/qw sequence vs unreliables weirdness...
@ -2589,13 +2637,14 @@ qboolean SV_SendClientDatagram (client_t *client)
}
if (client->netchan.fragmentsize)
msg.maxsize = client->netchan.fragmentsize; //try not to overflow
clientlimit = client->netchan.fragmentsize; //try not to overflow
else if (client->protocol == SCP_NETQUAKE)
msg.maxsize = MAX_NQDATAGRAM; //vanilla client is limited.
clientlimit = MAX_NQDATAGRAM; //vanilla client is limited.
else
msg.maxsize = MAX_DATAGRAM; //udp limit, ish.
if (msg.maxsize > countof(buf))
msg.maxsize = countof(buf);
clientlimit = MAX_DATAGRAM; //udp limit, ish.
if (clientlimit > countof(buf))
clientlimit = countof(buf);
msg.maxsize = clientlimit - client->datagram.cursize;
if (sv.world.worldmodel && !client->controller)
{
@ -2638,7 +2687,7 @@ qboolean SV_SendClientDatagram (client_t *client)
// copy the accumulated multicast datagram
// for this client out to the message
if (!client->datagram.overflowed && msg.cursize + client->datagram.cursize <= msg.maxsize)
if (!client->datagram.overflowed && msg.cursize + client->datagram.cursize <= clientlimit)
{
SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
SZ_Clear (&client->datagram);

View File

@ -914,7 +914,7 @@ int SQL_NewServer(const char *driver, const char **paramstr)
return serverref;
}
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), char *str, queryrequest_t **reqout)
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), const char *str, queryrequest_t **reqout)
{
int qsize = Q_strlen(str);
queryrequest_t *qreq;

View File

@ -108,7 +108,7 @@ void SQL_CloseRequest(sqlserver_t *server, queryrequest_t *qres, qboolean force)
void SQL_CloseAllResults(sqlserver_t *server);
char *SQL_ReadField (sqlserver_t *server, queryresult_t *qres, int row, int col, qboolean fields, size_t *resultsize);
int SQL_NewServer(const char *driver, const char **paramstr);
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), char *str, queryrequest_t **reqout); //callback will be called on the main thread once the result is back
int SQL_NewQuery(sqlserver_t *server, qboolean (*callback)(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof), const char *str, queryrequest_t **reqout); //callback will be called on the main thread once the result is back
void SQL_Disconnect(sqlserver_t *server);
void SQL_Escape(sqlserver_t *server, const char *src, char *dst, int dstlen);
const char *SQL_Info(sqlserver_t *server);

View File

@ -988,6 +988,11 @@ void SV_SendClientPrespawnInfo(client_t *client)
ClientReliableWrite_Begin(client, svc_stufftext, 20 + strlen(svs.info));
ClientReliableWrite_String (client, va("fullserverinfo \"%s\"\n", svs.info) );
}
else if (sv.csqcdebug)
{
ClientReliableWrite_Begin(client, svc_stufftext, 22 + strlen(svs.info));
ClientReliableWrite_String (client, va("//fullserverinfo \"%s\"\n", svs.info) );
}
}
else if (client->prespawn_idx == 1)
{
@ -1831,13 +1836,16 @@ void SV_SpawnSpectator (void)
void SV_Begin_Core(client_t *split)
{ //this is the client-protocol-independant core, for q1/q2 gamecode
client_t *oh;
#ifdef HEXEN2
if (progstype == PROG_H2 && split->playerclass)
split->edict->xv->playerclass = split->playerclass; //make sure it's set the same as the userinfo
#endif
if (split->spawned)
return;
split->spawned = true;
#ifdef Q2SERVER
if (ge)
{
@ -3927,6 +3935,7 @@ static void SV_UpdateSeats(client_t *controller)
ClientReliableWrite_Angle(controller, cl->edict->v->angles[0]);
ClientReliableWrite_Angle(controller, cl->edict->v->angles[1]);
ClientReliableWrite_Angle(controller, 0);//cl->edict->v->angles[2]);
cl->edict->v->fixangle = 0;
}
else
{
@ -4852,7 +4861,7 @@ static void Cmd_AddSeat_f(void)
prev = cl;
count++;
}
if (!changed && count <= num)
changed = !!SV_AddSplit(host_client, Cmd_Argv(2), num);
}
@ -5352,6 +5361,8 @@ static void SVNQ_Spawn_f (void)
ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters);
}
//SV_Begin_Core(host_client);
ClientReliableWrite_Begin (host_client, svc_signonnum, 2);
ClientReliableWrite_Byte (host_client, 3);
@ -5367,58 +5378,7 @@ static void SVNQ_Begin_f (void)
host_client->state = cs_spawned;
if (host_client->istobeloaded)
{
sendangles = true;
host_client->istobeloaded = false;
}
else
{
if (host_client->spectator)
{
SV_SpawnSpectator ();
if (SpectatorConnect)
{
// copy spawn parms out of the client_t
SV_SpawnParmsToQC(host_client);
// call the spawn function
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player);
PR_ExecuteProgram (svprogfuncs, SpectatorConnect);
}
sv.spawned_observer_slots++;
}
else
{
sv.spawned_client_slots++;
// copy spawn parms out of the client_t
SV_SpawnParmsToQC(host_client);
sv.skipbprintclient = host_client;
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
Q1QVM_ClientConnect(host_client);
else
#endif
{
// call the spawn function
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player);
if (pr_global_ptrs->ClientConnect)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect);
sv.skipbprintclient = NULL;
// actually spawn the player
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player);
if (pr_global_ptrs->PutClientInServer)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer);
}
}
}
SV_Begin_Core(host_client);
// clear the net statistics, because connecting gives a bogus picture
host_client->netchan.frame_latency = 0;
@ -5964,7 +5924,7 @@ ucmd_t nqucmds[] =
SV_ExecuteUserCommand
==================
*/
void SV_ExecuteUserCommand (char *s, qboolean fromQC)
void SV_ExecuteUserCommand (const char *s, qboolean fromQC)
{
ucmd_t *u;
client_t *oldhost = host_client;
@ -7799,7 +7759,7 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
host_client = cl;
sv_player = cl->edict;
if (cl->state >= cs_connected)
if (cl->state < cs_connected)
return; // disconnect command
break;

View File

@ -809,13 +809,6 @@ qboolean SVQ2_InitGameProgs(void)
return false;
}
// unload anything we have now
if (!sv.world.worldmodel || (sv.world.worldmodel->fromgame == fg_quake || sv.world.worldmodel->fromgame == fg_halflife)) //we don't support q1 or hl maps yet... If ever.
{
SVQ2_ShutdownGameProgs();
return false;
}
if (ge)
{
SVQ2_InitWorld();

View File

@ -32,6 +32,7 @@ line of sight checks trace->crosscontent, but bullets don't
*/
extern cvar_t sv_compatiblehulls;
extern cvar_t sv_gameplayfix_nolinknonsolid;
typedef struct
{
@ -600,8 +601,8 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
w->worldmodel->funcs.FindTouchedLeafs(w->worldmodel, &ent->pvsinfo, ent->v->absmin, ent->v->absmax);
}
// if (ent->v->solid == SOLID_NOT && !sv_gameplayfix_nolinknonsolid.ival)
// return;
if (ent->v->solid == SOLID_NOT && !sv_gameplayfix_nolinknonsolid.ival)
return;
// find the first node that the ent's box crosses
if (ent->v->solid == SOLID_PORTAL)
@ -1084,6 +1085,7 @@ qboolean World_TransformedTrace (struct model_s *model, int hulloverride, frames
VectorCopy (end_l, trace->endpos);
result = Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, trace);
VectorAdd (trace->endpos, origin, trace->endpos);
trace->contents = FTECONTENTS_BODY;
}
else
result = false;
@ -1125,6 +1127,12 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
model = NULL;
VectorSubtract (ent->v->mins, maxs, boxmins);
VectorSubtract (ent->v->maxs, mins, boxmaxs);
if (hitcontentsmask & ((ent->v->solid == SOLID_CORPSE)?FTECONTENTS_CORPSE:FTECONTENTS_BODY))
hitcontentsmask = FTECONTENTS_CORPSE|FTECONTENTS_BODY;
else
hitcontentsmask = 0;
// if (ent->xv->geomtype == GEOMTYPE_CAPSULE && !hitmodel)
// model = World_CapsuleForBox(boxmins, boxmaxs);
// else
@ -1686,12 +1694,17 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip)
{
if (w->usesolidcorpse)
{
#if 1
// if (!(clip->hitcontentsmask & ((touch->v->solid == SOLID_CORPSE)?FTECONTENTS_CORPSE:FTECONTENTS_BODY)))
// continue;
#else
// don't clip corpse against character
if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE))
continue;
// don't clip character against corpse
if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE)
continue;
#endif
}
if (!((int)clip->passedict->xv->dimension_hit & (int)touch->xv->dimension_solid))
continue;
@ -1982,16 +1995,59 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
if (passedict->xv->hitcontentsmaski)
clip.hitcontentsmask = passedict->xv->hitcontentsmaski;
#ifndef NOLEGACY
else if (passedict->xv->dphitcontentsmask)
{
unsigned int nm=0, fl = passedict->xv->dphitcontentsmask;
if (fl & DPCONTENTS_SOLID)
nm |= FTECONTENTS_SOLID;
if (fl & DPCONTENTS_WATER)
nm |= FTECONTENTS_WATER;
if (fl & DPCONTENTS_SLIME)
nm |= FTECONTENTS_SLIME;
if (fl & DPCONTENTS_LAVA)
nm |= FTECONTENTS_LAVA;
if (fl & DPCONTENTS_SKY)
nm |= FTECONTENTS_SKY;
if (fl & DPCONTENTS_BODY)
nm |= FTECONTENTS_BODY;
if (fl & DPCONTENTS_CORPSE)
nm |= FTECONTENTS_CORPSE;
if (fl & DPCONTENTS_NODROP)
nm |= Q3CONTENTS_NODROP;
if (fl & DPCONTENTS_PLAYERCLIP)
nm |= FTECONTENTS_PLAYERCLIP;
if (fl & DPCONTENTS_MONSTERCLIP)
nm |= FTECONTENTS_MONSTERCLIP;
if (fl & DPCONTENTS_DONOTENTER)
nm |= Q3CONTENTS_DONOTENTER;
if (fl & DPCONTENTS_BOTCLIP)
nm |= Q3CONTENTS_BOTCLIP;
// if (fl & DPCONTENTS_OPAQUE)
// nm |= DPCONTENTS_OPAQUE;
clip.hitcontentsmask = nm;
}
#endif
/*#ifndef NOLEGACY
else if (passedict->xv->hitcontentsmask)
clip.hitcontentsmask = passedict->xv->hitcontentsmask;
#endif*/
else if (type & MOVE_NOMONSTERS)
clip.hitcontentsmask = MASK_WORLDSOLID; /*solid only to world*/
else if (maxs[0] - mins[0] > 0)
clip.hitcontentsmask = MASK_BOXSOLID; /*impacts playerclip*/
else if (passedict->v->solid == SOLID_SLIDEBOX)
{
if ((int)passedict->v->flags & FL_MONSTER)
clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY | FTECONTENTS_MONSTERCLIP; /*solid only to world*/
else if (maxs[0] - mins[0] > 0)
clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY | FTECONTENTS_PLAYERCLIP; /*impacts playerclip*/
else
clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY; //slidebox passes through corpses
}
else if (passedict->v->solid == SOLID_CORPSE)
clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY; //corpses ignore corpses
else if (passedict->v->solid == SOLID_TRIGGER)
clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY; //triggers ignore corpses too, apparently
else
clip.hitcontentsmask = MASK_POINTSOLID; /*ignores playerclip but hits everything else*/
clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY | FTECONTENTS_CORPSE; //regular projectiles.
clip.capsule = (passedict->xv->geomtype == GEOMTYPE_CAPSULE);
if (type & MOVE_OTHERONLY)
@ -2016,6 +2072,9 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
if (type & MOVE_MISSILE)
{
if (type & MOVE_NOMONSTERS)
return clip.trace; //not sure why you'd really want this, but for the sake of dp compat...
for (i=0 ; i<3 ; i++)
{
clip.mins2[i] = -15;
@ -2154,8 +2213,8 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
// if (clip.trace.startsolid)
// clip.trace.fraction = 0;
if (!clip.trace.ent)
return clip.trace;
// if (!clip.trace.ent)
// return clip.trace;
return clip.trace;
}

View File

@ -60,6 +60,9 @@ void main ()
invsurface[2] = v_normal;
#endif
tc = v_texcoord;
#ifdef FLOW
tc.s += e_time * -0.5;
#endif
#ifdef VERTEXLIT
#ifdef LIGHTSTYLED
//FIXME, only one colour.

View File

@ -158,7 +158,7 @@ void SW_VID_UpdateViewport(wqcom_t *com);
void SW_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean SW_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean SW_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips);
void SW_DestroyTexture (texid_t tex);

View File

@ -35,7 +35,7 @@ void SW_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3
//always nearest...
}
qboolean SW_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
qboolean SW_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
{
swimage_t *img;
int i;

View File

@ -569,6 +569,10 @@ LONG WINAPI MainWndProc (
// raw input handling
INS_RawInput_Read((HANDLE)lParam);
break;
case WM_DEVICECHANGE:
COM_AddWork(WG_MAIN, INS_DeviceChanged, NULL, NULL, uMsg, 0);
lRet = TRUE;
break;
/* case WM_DISPLAYCHANGE:
if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode)
{

View File

@ -194,6 +194,19 @@ enum
VK_BUFF_MAX
};
typedef struct
{ //there should be only one copy of this struct for each thread that renders anything in vulkan.
//descriptor sets are: 0) entity+light 1) batch textures + pass textures
VkDescriptorSet descriptorsets[1];
//commandbuffer state, to avoid redundant state changes.
VkPipeline activepipeline;
float depthrange;
} vkrendercontext_t;
typedef struct
{
unsigned int inited;
@ -243,11 +256,7 @@ typedef struct
texid_t tex_refraction; //separate from rt_reflection, because $reasons
texid_t tex_ripplemap;
//descriptor sets are: 0) entity+light 1) batch textures + pass textures
VkDescriptorSet descriptorsets[1];
//commandbuffer state, to avoid redundant state changes.
VkPipeline activepipeline;
vkrendercontext_t rc;
struct shadowmaps_s
{
@ -266,8 +275,6 @@ typedef struct
} shadow[2]; //omni, spot
texid_t currentshadowmap;
float depthrange;
VkDescriptorSetLayout textureLayout;
} vkbackend_t;
@ -1578,7 +1585,7 @@ void VKBE_RestartFrame(void)
vk.dynbuf[i]->offset = vk.dynbuf[i]->flushed = 0;
}
shaderstate.activepipeline = VK_NULL_HANDLE;
shaderstate.rc.activepipeline = VK_NULL_HANDLE;
vk.descpool = vk.frame->descpools;
if (vk.descpool)
{
@ -2370,7 +2377,13 @@ static void tcmod(const tcmod_t *tcmod, int cnt, const float *src, float *dst, c
}
break;
case SHADER_TCMOD_PAGE:
default:
for (j = 0; j < cnt; j++, dst += 2, src+=2)
{
dst[0] = src[0];
dst[1] = src[1];
}
break;
}
}
@ -2988,7 +3001,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
if (err)
{
shaderstate.activepipeline = VK_NULL_HANDLE;
shaderstate.rc.activepipeline = VK_NULL_HANDLE;
if (err != VK_ERROR_INVALID_SHADER_NV)
Sys_Error("Error %i creating pipeline for %s. Check spir-v modules / drivers.\n", err, shaderstate.curshader->name);
else
@ -2996,7 +3009,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
return;
}
vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline);
vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.rc.activepipeline=pipe->pipeline);
}
static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int blendflags, unsigned int permu)
{
@ -3021,11 +3034,11 @@ static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int
if (pipe->blendbits == blendflags)
if (pipe->permu == permu)
{
if (pipe->pipeline != shaderstate.activepipeline)
if (pipe->pipeline != shaderstate.rc.activepipeline)
{
shaderstate.activepipeline = pipe->pipeline;
if (shaderstate.activepipeline)
vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline);
shaderstate.rc.activepipeline = pipe->pipeline;
if (shaderstate.rc.activepipeline)
vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.rc.activepipeline);
}
return;
}
@ -3088,13 +3101,13 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
perm &= p->supportedpermutations;
BE_BindPipeline(p, shaderbits, VKBE_ApplyShaderBits(pass->shaderbits), perm);
if (!shaderstate.activepipeline)
if (!shaderstate.rc.activepipeline)
return false; //err, something bad happened.
//most gpus will have a fairly low descriptor set limit of 4 (this is the minimum required)
//that isn't enough for all our textures, so we need to make stuff up as required.
{
VkDescriptorSet set = shaderstate.descriptorsets[0] = vk.khr_push_descriptor?VK_NULL_HANDLE:VKBE_TempDescriptorSet(p->desclayout);
VkDescriptorSet set = shaderstate.rc.descriptorsets[0] = vk.khr_push_descriptor?VK_NULL_HANDLE:VKBE_TempDescriptorSet(p->desclayout);
VkWriteDescriptorSet descs[MAX_TMUS], *desc = descs;
VkDescriptorImageInfo imgs[MAX_TMUS], *img = imgs;
unsigned int i;
@ -3182,7 +3195,7 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
vkUpdateDescriptorSets(vk.device, desc-descs, descs, 0, NULL);
}
if (!vk.khr_push_descriptor)
vkCmdBindDescriptorSets(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, countof(shaderstate.descriptorsets), shaderstate.descriptorsets, 0, NULL);
vkCmdBindDescriptorSets(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, countof(shaderstate.rc.descriptorsets), shaderstate.rc.descriptorsets, 0, NULL);
RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount);
RQuantAdd(RQUANT_DRAWS, 1);
@ -4437,10 +4450,10 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
Vector2Set(cbe->pad7, 0, 0);
ndr = (e->flags & RF_DEPTHHACK)?0.333:1;
if (ndr != shaderstate.depthrange)
if (ndr != shaderstate.rc.depthrange)
{
VkViewport viewport;
shaderstate.depthrange = ndr;
shaderstate.rc.depthrange = ndr;
viewport.x = r_refdef.pxrect.x;
viewport.y = r_refdef.pxrect.y;
@ -4940,7 +4953,7 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
if (vk.rendertarg)
vkCmdEndRenderPass(vk.rendertarg->cbuf);
#else
shaderstate.activepipeline = VK_NULL_HANDLE;
shaderstate.rc.activepipeline = VK_NULL_HANDLE;
targ->cbuf = VK_AllocFrameCBuf();
{
@ -4978,7 +4991,7 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
viewport.width = r_refdef.pxrect.width;
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange;
viewport.maxDepth = shaderstate.rc.depthrange;
vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
wrekt.offset.x = viewport.x;
wrekt.offset.y = viewport.y;
@ -5000,7 +5013,7 @@ void VKBE_RT_End(struct vk_rendertarg *targ)
#if 0
#else
shaderstate.activepipeline = VK_NULL_HANDLE;
shaderstate.rc.activepipeline = VK_NULL_HANDLE;
vkCmdEndRenderPass(targ->cbuf);
vkEndCommandBuffer(targ->cbuf);
@ -6087,7 +6100,7 @@ void VKBE_DoneShadows(void)
viewport.width = r_refdef.pxrect.width;
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange;
viewport.maxDepth = shaderstate.rc.depthrange;
vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
}
@ -6144,7 +6157,7 @@ void VKBE_DrawWorld (batch_t **worldbatches)
shaderstate.curentity = NULL;
shaderstate.depthrange = 0;
shaderstate.rc.depthrange = 0;
if (!r_refdef.recurse)
{

View File

@ -1120,7 +1120,7 @@ static void VK_TextureLoaded(void *ctx)
}
#endif
}
qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
{
#ifdef USE_STAGING_BUFFERS
VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
@ -1138,22 +1138,23 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
uint32_t blocksize;
uint32_t blockbytes;
uint32_t layers;
uint32_t mipcount = mips->mipcount;
if (mips->type != PTI_2D && mips->type != PTI_CUBEMAP)
return false;
if (!mips->mipcount || mips->mip[0].width == 0 || mips->mip[0].height == 0)
if (!mipcount || mips->mip[0].width == 0 || mips->mip[0].height == 0)
return false;
layers = (mips->type == PTI_CUBEMAP)?6:1;
if (layers == 1 && mips->mipcount > 1)
if (layers == 1 && mipcount > 1)
{ //npot mipmapped textures are awkward.
//vulkan floors.
for (i = 1; i < mips->mipcount; i++)
for (i = 1; i < mipcount; i++)
{
if (mips->mip[i].width != (mips->mip[i-1].width>>1) ||
mips->mip[i].height != (mips->mip[i-1].height>>1))
if (mips->mip[i].width != max(1,(mips->mip[i-1].width>>1)) ||
mips->mip[i].height != max(1,(mips->mip[i-1].height>>1)))
{ //okay, this mip looks like it was sized wrongly. this can easily happen with dds files.
mips->mipcount = i;
mipcount = i;
break;
}
}
@ -1212,7 +1213,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
}
fence = VK_FencedBegin(VK_TextureLoaded, sizeof(*fence));
fence->mips = mips->mipcount;
fence->mips = mipcount;
vkloadcmd = fence->w.cbuf;
//create our target image
@ -1222,7 +1223,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
if (tex->vkimage->width != mips->mip[0].width ||
tex->vkimage->height != mips->mip[0].height ||
tex->vkimage->layers != layers ||
tex->vkimage->mipcount != mips->mipcount ||
tex->vkimage->mipcount != mipcount ||
tex->vkimage->encoding != mips->encoding ||
tex->vkimage->type != mips->type)
{
@ -1251,7 +1252,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
imgbarrier.image = target.image;
imgbarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imgbarrier.subresourceRange.baseMipLevel = 0;
imgbarrier.subresourceRange.levelCount = mips->mipcount/layers;
imgbarrier.subresourceRange.levelCount = mipcount/layers;
imgbarrier.subresourceRange.baseArrayLayer = 0;
imgbarrier.subresourceRange.layerCount = layers;
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@ -1264,7 +1265,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
}
else
{
target = VK_CreateTexture2DArray(mips->mip[0].width, mips->mip[0].height, layers, mips->mipcount/layers, mips->encoding, mips->type, !!(tex->flags&IF_RENDERTARGET));
target = VK_CreateTexture2DArray(mips->mip[0].width, mips->mip[0].height, layers, mipcount/layers, mips->encoding, mips->type, !!(tex->flags&IF_RENDERTARGET));
{
//images have weird layout representations.
@ -1275,7 +1276,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
imgbarrier.image = target.image;
imgbarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imgbarrier.subresourceRange.baseMipLevel = 0;
imgbarrier.subresourceRange.levelCount = mips->mipcount/layers;
imgbarrier.subresourceRange.levelCount = mipcount/layers;
imgbarrier.subresourceRange.baseArrayLayer = 0;
imgbarrier.subresourceRange.layerCount = layers;
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@ -1290,7 +1291,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
#ifdef USE_STAGING_BUFFERS
//figure out how big our staging buffer needs to be
bci.size = 0;
for (i = 0; i < mips->mipcount; i++)
for (i = 0; i < mipcount; i++)
{
uint32_t blockwidth = (mips->mip[i].width+blocksize-1) / blocksize;
uint32_t blockheight = (mips->mip[i].height+blocksize-1) / blocksize;
@ -1318,7 +1319,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
Sys_Error("Unable to map staging image\n");
bci.size = 0;
for (i = 0; i < mips->mipcount; i++)
for (i = 0; i < mipcount; i++)
{
VkImageSubresource subres = {0};
VkBufferImageCopy region;
@ -1338,8 +1339,8 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
region.bufferRowLength = blockwidth*blocksize;//*blockbytes;
region.bufferImageHeight = blockheight*blocksize;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = i%(mips->mipcount/layers);
region.imageSubresource.baseArrayLayer = i/(mips->mipcount/layers);
region.imageSubresource.mipLevel = i%(mipcount/layers);
region.imageSubresource.baseArrayLayer = i/(mipcount/layers);
region.imageSubresource.layerCount = 1;
region.imageOffset.x = 0;
region.imageOffset.y = 0;
@ -1355,7 +1356,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
vkUnmapMemory(vk.device, fence->stagingmemory);
#else
//create the staging images and fill them
for (i = 0; i < mips->mipcount; i++)
for (i = 0; i < mipcount; i++)
{
VkImageSubresource subres = {0};
VkSubresourceLayout layout;
@ -1393,8 +1394,8 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
region.srcOffset.y = 0;
region.srcOffset.z = 0;
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.dstSubresource.mipLevel = i%(mips->mipcount/layers);
region.dstSubresource.baseArrayLayer = i/(mips->mipcount/layers);
region.dstSubresource.mipLevel = i%(mipcount/layers);
region.dstSubresource.baseArrayLayer = i/(mipcount/layers);
region.dstSubresource.layerCount = 1;
region.dstOffset.x = 0;
region.dstOffset.y = 0;
@ -1419,7 +1420,7 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips)
imgbarrier.image = target.image;
imgbarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imgbarrier.subresourceRange.baseMipLevel = 0;
imgbarrier.subresourceRange.levelCount = mips->mipcount/layers;
imgbarrier.subresourceRange.levelCount = mipcount/layers;
imgbarrier.subresourceRange.baseArrayLayer = 0;
imgbarrier.subresourceRange.layerCount = layers;
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;

View File

@ -376,7 +376,6 @@ struct pipeline_s
uint32_t vk_find_memory_try(uint32_t typeBits, VkFlags requirements_mask);
uint32_t vk_find_memory_require(uint32_t typeBits, VkFlags requirements_mask);
qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
void VK_DoPresent(struct vkframe *theframe);
qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*createSurface)(void), void (*dopresent)(struct vkframe *theframe));
@ -458,7 +457,7 @@ void VK_Draw_Init(void);
void VK_Draw_Shutdown(void);
void VK_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips);
void VK_DestroyTexture (texid_t tex);
void VK_DestroyVkTexture (vk_image_t *img);

View File

@ -494,10 +494,10 @@ void EZHud_UseNquake_f(void)
struct
{
xcommand_t cmd;
char *name;
const char *name;
} concmds[128];
int numconcmds;
qboolean Cmd_AddCommand (char *funcname, xcommand_t function)
qboolean Cmd_AddCommand (const char *funcname, xcommand_t function)
{
if (numconcmds < sizeof(concmds)/sizeof(concmds[0]))
{