misc fixes and tweaks:

added //it stuffcmd.
now parsing //wps stuffcmds for ezhud use.
rework worker threads a little so that the main thread is no longer guaranteed to be stalled at least once. This speeds up load times a little.
fix nq server player counts in the server browser.
fix switching from/to spectator mode from destroying frag counts.
tweak custom bf args a little.
fix issue with player names starting with char 0x80.
fix menu.dat not loading.
attempt to fix flush lag on windows.
some fixes for stencil shadows.
try to fix public builds not knowing their svn revision. this should fix autoupdates.
added global_gravitydir vector, for mods that want to be really weird. doesn't clear onground flags however.
reworked the status command a little to attempt to report bursts a little better.
fix multicasts missing in mvds issue.
fix illegible server message with dpp7 downloads.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4992 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-10-27 15:20:15 +00:00
parent 3e0e4c43a8
commit 9000f497ec
56 changed files with 1088 additions and 339 deletions

View file

@ -15,7 +15,7 @@ else
BASE_DIR:=$(realpath .) BASE_DIR:=$(realpath .)
endif endif
SVNREVISION:=-DSVNREVISION=$(shell test -d .svn && svnversion || echo -) SVNREVISION:=-DSVNREVISION=$(shell test -d $(BASE_DIR)/../.svn && svnversion $(BASE_DIR) || echo -)
WHOAMI:=$(shell whoami) WHOAMI:=$(shell whoami)

View file

@ -1517,6 +1517,8 @@ void CLNQ_ParseEntity(unsigned int bits)
entity_state_t *base; entity_state_t *base;
packet_entities_t *pack; packet_entities_t *pack;
qboolean isnehahra = false;//(cls.protocol_nq == CPNQ_ID && cls.demoplayback);
if (cls.signon == 4 - 1) if (cls.signon == 4 - 1)
{ // first update is the final signon stage { // first update is the final signon stage
cls.signon = 4; cls.signon = 4;
@ -1530,15 +1532,19 @@ void CLNQ_ParseEntity(unsigned int bits)
i = MSG_ReadByte (); i = MSG_ReadByte ();
bits |= (i<<8); bits |= (i<<8);
} }
if (bits & DPU_EXTEND1)
if (!isnehahra)
{ {
i = MSG_ReadByte (); if (bits & DPU_EXTEND1)
bits |= (i<<16); {
} i = MSG_ReadByte ();
if (bits & DPU_EXTEND2) bits |= (i<<16);
{ }
i = MSG_ReadByte (); if (bits & DPU_EXTEND2)
bits |= (i<<24); {
i = MSG_ReadByte ();
bits |= (i<<24);
}
} }
if (bits & NQU_LONGENTITY) if (bits & NQU_LONGENTITY)
@ -1603,7 +1609,21 @@ void CLNQ_ParseEntity(unsigned int bits)
if (bits & NQU_ANGLE3) if (bits & NQU_ANGLE3)
state->angles[2] = MSG_ReadAngle(); state->angles[2] = MSG_ReadAngle();
if (cls.protocol_nq == CPNQ_FITZ666) if (isnehahra)
{
if (bits & DPU_EXTEND1) //U_TRANS
{
float tmp = MSG_ReadFloat();
float alpha = MSG_ReadFloat();
if (tmp == 2)
{
if (MSG_ReadFloat() > 0.5)
state->effects |= EF_FULLBRIGHT;
}
state->trans = bound(0, 255 * alpha, 255);
}
}
else if (cls.protocol_nq == CPNQ_FITZ666)
{ {
if (bits & FITZU_ALPHA) if (bits & FITZU_ALPHA)
state->trans = MSG_ReadByte(); state->trans = MSG_ReadByte();
@ -1711,7 +1731,8 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt
if ((ps->dpflags & RENDER_EXTERIORMODEL) || r_refdef.playerview->viewentity == ps->number) if ((ps->dpflags & RENDER_EXTERIORMODEL) || r_refdef.playerview->viewentity == ps->number)
ent->flags |= RF_EXTERNALMODEL; ent->flags |= RF_EXTERNALMODEL;
if (ent->playerindex == -1 && ps->colormap > 0 && ps->colormap <= cl.allocated_client_slots) //hack for xonotic.
if ((ent->flags & RF_WEAPONMODEL) && ent->playerindex == -1 && ps->colormap > 0 && ps->colormap <= cl.allocated_client_slots)
{ {
ent->playerindex = ps->colormap-1; ent->playerindex = ps->colormap-1;
ent->topcolour = cl.players[ent->playerindex].ttopcolor; ent->topcolour = cl.players[ent->playerindex].ttopcolor;
@ -1828,7 +1849,7 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt
parent[10] = axis[2][2]; parent[10] = axis[2][2];
parent[11] = org[2]; parent[11] = org[2];
R_ConcatTransforms((void*)old, (void*)parent, (void*)result); R_ConcatTransforms((void*)parent, (void*)old, (void*)result);
ent->axis[0][0] = result[0]; ent->axis[0][0] = result[0];
ent->axis[1][0] = result[1]; ent->axis[1][0] = result[1];
@ -3436,11 +3457,14 @@ void CL_LinkPacketEntities (void)
else else
{ {
timerlink = &(*timerlink)->next; timerlink = &(*timerlink)->next;
if (timer->entnum >= cl.maxlerpents) if (timer->entnum)
continue; {
le = &cl.lerpents[timer->entnum]; if (timer->entnum >= cl.maxlerpents)
if (le->sequence != cl.lerpentssequence) continue;
continue; le = &cl.lerpents[timer->entnum];
if (le->sequence != cl.lerpentssequence)
continue;
}
R_AddItemTimer(timer->origin, cl.time*90 + timer->origin[0] + timer->origin[1] + timer->origin[2], timer->radius, (cl.time - timer->start) / timer->duration); R_AddItemTimer(timer->origin, cl.time*90 + timer->origin[0] + timer->origin[1] + timer->origin[2], timer->radius, (cl.time - timer->start) / timer->duration);
} }
} }

View file

@ -298,7 +298,7 @@ void IN_JumpDown (void)
KeyDown(&in_up); KeyDown(&in_up);
else else
#endif #endif
if (condition && cl.spectator && !CAM_ISLOCKED(&cl.playerview[pnum])) if (condition && cl.spectator && cl.playerview[pnum].cam_state == CAM_FREECAM)
KeyDown(&in_up); KeyDown(&in_up);
else else
KeyDown(&in_jump); KeyDown(&in_jump);
@ -2026,7 +2026,11 @@ void CL_SendCmd (double frametime, qboolean mainloop)
// deliver the message // deliver the message
// //
cls.netchan.dupe = cl_c2sdupe.ival; cls.netchan.dupe = cl_c2sdupe.ival;
Netchan_Transmit (&cls.netchan, buf.cursize, buf.data, 2500); Netchan_Transmit (&cls.netchan, buf.cursize, buf.data, 2500);
//don't bank too much, because that results in banking speedcheats
if (msecs > 200)
msecs = 200;
if (cls.netchan.fatal_error) if (cls.netchan.fatal_error)
{ {

View file

@ -4890,7 +4890,11 @@ double Host_Frame (double time)
CL_ProgressDemoTime(); CL_ProgressDemoTime();
hadwork = haswork; hadwork = haswork;
} }
cl.stillloading = cl.sendprespawn || (cls.state < ca_active && worker_flush.ival && COM_HasWork()); cl.stillloading = cl.sendprespawn
#ifdef LOADERTHREAD
|| (cls.state < ca_active && worker_flush.ival && COM_HasWork())
#endif
;
COM_MainThreadWork(); COM_MainThreadWork();

View file

@ -5725,8 +5725,71 @@ void CL_ParsePrint(char *msg, int level)
} }
} }
static void CL_ParseWeaponStats(void)
{
#ifdef QUAKEHUD
int pl = atoi(Cmd_Argv(0));
char *wname = Cmd_Argv(1);
unsigned int total = strtoul(Cmd_Argv(2), NULL, 0);
unsigned int hit = strtoul(Cmd_Argv(3), NULL, 0);
unsigned int idx;
void CL_ParseTeamInfo(void) if (pl >= cl.allocated_client_slots)
return;
for (idx = 0; idx < countof(cl.players[pl].weaponstats); idx++)
{
if (!strcmp(cl.players[pl].weaponstats[idx].wname, wname) || !*cl.players[pl].weaponstats[idx].wname)
{
Q_strncpyz(cl.players[pl].weaponstats[idx].wname, wname, sizeof(cl.players[pl].weaponstats[idx].wname));
cl.players[pl].weaponstats[idx].total = total;
cl.players[pl].weaponstats[idx].hit = hit;
return;
}
}
#endif
}
static void CL_ParseItemTimer(void)
{
float timeout = atof(Cmd_Argv(0));
vec3_t org = { atof(Cmd_Argv(1)),
atof(Cmd_Argv(2)),
atof(Cmd_Argv(3))};
float radius = atof(Cmd_Argv(4));
//unsigned int rgb = strtoul(Cmd_Argv(5), NULL, 16);
char *timername = Cmd_Argv(6);
unsigned int entnum = strtoul(Cmd_Argv(7), NULL, 0);
struct itemtimer_s *timer;
if (!timeout)
timeout = FLT_MAX;
if (!radius)
radius = 32;
for (timer = cl.itemtimers; timer; timer = timer->next)
{
if (VectorCompare(timer->origin, org) && timer->entnum == entnum)
break;
}
if (!timer)
{ //didn't find it.
timer = Z_Malloc(sizeof(*timer));
timer->next = cl.itemtimers;
cl.itemtimers = timer;
}
VectorCopy(org, timer->origin);
timer->start = cl.time;
timer->duration = timeout;
timer->radius = radius;
timer->duration = timeout;
timer->entnum = entnum;
timer->start = cl.time;
timer->end = cl.time + timer->duration;
}
static void CL_ParseTeamInfo(void)
{ {
unsigned int pidx = atoi(Cmd_Argv(1)); unsigned int pidx = atoi(Cmd_Argv(1));
vec3_t org = vec3_t org =
@ -5828,8 +5891,8 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
} }
else if (!strncmp(stufftext, "//wps ", 5)) else if (!strncmp(stufftext, "//wps ", 5))
{ {
//weapon stats, eg: Cmd_TokenizeString(stufftext+5, false, false);
//wps CLIENT WNAME attacks hits CL_ParseWeaponStats();
} }
else if (!strncmp(stufftext, "//kickfile ", 11)) else if (!strncmp(stufftext, "//kickfile ", 11))
{ {
@ -5838,6 +5901,11 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
if (FS_FLocateFile(Cmd_Argv(1), FSLF_IFFOUND, &loc)) if (FS_FLocateFile(Cmd_Argv(1), FSLF_IFFOUND, &loc))
Con_Printf("You have been kicked due to the file \"%s\" being modified.\n", Cmd_Argv(1)); Con_Printf("You have been kicked due to the file \"%s\" being modified.\n", Cmd_Argv(1));
} }
else if (!strncmp(stufftext, "//it ", 5))
{
Cmd_TokenizeString(stufftext+5, false, false);
CL_ParseItemTimer();
}
#ifdef PLUGINS #ifdef PLUGINS
else if (!strncmp(stufftext, "//tinfo ", 8)) else if (!strncmp(stufftext, "//tinfo ", 8))
{ {
@ -7002,6 +7070,11 @@ void CLNQ_ParseServerMessage (void)
CLNQ_ParseProtoVersion(); CLNQ_ParseProtoVersion();
break; break;
case svc_serverdata: case svc_serverdata:
if (*printtext)
{ //work around a missing-eol proquake bug.
CL_PrintStandardMessage(printtext, PRINT_HIGH);
printtext[0] = 0;
}
Cbuf_Execute (); // make sure any stuffed commands are done Cbuf_Execute (); // make sure any stuffed commands are done
CLNQ_ParseServerData (); CLNQ_ParseServerData ();
break; break;

View file

@ -370,6 +370,32 @@ static qintptr_t VARGS Plug_Draw_StringH(void *offset, quintptr_t mask, const qi
return 0; return 0;
} }
static qintptr_t VARGS Plug_Draw_StringWidth(void *offset, quintptr_t mask, const qintptr_t *arg)
{
qintptr_t ret;
float h = VM_FLOAT(arg[0]);
unsigned int flags = VM_LONG(arg[1]);
char *instr = VM_POINTER(arg[2]);
conchar_t buffer[2048], *str, cmask = CON_WHITEMASK;
unsigned int parseflags = 0;
float px,py;
if (qrenderer == QR_NONE)
return 0;
if (flags & 1)
cmask |= CON_2NDCHARSETTEXT;
if (flags & 2)
parseflags |= PFS_FORCEUTF8;
str = COM_ParseFunString(CON_WHITEMASK, instr, buffer, sizeof(buffer), parseflags);
Font_BeginScaledString(font_default, 0, 0, h, h, &px, &py);
px = Font_LineScaleWidth(buffer, str);
Font_EndString(NULL);
//put it back in virtual space
VM_FLOAT(ret) = (px*(float)vid.width) / (float)vid.rotpixelwidth;
return ret;
}
static qintptr_t VARGS Plug_Draw_Fill(void *offset, quintptr_t mask, const qintptr_t *arg) static qintptr_t VARGS Plug_Draw_Fill(void *offset, quintptr_t mask, const qintptr_t *arg)
{ {
float x, y, width, height; float x, y, width, height;
@ -791,6 +817,38 @@ static qintptr_t VARGS Plug_GetTeamInfo(void *offset, quintptr_t mask, const qin
return VM_LONG(count); return VM_LONG(count);
} }
#endif #endif
#ifdef QUAKEHUD
static qintptr_t VARGS Plug_GetWeaponStats(void *offset, quintptr_t mask, const qintptr_t *arg)
{
int self = VM_LONG(arg[0]);
struct wstats_s *result = VM_POINTER(arg[1]);
size_t maxresults = VM_LONG(arg[2]);
int count = 0;
int i;
if (VM_OOB(arg[0], maxresults*sizeof(*result)))
return 0;
//FIXME: we should support some way to clear this to 0 again, other than nosave.
Cvar_Get("wpsx", "1", CVAR_USERINFO|CVAR_NOSAVE, "Hacks because ktx sucks. Must be 1 in order to receive weapon stats information in ktx.");
if (self < 0)
{
unsigned int seat = (unsigned)(-self-1)%MAX_SPLITS;
self = cl.playerview[seat].playernum;
if (cl.playerview[seat].cam_state != CAM_FREECAM)
self = cl.playerview[seat].cam_spec_track;
}
if (self < 0)
return 0;
if (maxresults > countof(cl.players[i].weaponstats))
maxresults = countof(cl.players[i].weaponstats);
memcpy(result, cl.players[self].weaponstats, sizeof(*result) * maxresults);
return VM_LONG(maxresults);
}
#endif
static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg) static qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg)
{ {
@ -1158,6 +1216,7 @@ void Plug_Client_Init(void)
Plug_RegisterBuiltin("Draw_CharacterH", Plug_Draw_CharacterH, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_CharacterH", Plug_Draw_CharacterH, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_String", Plug_Draw_String, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_String", Plug_Draw_String, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_StringH", Plug_Draw_StringH, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_StringH", Plug_Draw_StringH, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_StringWidth", Plug_Draw_StringWidth, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Line", Plug_Draw_Line, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_Line", Plug_Draw_Line, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("Draw_Colourp", Plug_Draw_ColourP, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("Draw_Colourp", Plug_Draw_ColourP, PLUG_BIF_NEEDSRENDERER);
@ -1181,6 +1240,7 @@ void Plug_Client_Init(void)
#ifdef QUAKEHUD #ifdef QUAKEHUD
Plug_RegisterBuiltin("GetTeamInfo", Plug_GetTeamInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetTeamInfo", Plug_GetTeamInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetWeaponStats", Plug_GetWeaponStats, PLUG_BIF_NEEDSRENDERER);
#endif #endif
Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER);

View file

@ -370,9 +370,18 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state
split = *u; split = *u;
split.msec = u->msec / 2; //special care to avoid forgetting an msec here and there split.msec = u->msec / 2; //special care to avoid forgetting an msec here and there
CL_PredictUsercmd (pnum, entnum, from, &temp, &split);
split.msec = u->msec - split.msec; if (split.msec > 500)
CL_PredictUsercmd (pnum, entnum, &temp, to, &split); {
split.msec = 500;
CL_PredictUsercmd (pnum, entnum, from, to, &split);
}
else
{
CL_PredictUsercmd (pnum, entnum, from, &temp, &split);
split.msec = u->msec - split.msec;
CL_PredictUsercmd (pnum, entnum, &temp, to, &split);
}
return; return;
} }
if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED) if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED)
@ -972,7 +981,7 @@ void CL_PredictMovePNum (int seat)
if (!cl.ackedmovesequence) if (!cl.ackedmovesequence)
nopred = true; nopred = true;
else if (cl.movesequence - cl.ackedmovesequence >= UPDATE_BACKUP-1) else if (cl.movesequence - cl.ackedmovesequence >= UPDATE_BACKUP-1)
return; nopred = true;
//these things also force-disable prediction //these things also force-disable prediction
if ((cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV) || if ((cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV) ||

View file

@ -1889,6 +1889,8 @@ void SCR_ImageName (char *mapname)
if (qrenderer) if (qrenderer)
{ {
R_LoadHiResTexture(levelshotname, NULL, IF_NOWORKER|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP);
if (!R_GetShaderSizes(R2D_SafeCachePic (levelshotname), NULL, NULL, true)) if (!R_GetShaderSizes(R2D_SafeCachePic (levelshotname), NULL, NULL, true))
{ {
*levelshotname = '\0'; *levelshotname = '\0';

View file

@ -200,6 +200,15 @@ typedef struct player_info_s
int prevcount; int prevcount;
#ifdef QUAKEHUD
struct wstats_s
{
char wname[16];
unsigned int hit;
unsigned int total;
} weaponstats[16];
#endif
int stats[MAX_CL_STATS]; int stats[MAX_CL_STATS];
float statsf[MAX_CL_STATS]; float statsf[MAX_CL_STATS];
} player_info_t; } player_info_t;

View file

@ -60,6 +60,9 @@ float con_cursorspeed = 4;
cvar_t con_numnotifylines = SCVAR("con_notifylines","4"); //max lines to show cvar_t con_numnotifylines = SCVAR("con_notifylines","4"); //max lines to show
cvar_t con_notifytime = SCVAR("con_notifytime","3"); //seconds cvar_t con_notifytime = SCVAR("con_notifytime","3"); //seconds
cvar_t con_notify_x = SCVAR("con_notify_x","0");
cvar_t con_notify_y = SCVAR("con_notify_y","0");
cvar_t con_notify_w = SCVAR("con_notify_w","1");
cvar_t con_centernotify = SCVAR("con_centernotify", "0"); cvar_t con_centernotify = SCVAR("con_centernotify", "0");
cvar_t con_displaypossibilities = SCVAR("con_displaypossibilities", "1"); cvar_t con_displaypossibilities = SCVAR("con_displaypossibilities", "1");
cvar_t con_maxlines = SCVAR("con_maxlines", "1024"); cvar_t con_maxlines = SCVAR("con_maxlines", "1024");
@ -622,8 +625,11 @@ void Con_Init (void)
// //
// register our commands // register our commands
// //
Cvar_Register (&con_notifytime, "Console controls");
Cvar_Register (&con_centernotify, "Console controls"); Cvar_Register (&con_centernotify, "Console controls");
Cvar_Register (&con_notifytime, "Console controls");
Cvar_Register (&con_notify_x, "Console controls");
Cvar_Register (&con_notify_y, "Console controls");
Cvar_Register (&con_notify_w, "Console controls");
Cvar_Register (&con_numnotifylines, "Console controls"); Cvar_Register (&con_numnotifylines, "Console controls");
Cvar_Register (&con_displaypossibilities, "Console controls"); Cvar_Register (&con_displaypossibilities, "Console controls");
Cvar_Register (&cl_chatmode, "Console controls"); Cvar_Register (&cl_chatmode, "Console controls");
@ -1036,6 +1042,8 @@ void Con_Footerf(console_t *con, qboolean append, char *fmt, ...)
conline_t *newf; conline_t *newf;
if (!con) if (!con)
con = con_current; con = con_current;
if (!con)
return;
va_start (argptr,fmt); va_start (argptr,fmt);
vsnprintf (msg,sizeof(msg)-1, fmt,argptr); vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
@ -1422,7 +1430,9 @@ void Con_DrawNotify (void)
con_main.flags |= CONF_NOTIFY; con_main.flags |= CONF_NOTIFY;
/*keep the main console up to date*/ /*keep the main console up to date*/
con_main.notif_l = con_numnotifylines.ival; con_main.notif_l = con_numnotifylines.ival;
con_main.notif_w = 1; con_main.notif_w = con_notify_w.value;
con_main.notif_x = con_notify_x.value;
con_main.notif_y = con_notify_y.value;
con_main.notif_t = con_notifytime.value; con_main.notif_t = con_notifytime.value;
if (con_chat) if (con_chat)
@ -1540,7 +1550,7 @@ static int Con_DrawProgress(int left, int right, int y)
char *progresstext = NULL; char *progresstext = NULL;
char *txt; char *txt;
int x, tw; int x, tw;
int i, j; int i;
int barwidth, barleft; int barwidth, barleft;
float progresspercent = 0; float progresspercent = 0;
unsigned int codeflags, codepoint; unsigned int codeflags, codepoint;
@ -1761,7 +1771,6 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
int linecount; int linecount;
conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])]; conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])];
conchar_t *s, *e, *c; conchar_t *s, *e, *c;
int i;
int x; int x;
int charh = Font_CharHeight(); int charh = Font_CharHeight();
unsigned int codeflags, codepoint; unsigned int codeflags, codepoint;

View file

@ -4384,6 +4384,9 @@ static image_t *Image_CreateTexture_Internal (const char *identifier, const char
buck = (bucket_t*)(tex+1); buck = (bucket_t*)(tex+1);
tex->ident = (char*)(buck+1); tex->ident = (char*)(buck+1);
strcpy(tex->ident, identifier); strcpy(tex->ident, identifier);
#ifdef _DEBUG
Q_strncpyz(tex->dbgident, identifier, sizeof(tex->dbgident));
#endif
if (subdir && *subdir) if (subdir && *subdir)
{ {
tex->subpath = tex->ident + strlen(identifier)+1; tex->subpath = tex->ident + strlen(identifier)+1;

View file

@ -253,7 +253,30 @@ void M_Menu_Options_f (void)
}; };
menu_t *menu = M_Options_Title(&y, 0); menu_t *menu = M_Options_Title(&y, 0);
static menuresel_t resel; static menuresel_t resel;
MC_AddBulk(menu, &resel, bulk, 16, 216, y); y = MC_AddBulk(menu, &resel, bulk, 16, 216, y);
#ifdef PLUGINS
if (Cmd_Exists("ezhud_nquake"))
{
extern cvar_t plug_sbar;
static const char *hudplugopts[] = {
"Never",
"Deathmatch",
"Single Player/Coop",
"Always",
NULL
};
static const char *hudplugvalues[] = {
"0",
"1",
"2",
"3",
NULL
};
MC_AddCvarCombo(menu, 16, 216, y, "Use Hud Plugin", &plug_sbar, hudplugopts, hudplugvalues); y += 8;
}
#endif
menu->data = updatecbo; menu->data = updatecbo;
menu->remove = M_Options_Remove; menu->remove = M_Options_Remove;
@ -1213,6 +1236,9 @@ qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct menu_s *menu,
cvarsrds = "1"; cvarsrds = "1";
break; break;
case 4: case 4:
cvard = "-1";
break;
case 5:
cvard = "1"; cvard = "1";
cvarvd = "1"; cvarvd = "1";
break; break;
@ -1259,6 +1285,7 @@ void M_Menu_Lighting_f (void)
"Standard", "Standard",
"Realtime", "Realtime",
"RT+Shadows", "RT+Shadows",
"Threaded Lightmaps",
#ifndef MINIMAL #ifndef MINIMAL
"Vertex", "Vertex",
#endif #endif
@ -1352,11 +1379,13 @@ void M_Menu_Lighting_f (void)
else else
dlightselect = 2; dlightselect = 2;
} }
else if (r_dynamic.ival < 0)
dlightselect = 4;
#ifndef MINIMAL #ifndef MINIMAL
else if (r_vertexdlights.ival) else if (r_vertexdlights.ival)
dlightselect = 4; dlightselect = 5;
#endif #endif
else if (r_dynamic.ival) else if (r_dynamic.ival > 0)
dlightselect = 1; dlightselect = 1;
else else
dlightselect = 0; dlightselect = 0;
@ -2707,6 +2736,9 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
modelview_t *mods = c->dptr; modelview_t *mods = c->dptr;
if (R2D_Flush)
R2D_Flush();
memset(&pv, 0, sizeof(pv)); memset(&pv, 0, sizeof(pv));
CL_DecayLights (); CL_DecayLights ();

View file

@ -137,6 +137,7 @@ enum mlverbosity_e
{ {
MLV_SILENT, MLV_SILENT,
MLV_WARN, MLV_WARN,
MLV_WARNSYNC,
MLV_ERROR MLV_ERROR
}; };
@ -225,6 +226,9 @@ enum
}; };
typedef struct image_s typedef struct image_s
{ {
#ifdef _DEBUG
char dbgident[32];
#endif
char *ident; //allocated on end char *ident; //allocated on end
char *subpath; //allocated on end char *subpath; //allocated on end
int regsequence; int regsequence;

View file

@ -2923,7 +2923,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
info->players=details.numplayers = 0; info->players=details.numplayers = 0;
if (!strchr(msg, '\n')) if (!strchr(msg, '\n'))
info->players = atoi(Info_ValueForKey(details.info, "clients")); info->numhumans = info->players = atoi(Info_ValueForKey(details.info, "clients"));
else else
{ {
int clnum; int clnum;

View file

@ -830,7 +830,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn)
memset(&tn, 0, sizeof(tn)); memset(&tn, 0, sizeof(tn));
if (*ptype->texname) if (*ptype->texname)
{ {
tn.base = R_LoadHiResTexture(ptype->texname, "particles", IF_NOMIPMAP|(ptype->looks.premul?IF_PREMULTIPLYALPHA:0)); //mipmapping breaks particlefont stuff tn.base = R_LoadHiResTexture(ptype->texname, "particles", IF_LOADNOW | IF_NOMIPMAP|(ptype->looks.premul?IF_PREMULTIPLYALPHA:0)); //mipmapping breaks particlefont stuff
if (tn.base && tn.base->status == TEX_LOADING) if (tn.base && tn.base->status == TEX_LOADING)
COM_WorkerPartialSync(tn.base, &tn.base->status, TEX_LOADING); COM_WorkerPartialSync(tn.base, &tn.base->status, TEX_LOADING);
} }

View file

@ -1575,9 +1575,9 @@ static void Surf_RenderDynamicLightmaps_Worker (msurface_t *fa)
qbyte *base, *luxbase; qbyte *base, *luxbase;
stmap *stainbase; stmap *stainbase;
int maps; int maps;
glRect_t *theRect; glRect_t *lmr, *dlmr = NULL;
int smax, tmax; int smax, tmax;
lightmapinfo_t *lm, *dlm; lightmapinfo_t *lm, *dlm = NULL;
//surfaces without lightmaps //surfaces without lightmaps
if (fa->lightmaptexturenums[0]<0 || !lightmap) if (fa->lightmaptexturenums[0]<0 || !lightmap)
@ -1613,29 +1613,11 @@ dynamic:
smax = (fa->extents[0]>>fa->lmshift)+1; smax = (fa->extents[0]>>fa->lmshift)+1;
tmax = (fa->extents[1]>>fa->lmshift)+1; tmax = (fa->extents[1]>>fa->lmshift)+1;
theRect = &lm->rectchange; lmr = &lm->rectchange;
if (theRect->t > fa->light_t[0])
theRect->t = fa->light_t[0];
if (theRect->b < fa->light_t[0]+tmax)
theRect->b = fa->light_t[0]+tmax;
if (theRect->l > fa->light_s[0])
theRect->l = fa->light_s[0];
if (theRect->r < fa->light_s[0]+smax)
theRect->r = fa->light_s[0]+smax;
if (lm->hasdeluxe) if (lm->hasdeluxe)
{ {
dlm = lightmap[fa->lightmaptexturenums[0]+1]; dlm = lightmap[fa->lightmaptexturenums[0]+1];
dlm->modified = true; dlmr = &dlm->rectchange;
theRect = &dlm->rectchange;
if (theRect->t > fa->light_t[0])
theRect->t = fa->light_t[0];
if (theRect->b < fa->light_t[0]+tmax)
theRect->b = fa->light_t[0]+tmax;
if (theRect->l > fa->light_s[0])
theRect->l = fa->light_s[0];
if (theRect->r < fa->light_s[0]+smax)
theRect->r = fa->light_s[0]+smax;
luxbase = dlm->lightmaps; luxbase = dlm->lightmaps;
luxbase += (fa->light_t[0] * dlm->width + fa->light_s[0]) * lightmap_bytes; luxbase += (fa->light_t[0] * dlm->width + fa->light_s[0]) * lightmap_bytes;
@ -1649,6 +1631,26 @@ dynamic:
stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3; stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3;
Surf_BuildLightMap_Worker (fa, base, luxbase, stainbase, lightmap_shift, r_ambient.value*255, lm->width); Surf_BuildLightMap_Worker (fa, base, luxbase, stainbase, lightmap_shift, r_ambient.value*255, lm->width);
if (dlm)
{
if (dlmr->t > fa->light_t[0])
dlmr->t = fa->light_t[0];
if (dlmr->b < fa->light_t[0]+tmax)
dlmr->b = fa->light_t[0]+tmax;
if (dlmr->l > fa->light_s[0])
dlmr->l = fa->light_s[0];
if (dlmr->r < fa->light_s[0]+smax)
dlmr->r = fa->light_s[0]+smax;
dlm->modified = true;
}
if (lmr->t > fa->light_t[0])
lmr->t = fa->light_t[0];
if (lmr->b < fa->light_t[0]+tmax)
lmr->b = fa->light_t[0]+tmax;
if (lmr->l > fa->light_s[0])
lmr->l = fa->light_s[0];
if (lmr->r < fa->light_s[0]+smax)
lmr->r = fa->light_s[0]+smax;
lm->modified = true; lm->modified = true;
} }
#endif //THREADEDWORLD #endif //THREADEDWORLD
@ -3584,7 +3586,7 @@ TRACE(("dbg: Surf_NewMap: tp\n"));
{ {
//unfortunately, we need to know the actual size so that we can get this right. bum. //unfortunately, we need to know the actual size so that we can get this right. bum.
if (cl_static_entities[i].ent.model->loadstate == MLS_NOTLOADED) if (cl_static_entities[i].ent.model->loadstate == MLS_NOTLOADED)
Mod_LoadModel(cl_static_entities[i].ent.model, MLV_SILENT); Mod_LoadModel(cl_static_entities[i].ent.model, MLV_WARNSYNC);
if (cl_static_entities[i].ent.model->loadstate == MLS_LOADING) if (cl_static_entities[i].ent.model->loadstate == MLS_LOADING)
COM_WorkerPartialSync(cl_static_entities[i].ent.model, &cl_static_entities[i].ent.model->loadstate, MLS_LOADING); COM_WorkerPartialSync(cl_static_entities[i].ent.model, &cl_static_entities[i].ent.model->loadstate, MLS_LOADING);
VectorAdd(cl_static_entities[i].ent.origin, cl_static_entities[i].ent.model->mins, mins); VectorAdd(cl_static_entities[i].ent.origin, cl_static_entities[i].ent.model->mins, mins);

View file

@ -1268,7 +1268,7 @@ TRACE(("dbg: R_ApplyRenderer: initing mods\n"));
#endif #endif
TRACE(("dbg: R_ApplyRenderer: reloading server map\n")); TRACE(("dbg: R_ApplyRenderer: reloading server map\n"));
sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_WARN); sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_WARNSYNC);
TRACE(("dbg: R_ApplyRenderer: loaded\n")); TRACE(("dbg: R_ApplyRenderer: loaded\n"));
if (sv.world.worldmodel->loadstate == MLS_LOADING) if (sv.world.worldmodel->loadstate == MLS_LOADING)
COM_WorkerPartialSync(sv.world.worldmodel, &sv.world.worldmodel->loadstate, MLS_LOADING); COM_WorkerPartialSync(sv.world.worldmodel, &sv.world.worldmodel->loadstate, MLS_LOADING);

View file

@ -1423,8 +1423,6 @@ void Sbar_SortFrags (qboolean includespec, qboolean doteamsort)
{ {
fragsort[scoreboardlines] = i; fragsort[scoreboardlines] = i;
scoreboardlines++; scoreboardlines++;
if (cl.players[i].spectator)
cl.players[i].frags = -999;
} }
} }
@ -1443,8 +1441,8 @@ void Sbar_SortFrags (qboolean includespec, qboolean doteamsort)
if (!doteamsort || w1 == w2) if (!doteamsort || w1 == w2)
#endif #endif
{ {
w1 = cl.players[fragsort[i]].frags; w1 = cl.players[fragsort[i]].spectator==1?-999:cl.players[fragsort[i]].frags;
w2 = cl.players[fragsort[j]].frags; w2 = cl.players[fragsort[j]].spectator==1?-999:cl.players[fragsort[j]].frags;
} }
if (w1 < w2) if (w1 < w2)
{ {

View file

@ -2572,26 +2572,23 @@ void S_StopAllSounds(qboolean clear)
for (sc = sndcardinfo; sc; sc = sc->next) for (sc = sndcardinfo; sc; sc = sc->next)
{ {
for (i=0 ; i<sc->total_chans ; i++) for (i=sc->total_chans ; i --> 0 ; )
{ {
if (i >= MUSIC_FIRST && i < MUSIC_FIRST+NUM_MUSICS && sc->selfpainting) if (i >= MUSIC_FIRST && i < MUSIC_FIRST+NUM_MUSICS && sc->selfpainting)
continue; //don't reset music if is safe to continue playing it without stuttering continue; //don't reset music if is safe to continue playing it without stuttering
if (sc->channel[i].sfx) s = sc->channel[i].sfx;
if (s)
{ {
s = sc->channel[i].sfx; sc->channel[i].sfx = NULL;
if (s->loadstate == SLS_LOADING) if (s->loadstate == SLS_LOADED && s->decoder.ended)
COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING); if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly.
// else
{ {
sc->channel[i].sfx = NULL;
if (s->decoder.ended) if (s->decoder.ended)
if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly.
{
s->decoder.ended(s); s->decoder.ended(s);
}
if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, &sc->channel[i], true);
} }
if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, &sc->channel[i], true);
} }
} }

View file

@ -580,37 +580,68 @@ When you run over an item, the server sends this command
*/ */
void V_BonusFlash_f (void) void V_BonusFlash_f (void)
{ {
if (v_bonusflash.value || !Cmd_FromGamecode()) float frac;
if (!gl_cshiftenabled.ival)
frac = 0;
else if (Cmd_FromGamecode())
frac = v_bonusflash.value;
else
frac = 1;
{
//still adheres to gl_cshiftpercent even when forced.
float minfrac = atof(Cmd_Argv(5));
if (frac < minfrac)
frac = minfrac;
}
frac *= gl_cshiftpercent.value / 100.0;
if (frac)
{ {
if (Cmd_Argc() > 1) if (Cmd_Argc() > 1)
{ //this is how I understand DP expects them. { //this is how I understand DP expects them.
cl.cshifts[CSHIFT_BONUS].destcolor[0] = atof(Cmd_Argv(1)); cl.cshifts[CSHIFT_BONUS].destcolor[0] = atof(Cmd_Argv(1))*255;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = atof(Cmd_Argv(2)); cl.cshifts[CSHIFT_BONUS].destcolor[1] = atof(Cmd_Argv(2))*255;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = atof(Cmd_Argv(3)); cl.cshifts[CSHIFT_BONUS].destcolor[2] = atof(Cmd_Argv(3))*255;
cl.cshifts[CSHIFT_BONUS].percent = atof(Cmd_Argv(4))*255*v_bonusflash.value; cl.cshifts[CSHIFT_BONUS].percent = atof(Cmd_Argv(4))*255*frac;
} }
else else
{ {
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69; cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
cl.cshifts[CSHIFT_BONUS].percent = 50*v_bonusflash.value; cl.cshifts[CSHIFT_BONUS].percent = 50*frac;
} }
} }
} }
void V_DarkFlash_f (void) void V_DarkFlash_f (void)
{ {
float frac;
if (!gl_cshiftenabled.ival)
frac = 0;
else
frac = 1;
frac *= gl_cshiftpercent.value / 100.0;
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 0; cl.cshifts[CSHIFT_BONUS].destcolor[0] = 0;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 0; cl.cshifts[CSHIFT_BONUS].destcolor[1] = 0;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 0; cl.cshifts[CSHIFT_BONUS].destcolor[2] = 0;
cl.cshifts[CSHIFT_BONUS].percent = 255; cl.cshifts[CSHIFT_BONUS].percent = 255*frac;
} }
void V_WhiteFlash_f (void) void V_WhiteFlash_f (void)
{ {
float frac;
if (!gl_cshiftenabled.ival)
frac = 0;
else
frac = 1;
frac *= gl_cshiftpercent.value / 100.0;
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 255; cl.cshifts[CSHIFT_BONUS].destcolor[0] = 255;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 255; cl.cshifts[CSHIFT_BONUS].destcolor[1] = 255;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 255; cl.cshifts[CSHIFT_BONUS].destcolor[2] = 255;
cl.cshifts[CSHIFT_BONUS].percent = 255; cl.cshifts[CSHIFT_BONUS].percent = 255*frac;
} }
/* /*
@ -718,7 +749,7 @@ void V_CalcBlend (float *hw_blend)
//don't apply it to the server, we'll blend the two later if the user has no hardware gamma (if they do have it, we use just the server specified value) This way we avoid winnt users having a cheat with flashbangs and stuff. //don't apply it to the server, we'll blend the two later if the user has no hardware gamma (if they do have it, we use just the server specified value) This way we avoid winnt users having a cheat with flashbangs and stuff.
for (j=0 ; j<NUM_CSHIFTS ; j++) for (j=0 ; j<NUM_CSHIFTS ; j++)
{ {
if (j != CSHIFT_SERVER) if (j != CSHIFT_SERVER && j != CSHIFT_BONUS)
{ {
if (!gl_cshiftpercent.value || !gl_cshiftenabled.ival) if (!gl_cshiftpercent.value || !gl_cshiftenabled.ival)
continue; continue;

View file

@ -688,6 +688,8 @@ void Cmd_Echo_f (void)
for (i=1 ; i<Cmd_Argc() ; i++) for (i=1 ; i<Cmd_Argc() ; i++)
{ {
if (i >= 2)
Con_Printf (" ");
#ifdef SERVERONLY #ifdef SERVERONLY
Con_Printf ("%s", Cmd_Argv(i)); Con_Printf ("%s", Cmd_Argv(i));
#else #else

View file

@ -704,7 +704,10 @@ void deleetstring(char *result, const char *leet)
s2++; s2++;
continue; continue;
} }
*s = *s2 & ~128; if (*s2 >= 0xa0)
*s = *s2 & ~128;
else
*s = *s2;
s2++; s2++;
if (*s == '3') if (*s == '3')
*s = 'e'; *s = 'e';
@ -4724,6 +4727,11 @@ void COM_ErrorMe_f(void)
#ifdef LOADERTHREAD #ifdef LOADERTHREAD
static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue);
cvar_t worker_flush = CVARD("worker_flush", "1", "If set, process the entire load queue, loading stuff faster but at the risk of stalling the main thread.");
cvar_t worker_count = CVARFDC("worker_count", "", CVAR_NOTFROMSERVER, "Specifies the number of worker threads to utilise.", COM_WorkerCount_Change);
cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSERVER, "Causes workers to sleep for a period of time after each job.");
#define WG_MAIN 0 #define WG_MAIN 0
#define WG_LOADER 1 #define WG_LOADER 1
#define WG_COUNT 2 //main and loaders #define WG_COUNT 2 //main and loaders
@ -4801,11 +4809,26 @@ void COM_AddWork(int tg, void(*func)(void *ctx, void *data, size_t a, size_t b),
Sys_ConditionSignal(com_workercondition[tg]); Sys_ConditionSignal(com_workercondition[tg]);
Sys_UnlockConditional(com_workercondition[tg]); Sys_UnlockConditional(com_workercondition[tg]);
// if (!com_workerthread[thread])
// while(COM_DoWork(thread, false))
// ;
} }
void COM_PrintWork(void)
{
struct com_work_s *work;
int tg;
Sys_Printf("--------- BEGIN WORKER LIST ---------\n");
for (tg = 0; tg < WG_COUNT; tg++)
{
Sys_LockConditional(com_workercondition[tg]);
work = com_work_head[tg];
while (work)
{
Sys_Printf("thread%i: %s\n", tg, (char*)work->ctx);
work = work->next;
}
Sys_UnlockConditional(com_workercondition[tg]);
}
}
//leavelocked = false == poll mode. //leavelocked = false == poll mode.
//leavelocked = true == safe sleeping //leavelocked = true == safe sleeping
qboolean COM_DoWork(int tg, qboolean leavelocked) qboolean COM_DoWork(int tg, qboolean leavelocked)
@ -4905,7 +4928,14 @@ static int COM_WorkerThread(void *arg)
for(;;) for(;;)
{ {
while(COM_DoWork(group, true)) while(COM_DoWork(group, true))
; {
if (worker_sleeptime.value)
{
Sys_UnlockConditional(com_workercondition[group]);
Sys_Sleep(worker_sleeptime.value);
Sys_LockConditional(com_workercondition[group]);
}
}
if (thread->request) //flagged from some work if (thread->request) //flagged from some work
{ {
if (thread->request == WR_DIE) if (thread->request == WR_DIE)
@ -5065,7 +5095,7 @@ void COM_WorkerFullSync(void)
void COM_WorkerPartialSync(void *priorityctx, int *address, int value) void COM_WorkerPartialSync(void *priorityctx, int *address, int value)
{ {
struct com_work_s **link, *work, *prev; struct com_work_s **link, *work, *prev;
double time1 = Sys_DoubleTime(); // double time1 = Sys_DoubleTime();
// Con_Printf("waiting for %p %s\n", priorityctx, priorityctx); // Con_Printf("waiting for %p %s\n", priorityctx, priorityctx);
@ -5106,7 +5136,15 @@ void COM_WorkerPartialSync(void *priorityctx, int *address, int value)
Sys_UnlockConditional(com_workercondition[grp]); Sys_UnlockConditional(com_workercondition[grp]);
} }
if (!found) if (!found)
Con_DPrintf("Might be in for a long wait for %s\n", (char*)priorityctx); {
while(COM_DoWork(WG_MAIN, false))
{
//give up as soon as we're done
if (*address != value)
return;
}
// Con_Printf("Might be in for a long wait for %s\n", (char*)priorityctx);
}
} }
Sys_LockConditional(com_workercondition[WG_MAIN]); Sys_LockConditional(com_workercondition[WG_MAIN]);
@ -5178,8 +5216,6 @@ static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue)
} }
Sys_ConditionBroadcast(com_workercondition[WG_LOADER]); //and make sure they ALL wake up to check their new death values. Sys_ConditionBroadcast(com_workercondition[WG_LOADER]); //and make sure they ALL wake up to check their new death values.
} }
cvar_t worker_flush = CVARD("worker_flush", "1", "If set, process the entire load queue, loading stuff faster but at the risk of stalling the main thread.");
cvar_t worker_count = CVARFDC("worker_count", "", CVAR_NOTFROMSERVER, "Specifies the number of worker threads to utilise.", COM_WorkerCount_Change);
static void COM_InitWorkerThread(void) static void COM_InitWorkerThread(void)
{ {
int i; int i;
@ -5200,10 +5236,11 @@ static void COM_InitWorkerThread(void)
worker_count.flags |= CVAR_NOSET; worker_count.flags |= CVAR_NOSET;
} }
Cvar_Register(&worker_count, NULL); Cvar_Register(&worker_count, NULL);
Cvar_ForceCallback(&worker_count);
Cmd_AddCommand ("worker_test", COM_WorkerTest_f); Cmd_AddCommand ("worker_test", COM_WorkerTest_f);
Cvar_Register(&worker_flush, NULL); Cvar_Register(&worker_flush, NULL);
Cvar_Register(&worker_sleeptime, NULL);
Cvar_ForceCallback(&worker_count);
} }
#endif #endif

View file

@ -1179,6 +1179,10 @@ cvar_t *Cvar_Get2(const char *name, const char *defaultvalue, int flags, const c
if (!description) if (!description)
description = ""; description = "";
//don't allow cvars with certain funny chars in their name. ever. such things get really messy when saved in configs or whatever.
if (!*name || strchr(name, '\"') || strchr(name, '^') || strchr(name, '$') || strchr(name, ' ') || strchr(name, '\t') || strchr(name, '\r') || strchr(name, '\n') || strchr(name, ';'))
return NULL;
var = (cvar_t*)Z_Malloc(sizeof(cvar_t)+strlen(name)+1+(description?(strlen(description)+1):0)); var = (cvar_t*)Z_Malloc(sizeof(cvar_t)+strlen(name)+1+(description?(strlen(description)+1):0));
var->name = (char *)(var+1); var->name = (char *)(var+1);
strcpy(var->name, name); strcpy(var->name, name);
@ -1259,31 +1263,31 @@ qboolean Cvar_Command (int level)
{ {
if (v->flags & CVAR_LATCH) if (v->flags & CVAR_LATCH)
{ {
Con_Printf ("\"%s\" is currently %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), false)); Con_Printf ("\"%s\" is currently \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_Printf ("Will be changed to %s on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), false)); Con_Printf ("Will be changed to \"%s\" on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
} }
else if (v->flags & CVAR_RENDERERLATCH) else if (v->flags & CVAR_RENDERERLATCH)
{ {
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), false)); Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_Printf ("Will be changed to %s on vid_restart\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), false)); Con_Printf ("Will be changed to \"%s\" on vid_restart\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
} }
else else
{ {
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer), false)); Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
Con_Printf ("Effective value is %s\n", COM_QuotedString(v->string, buffer, sizeof(buffer), false)); Con_Printf ("Effective value is \"%s\"\n", COM_QuotedString(v->string, buffer, sizeof(buffer), true));
} }
if (v->defaultstr) if (v->defaultstr)
Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), false)); Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), true));
} }
else else
{ {
if (v->defaultstr && !strcmp(v->string, v->defaultstr)) if (v->defaultstr && !strcmp(v->string, v->defaultstr))
Con_Printf ("\"%s\" is %s (default)\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), false)); Con_Printf ("\"%s\" is \"%s\" (default)\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
else else
{ {
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), false)); Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
if (v->defaultstr) if (v->defaultstr)
Con_Printf("Default: %s\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), false)); Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), true));
} }
} }
return true; return true;
@ -1309,9 +1313,9 @@ qboolean Cvar_Command (int level)
{ //don't bother even changing the cvar locally, just update the server's version. { //don't bother even changing the cvar locally, just update the server's version.
//fixme: quake2/quake3 latching. //fixme: quake2/quake3 latching.
if (seat) if (seat)
CL_SendClientCommand(true, "%i setinfo %s \"%s\"", seat+1, v->name, str); CL_SendClientCommand(true, "%i setinfo %s %s", seat+1, v->name, COM_QuotedString(str, buffer, sizeof(buffer), false));
else else
CL_SendClientCommand(true, "setinfo %s \"%s\"", v->name, str); CL_SendClientCommand(true, "setinfo %s %s", v->name, COM_QuotedString(str, buffer, sizeof(buffer), false));
} }
else else
CL_SetInfo(seat, v->name, str); CL_SetInfo(seat, v->name, str);

View file

@ -1065,7 +1065,7 @@ int FS_FLocateFile(const char *filename, unsigned int lflags, flocation_t *loc)
// optionally check the non-pure paths too. // optionally check the non-pure paths too.
for (search = com_searchpaths ; search ; search = search->next) for (search = com_searchpaths ; search ; search = search->next)
{ {
if ((lflags & FSLF_SECUREONLY) && !(search->flags & SPF_UNTRUSTED)) if ((lflags & FSLF_SECUREONLY) && (search->flags & SPF_UNTRUSTED))
continue; continue;
depth += ((search->flags & SPF_EXPLICIT) || (lflags & FSLF_DEPTH_EXPLICIT)); depth += ((search->flags & SPF_EXPLICIT) || (lflags & FSLF_DEPTH_EXPLICIT));
fs_finds++; fs_finds++;
@ -3636,8 +3636,11 @@ static void FS_FreePaths(void)
void FS_Shutdown(void) void FS_Shutdown(void)
{ {
FS_FreePaths(); FS_FreePaths();
Sys_DestroyMutex(fs_thread_mutex); if (fs_thread_mutex)
fs_thread_mutex = NULL; {
Sys_DestroyMutex(fs_thread_mutex);
fs_thread_mutex = NULL;
}
Cvar_SetEngineDefault(&fs_gamename, NULL); Cvar_SetEngineDefault(&fs_gamename, NULL);
Cvar_SetEngineDefault(&com_protocolname, NULL); Cvar_SetEngineDefault(&com_protocolname, NULL);

View file

@ -281,7 +281,10 @@ static void QDECL VFSW32_Flush(struct vfsfile_s *file)
vfsw32file_t *intfile = (vfsw32file_t*)file; vfsw32file_t *intfile = (vfsw32file_t*)file;
if (intfile->mmap) if (intfile->mmap)
FlushViewOfFile(intfile->mmap, intfile->length); FlushViewOfFile(intfile->mmap, intfile->length);
FlushFileBuffers(intfile->hand);
//we only really flush things to ensure that we don't get a stall later.
//in windows, FlushFileBuffers can have significant costs, so lets see if anyone complains about us not flushing.
// FlushFileBuffers(intfile->hand);
} }
static qofs_t QDECL VFSW32_GetSize (struct vfsfile_s *file) static qofs_t QDECL VFSW32_GetSize (struct vfsfile_s *file)
{ {

View file

@ -105,19 +105,29 @@ void INS_UpdateGrabs(int fullscreen, int activeapp);
int QCLibEditor(pubprogfuncs_t *prinst, const char *filename, int *line, int *statement, char *error, pbool fatal); int QCLibEditor(pubprogfuncs_t *prinst, const char *filename, int *line, int *statement, char *error, pbool fatal);
void QCLoadBreakpoints(const char *vmname, const char *progsname) void QCLoadBreakpoints(const char *vmname, const char *progsname)
{ //this asks the gui to reapply any active breakpoints and waits for them so that any spawn functions can be breakpointed properly. { //this asks the gui to reapply any active breakpoints and waits for them so that any spawn functions can be breakpointed properly.
#if defined(_WIN32) && !defined(SERVERONLY) && !defined(FTE_SDL) #if defined(_WIN32) && !defined(FTE_SDL)
extern int isPlugin; extern int isPlugin;
if (isPlugin >= 2) if (isPlugin >= 2)
{ {
#ifdef SERVERONLY
SV_GetConsoleCommands();
#else
Sys_SendKeyEvents(); Sys_SendKeyEvents();
#endif
debuggerresume = -1; debuggerresume = -1;
printf("qcreloaded \"%s\" \"%s\"\n", vmname, progsname); printf("qcreloaded \"%s\" \"%s\"\n", vmname, progsname);
fflush(stdout); fflush(stdout);
#ifndef SERVERONLY
INS_UpdateGrabs(false, false); INS_UpdateGrabs(false, false);
#endif
while(debuggerresume == -1 && !wantquit) while(debuggerresume == -1 && !wantquit)
{ {
Sleep(10); Sleep(10);
#ifdef SERVERONLY
SV_GetConsoleCommands();
#else
Sys_SendKeyEvents(); Sys_SendKeyEvents();
#endif
} }
} }
#endif #endif
@ -129,6 +139,8 @@ size_t debuggerwnd;
qboolean QCExternalDebuggerCommand(char *text) qboolean QCExternalDebuggerCommand(char *text)
{ {
if (!isPlugin)
return false;
if ((!strncmp(text, "qcstep", 6) && (text[6] == 0 || text[6] == ' ')) || (!strncmp(text, "qcresume", 8) && (text[8] == 0 || text[8] == ' '))) if ((!strncmp(text, "qcstep", 6) && (text[6] == 0 || text[6] == ' ')) || (!strncmp(text, "qcresume", 8) && (text[8] == 0 || text[8] == ' ')))
{ {
// int l; // int l;
@ -321,6 +333,8 @@ int QDECL QCEditor (pubprogfuncs_t *prinst, const char *filename, int *line, int
if (debuggerstacky) if (debuggerstacky)
PR_StackTrace(prinst, 2); PR_StackTrace(prinst, 2);
debuggerstacky = 0; debuggerstacky = 0;
if (R2D_Flush)
R2D_Flush();
VID_SwapBuffers(); VID_SwapBuffers();
} }
} }
@ -4575,14 +4589,13 @@ void QCBUILTIN PF_droptofloor (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
vec3_t start; vec3_t start;
trace_t trace; trace_t trace;
const float *gravitydir; const float *gravitydir;
extern const vec3_t standardgravity;
ent = PROG_TO_WEDICT(prinst, *world->g.self); ent = PROG_TO_WEDICT(prinst, *world->g.self);
if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0]) if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0])
gravitydir = ent->xv->gravitydir; gravitydir = ent->xv->gravitydir;
else else
gravitydir = standardgravity; gravitydir = world->g.defaultgravitydir;
VectorCopy (ent->v->origin, end); VectorCopy (ent->v->origin, end);
if (pr_droptofloorunits.value > 0) if (pr_droptofloorunits.value > 0)
@ -5960,9 +5973,11 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_QC_TRACETRIGGER"}, {"FTE_QC_TRACETRIGGER"},
{"FTE_SOLID_LADDER"}, //Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS {"FTE_SOLID_LADDER"}, //Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS
#ifdef SQL
// serverside SQL functions for managing an SQL database connection // serverside SQL functions for managing an SQL database connection
{"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion", {"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion",
"sqlreadfloat"}}, "sqlreadfloat"}},
#endif
//eperimental advanced strings functions. //eperimental advanced strings functions.
//reuses the FRIK_FILE builtins (with substring extension) //reuses the FRIK_FILE builtins (with substring extension)

View file

@ -213,6 +213,7 @@ struct world_s
float *v_forward; float *v_forward;
float *v_right; float *v_right;
float *v_up; float *v_up;
float *defaultgravitydir;
//used by menu+csqc. //used by menu+csqc.
float *drawfont; float *drawfont;

View file

@ -248,18 +248,16 @@ void GLBE_PolyOffsetStencilShadow(qboolean pushdepth)
{ {
extern cvar_t r_polygonoffset_stencil_offset, r_polygonoffset_stencil_factor; extern cvar_t r_polygonoffset_stencil_offset, r_polygonoffset_stencil_factor;
polyoffset_t po; polyoffset_t po;
po.factor = r_polygonoffset_stencil_factor.value;
po.unit = r_polygonoffset_stencil_offset.value;
if (pushdepth) if (pushdepth)
{ {
/*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc
we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/
extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor; extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor;
po.factor = r_polygonoffset_submodel_factor.value + r_polygonoffset_stencil_factor.value; po.factor += r_polygonoffset_submodel_factor.value;
po.unit = r_polygonoffset_submodel_offset.value + r_polygonoffset_stencil_offset.value; po.unit += r_polygonoffset_submodel_offset.value;
}
else
{
po.factor = r_polygonoffset_stencil_factor.value;
po.unit = r_polygonoffset_stencil_offset.value;
} }
#ifndef FORCESTATE #ifndef FORCESTATE
@ -903,7 +901,8 @@ void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsi
shaderstate.sourcevbo = &shaderstate.dummyvbo; shaderstate.sourcevbo = &shaderstate.dummyvbo;
shaderstate.dummyvbo.indicies.gl.vbo = ibo; shaderstate.dummyvbo.indicies.gl.vbo = ibo;
GLBE_PolyOffsetShadowMap(false); if (shaderstate.mode != BEM_STENCIL)
GLBE_PolyOffsetShadowMap(false);
if (shaderstate.allblackshader.glsl.handle) if (shaderstate.allblackshader.glsl.handle)
{ {
@ -4942,7 +4941,11 @@ static void BE_UpdateLightmaps(void)
{ {
int t = lm->rectchange.t; //pull them out now, in the hopes that it'll be more robust with respect to r_dynamic -1 int t = lm->rectchange.t; //pull them out now, in the hopes that it'll be more robust with respect to r_dynamic -1
int b = lm->rectchange.b; int b = lm->rectchange.b;
lm->modified = false; #ifdef _DEBUG
if (t >= b)
Con_Printf("Dodgy lightmaps\n");
else
#endif
if (!TEXVALID(lm->lightmap_texture)) if (!TEXVALID(lm->lightmap_texture))
{ {
extern cvar_t gl_lightmap_nearest; extern cvar_t gl_lightmap_nearest;
@ -4962,6 +4965,7 @@ static void BE_UpdateLightmaps(void)
lm->width, b-t, glformat, gltype, lm->width, b-t, glformat, gltype,
lm->lightmaps+t *lm->width*lightmap_bytes); lm->lightmaps+t *lm->width*lightmap_bytes);
} }
lm->modified = false;
lm->rectchange.l = lm->width; lm->rectchange.l = lm->width;
lm->rectchange.t = lm->height; lm->rectchange.t = lm->height;
lm->rectchange.r = 0; lm->rectchange.r = 0;

View file

@ -946,17 +946,17 @@ static texid_t Font_LoadReplacementConchars(void)
{ {
texid_t tex; texid_t tex;
//q1 replacement //q1 replacement
tex = R_LoadReplacementTexture("gfx/conchars.lmp", NULL, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, NULL, 0, 0, TF_INVALID); tex = R_LoadReplacementTexture("gfx/conchars.lmp", NULL, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, NULL, 0, 0, TF_INVALID);
TEXDOWAIT(tex); TEXDOWAIT(tex);
if (TEXLOADED(tex)) if (TEXLOADED(tex))
return tex; return tex;
//q2 //q2
tex = R_LoadHiResTexture("pics/conchars.pcx", NULL, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); tex = R_LoadHiResTexture("pics/conchars.pcx", NULL, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA);
TEXDOWAIT(tex); TEXDOWAIT(tex);
if (TEXLOADED(tex)) if (TEXLOADED(tex))
return tex; return tex;
//q3 //q3
tex = R_LoadHiResTexture("gfx/2d/bigchars.tga", NULL, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); tex = R_LoadHiResTexture("gfx/2d/bigchars.tga", NULL, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA);
TEXDOWAIT(tex); TEXDOWAIT(tex);
if (TEXLOADED(tex)) if (TEXLOADED(tex))
return tex; return tex;
@ -980,7 +980,7 @@ static texid_t Font_LoadQuakeConchars(void)
if (lump[i] == 0) if (lump[i] == 0)
lump[i] = 255; // proper transparent color lump[i] = 255; // proper transparent color
return R_LoadTexture8("charset", 128, 128, (void*)lump, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1); return R_LoadTexture8("charset", 128, 128, (void*)lump, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1);
} }
return r_nulltex; return r_nulltex;
} }
@ -1066,7 +1066,7 @@ static texid_t Font_LoadHexen2Conchars(qboolean iso88591)
for (i=0 ; i<128*128 ; i++) for (i=0 ; i<128*128 ; i++)
if (outbuf[i] == 0) if (outbuf[i] == 0)
outbuf[i] = 255; // proper transparent color outbuf[i] = 255; // proper transparent color
tex = R_LoadTexture8 (iso88591?"gfx/menu/8859-1.lmp":"charset", 128, 128, outbuf, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1); tex = R_LoadTexture8 (iso88591?"gfx/menu/8859-1.lmp":"charset", 128, 128, outbuf, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1);
Z_Free(outbuf); Z_Free(outbuf);
return tex; return tex;
} }
@ -1123,7 +1123,7 @@ static texid_t Font_LoadFallbackConchars(void)
Font_CopyGlyph(']', 130, lump); Font_CopyGlyph(']', 130, lump);
Font_CopyGlyph('o', 131, lump); Font_CopyGlyph('o', 131, lump);
} }
tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA);
BZ_Free(lump); BZ_Free(lump);
return tex; return tex;
} }

View file

@ -481,7 +481,11 @@ void Mod_Purge(enum mod_purge_e ptype)
if (unused || ptype != MP_MAPCHANGED) if (unused || ptype != MP_MAPCHANGED)
{ {
if (mod->loadstate == MLS_LOADING) if (mod->loadstate == MLS_LOADING)
{
if (ptype == MP_MAPCHANGED && !mod->submodelof)
continue; //don't bother waiting for it on map changes.
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING); COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
}
if (unused) if (unused)
Con_DPrintf("model \"%s\" no longer needed\n", mod->name); Con_DPrintf("model \"%s\" no longer needed\n", mod->name);
@ -944,6 +948,7 @@ void Mod_ModelLoaded(void *ctx, void *data, size_t a, size_t b)
case MLV_ERROR: case MLV_ERROR:
Host_EndGame ("Mod_NumForName: %s not found or couldn't load", mod->name); Host_EndGame ("Mod_NumForName: %s not found or couldn't load", mod->name);
break; break;
case MLV_WARNSYNC:
case MLV_WARN: case MLV_WARN:
if (*mod->name != '*' && strcmp(mod->name, "null") && mod_warnmodels.ival && !previouslyfailed) if (*mod->name != '*' && strcmp(mod->name, "null") && mod_warnmodels.ival && !previouslyfailed)
Con_Printf(CON_ERROR "Unable to load %s\n", mod->name); Con_Printf(CON_ERROR "Unable to load %s\n", mod->name);
@ -1168,6 +1173,9 @@ model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose)
// if (verbose == MLV_ERROR) //if its fatal on failure (ie: world), do it on the main thread and block to wait for it. // if (verbose == MLV_ERROR) //if its fatal on failure (ie: world), do it on the main thread and block to wait for it.
// Mod_LoadModelWorker(mod, MLV_WARN, 0); // Mod_LoadModelWorker(mod, MLV_WARN, 0);
// else // else
if (verbose == MLV_ERROR || verbose == MLV_WARNSYNC)
COM_AddWork(0, Mod_LoadModelWorker, mod, NULL, verbose, 0);
else
COM_AddWork(1, Mod_LoadModelWorker, mod, NULL, verbose, 0); COM_AddWork(1, Mod_LoadModelWorker, mod, NULL, verbose, 0);
} }
@ -1689,6 +1697,8 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
COM_FileBase(loadmodel->name, litbase, sizeof(litbase)); COM_FileBase(loadmodel->name, litbase, sizeof(litbase));
for (i = 0; i < sizeof(litnames)/sizeof(litnames[0]); i++) for (i = 0; i < sizeof(litnames)/sizeof(litnames[0]); i++)
{ {
if (temp_lit2support.ival && !(i & 1))
continue;
if (strchr(litnames[i], '/')) if (strchr(litnames[i], '/'))
Q_snprintfz(litname, sizeof(litname), litnames[i], litbase); Q_snprintfz(litname, sizeof(litname), litnames[i], litbase);
else else

View file

@ -2755,6 +2755,7 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
int i; int i;
struct shadowmesh_s *sm; struct shadowmesh_s *sm;
entity_t *ent; entity_t *ent;
model_t *emodel;
sm = SHM_BuildShadowMesh(dl, lvis, vvis, SMT_STENCILVOLUME); sm = SHM_BuildShadowMesh(dl, lvis, vvis, SMT_STENCILVOLUME);
if (!sm) if (!sm)
@ -2804,25 +2805,37 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
{ {
ent = &cl_visedicts[i]; ent = &cl_visedicts[i];
if (ent->rtype != RT_MODEL)
continue;
if (ent->flags & (RF_NOSHADOW|Q2RF_BEAM)) if (ent->flags & (RF_NOSHADOW|Q2RF_BEAM))
continue; continue;
if (ent->keynum == dl->key && ent->keynum) if (ent->keynum == dl->key && ent->keynum)
continue; continue;
if (!ent->model) emodel = ent->model;
if (!emodel)
continue; continue;
if (cls.allow_anyparticles) //allowed or static if (cls.allow_anyparticles) //allowed or static
{ {
if (ent->model->engineflags & MDLF_ENGULPHS) if (emodel->engineflags & MDLF_ENGULPHS)
{ {
if (gl_part_flame.value) if (gl_part_flame.value)
continue; continue;
} }
} }
switch (ent->model->type) if (emodel->loadstate == MLS_NOTLOADED)
{
if (!Mod_LoadModel(emodel, MLV_WARN))
continue;
}
if (emodel->loadstate != MLS_LOADED)
continue;
switch (emodel->type)
{ {
case mod_alias: case mod_alias:
R_DrawGAliasShadowVolume (ent, dl->origin, dl->radius); R_DrawGAliasShadowVolume (ent, dl->origin, dl->radius);
@ -2940,7 +2953,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, vec3_t axis[3],
} }
#endif #endif
//our stencil writes. //our stencil writes.
if (gl_config.arb_depth_clamp) if (gl_config.arb_depth_clamp && gl_maxdist.value != 0)
qglEnable(GL_DEPTH_CLAMP_ARB); qglEnable(GL_DEPTH_CLAMP_ARB);
#if 0 //def _DEBUG #if 0 //def _DEBUG

View file

@ -1021,7 +1021,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
//certain drivers (*cough* mesa *cough*) update vao0 state even when a different vao is bound. //certain drivers (*cough* mesa *cough*) update vao0 state even when a different vao is bound.
//they also don't support client arrays, so are unusable without glsl or vertex streaming (which is *really* hard to optimise for - especially with webgl etc) //they also don't support client arrays, so are unusable without glsl or vertex streaming (which is *really* hard to optimise for - especially with webgl etc)
//so only use them with gl3+ core contexts where vbo is mandatory anyway. //so only use them with gl3+ core contexts where vbo is mandatory anyway.
if (!gl_config.nofixedfunc) if (!gl_config_nofixedfunc)
{ {
//don't bother if we've no glsl //don't bother if we've no glsl
qglGenVertexArrays = NULL; qglGenVertexArrays = NULL;
@ -1833,11 +1833,6 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
length[strings] = strlen(prstrings[strings]); length[strings] = strlen(prstrings[strings]);
strings++; strings++;
//prstrings[strings] = "invariant gl_Position;\n";
//length[strings] = strlen(prstrings[strings]);
//strings++;
switch (shadertype) switch (shadertype)
{ {
case GL_FRAGMENT_SHADER_ARB: case GL_FRAGMENT_SHADER_ARB:
@ -1884,6 +1879,12 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
prstrings[strings] = "#define VERTEX_SHADER\n"; prstrings[strings] = "#define VERTEX_SHADER\n";
length[strings] = strlen(prstrings[strings]); length[strings] = strlen(prstrings[strings]);
strings++; strings++;
if (!r_shadow_shadowmapping.ival && ver >= 120)
{
prstrings[strings] = "invariant gl_Position;\n";
length[strings] = strlen(prstrings[strings]);
strings++;
}
if (gl_config.gles) if (gl_config.gles)
{ {
prstrings[strings] = prstrings[strings] =
@ -1905,7 +1906,7 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
length[strings] = strlen(prstrings[strings]); length[strings] = strlen(prstrings[strings]);
strings++; strings++;
} }
if (gl_config.nofixedfunc || ver >= 130) if (gl_config_nofixedfunc || ver >= 130)
{ {
prstrings[strings] = prstrings[strings] =
"attribute vec3 v_position1;\n" "attribute vec3 v_position1;\n"
@ -2029,7 +2030,7 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
Con_Printf("%s shader (%s) compilation error:\n----------\n%s----------\n", typedesc, name, str); Con_Printf("%s shader (%s) compilation error:\n----------\n%s----------\n", typedesc, name, str);
//if there's no fixed function then failure to compile the default2d shader should be considered fatal. this should help avoid black screens on android. //if there's no fixed function then failure to compile the default2d shader should be considered fatal. this should help avoid black screens on android.
if (gl_config.nofixedfunc && !strcmp(name, "default2d")) if (gl_config_nofixedfunc && !strcmp(name, "default2d"))
Sys_Error("%s shader (%s) compilation error:\n----------\n%s----------\n", typedesc, name, str); Sys_Error("%s shader (%s) compilation error:\n----------\n%s----------\n", typedesc, name, str);
if (developer.ival) if (developer.ival)
@ -2658,7 +2659,7 @@ void GL_Init(void *(*getglfunction) (char *name))
qglDrawRangeElements = GL_DrawRangeElementsEmul; qglDrawRangeElements = GL_DrawRangeElementsEmul;
} }
else if (gl_config.nofixedfunc) else if (gl_config_nofixedfunc)
{ {
qglLoadMatrixf = NULL; qglLoadMatrixf = NULL;
qglPolygonMode = NULL; qglPolygonMode = NULL;
@ -2773,7 +2774,7 @@ void GL_Init(void *(*getglfunction) (char *name))
sh_config.pProgAutoFields = GLSlang_ProgAutoFields; sh_config.pProgAutoFields = GLSlang_ProgAutoFields;
} }
if (gl_config.nofixedfunc) if (gl_config_nofixedfunc)
{ {
sh_config.tex_env_combine = 1; sh_config.tex_env_combine = 1;
sh_config.nv_tex_env_combine4 = 1; sh_config.nv_tex_env_combine4 = 1;

View file

@ -220,6 +220,12 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath, pbool
} }
} }
while (doubledots-- > 0)
{
strcpy(end, "../");
end += 3;
}
strcpy(end, newfile); strcpy(end, newfile);
if (verbose) if (verbose)

View file

@ -4951,6 +4951,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
{ {
{FCONTROL|FVIRTKEY, 'S', IDM_SAVE}, {FCONTROL|FVIRTKEY, 'S', IDM_SAVE},
{FCONTROL|FVIRTKEY, 'F', IDM_FIND}, {FCONTROL|FVIRTKEY, 'F', IDM_FIND},
{FCONTROL|FVIRTKEY, 'G', IDM_GREP},
{FCONTROL|FVIRTKEY, 'R', IDM_RECOMPILE}, {FCONTROL|FVIRTKEY, 'R', IDM_RECOMPILE},
// {FVIRTKEY, VK_F4, IDM_NEXTERROR}, // {FVIRTKEY, VK_F4, IDM_NEXTERROR},
{FVIRTKEY, VK_F5, IDM_DEBUG_RUN}, {FVIRTKEY, VK_F5, IDM_DEBUG_RUN},

View file

@ -425,6 +425,7 @@ void PR_SV_FillWorldGlobals(world_t *w)
w->g.v_forward = *pr_global_ptrs->v_forward; w->g.v_forward = *pr_global_ptrs->v_forward;
w->g.v_right = *pr_global_ptrs->v_right; w->g.v_right = *pr_global_ptrs->v_right;
w->g.v_up = *pr_global_ptrs->v_up; w->g.v_up = *pr_global_ptrs->v_up;
w->g.defaultgravitydir = *pr_global_ptrs->global_gravitydir;
} }
static void PDECL PR_SSQC_Relocated(pubprogfuncs_t *pr, char *oldb, char *newb, int oldlen) static void PDECL PR_SSQC_Relocated(pubprogfuncs_t *pr, char *oldb, char *newb, int oldlen)
@ -692,6 +693,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static float input_impulse_default; static float input_impulse_default;
static vec3_t input_angles_default; static vec3_t input_angles_default;
static vec3_t input_movevalues_default; static vec3_t input_movevalues_default;
static vec3_t global_gravitydir_default;
int i; int i;
int *v; int *v;
globalptrs_t *pr_globals = pr_global_ptrs; globalptrs_t *pr_globals = pr_global_ptrs;
@ -758,6 +760,7 @@ void PR_LoadGlabalStruct(qboolean muted)
globalvec (false, input_movevalues); globalvec (false, input_movevalues);
globalfloat (false, input_buttons); globalfloat (false, input_buttons);
globalint (false, serverid); globalint (false, serverid);
globalvec (false, global_gravitydir);
memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch)); memset(&evalc_idealpitch, 0, sizeof(evalc_idealpitch));
memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed)); memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed));
@ -782,6 +785,7 @@ void PR_LoadGlabalStruct(qboolean muted)
ensureglobal(input_angles, input_angles_default); ensureglobal(input_angles, input_angles_default);
ensureglobal(input_movevalues, input_movevalues_default); ensureglobal(input_movevalues, input_movevalues_default);
ensureglobal(input_buttons, input_buttons_default); ensureglobal(input_buttons, input_buttons_default);
ensureglobal(global_gravitydir, global_gravitydir_default);
// qtest renames and missing variables // qtest renames and missing variables
if (!(pr_globals)->trace_plane_normal) if (!(pr_globals)->trace_plane_normal)
@ -2452,7 +2456,7 @@ void PF_setmodel_Internal (pubprogfuncs_t *prinst, edict_t *e, const char *m)
//qw dedicated servers only load bsps (better) //qw dedicated servers only load bsps (better)
if (mod) if (mod)
{ {
mod = Mod_ForName (Mod_FixName(m, sv.modelname), MLV_WARN); mod = Mod_ForName (Mod_FixName(m, sv.modelname), MLV_WARNSYNC);
if (mod) if (mod)
{ {
while(mod->loadstate == MLS_LOADING) while(mod->loadstate == MLS_LOADING)
@ -3456,8 +3460,10 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
slen = strlen(str); slen = strlen(str);
SV_StuffcmdToClient(cl, str); if (!(flags & STUFFCMD_DEMOONLY))
SV_StuffcmdToClient(cl, str);
if (!(flags & STUFFCMD_IGNOREINDEMO))
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
sizebuf_t *msg = MVDWrite_Begin (dem_single, entnum - 1, 2 + slen); sizebuf_t *msg = MVDWrite_Begin (dem_single, entnum - 1, 2 + slen);
@ -3466,6 +3472,7 @@ void PF_stuffcmd_Internal(int entnum, const char *str, unsigned int flags)
} }
//this seems a little dangerous. v_cshift could leave a spectator's machine unusable if they switch players at unfortunate times. //this seems a little dangerous. v_cshift could leave a spectator's machine unusable if they switch players at unfortunate times.
if (!(flags & STUFFCMD_DEMOONLY))
if (sv_specprint.ival & SPECPRINT_STUFFCMD) if (sv_specprint.ival & SPECPRINT_STUFFCMD)
{ {
client_t *spec; client_t *spec;
@ -3494,6 +3501,11 @@ static void QCBUILTIN PF_stuffcmd (pubprogfuncs_t *prinst, struct globalvars_s *
PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM1), 0); PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM1), 0);
} }
static void QCBUILTIN PF_stuffcmdflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
PF_stuffcmd_Internal(G_EDICTNUM(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM2), G_FLOAT(OFS_PARM1));
}
//DP_QC_DROPCLIENT //DP_QC_DROPCLIENT
static void QCBUILTIN PF_dropclient (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_dropclient (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -3864,7 +3876,7 @@ int PF_precache_model_Internal (pubprogfuncs_t *prinst, const char *s, qboolean
sv.strings.model_precache[i] = PR_AddString(prinst, s, 0, false); sv.strings.model_precache[i] = PR_AddString(prinst, s, 0, false);
s = sv.strings.model_precache[i]; s = sv.strings.model_precache[i];
if (!strcmp(s + strlen(s) - 4, ".bsp") || sv_gameplayfix_setmodelrealbox.ival) if (!strcmp(s + strlen(s) - 4, ".bsp") || sv_gameplayfix_setmodelrealbox.ival)
sv.models[i] = Mod_ForName(Mod_FixName(s, sv.modelname), MLV_WARN); sv.models[i] = Mod_ForName(Mod_FixName(s, sv.modelname), MLV_WARNSYNC);
else else
{ {
/*touch the file, so any packs will be referenced*/ /*touch the file, so any packs will be referenced*/
@ -5371,11 +5383,22 @@ char *PF_infokey_Internal (int entnum, const char *key)
{ {
value = ov; value = ov;
if (!strcmp(key, "ip")) if (!strcmp(key, "ip"))
NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address); {
if (svs.clients[entnum-1].state > cs_zombie && svs.clients[entnum-1].protocol == SCP_BAD)
sprintf(ov, "bot"); //bots don't have valid ips
else if (svs.clients[entnum-1].netchan.remote_address.type == NA_INVALID)
sprintf(ov, ""); //bots don't have valid ips
else
NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address);
}
else if (!strcmp(key, "realip")) else if (!strcmp(key, "realip"))
{ {
if (svs.clients[entnum-1].realip_status) if (svs.clients[entnum-1].state > cs_zombie && svs.clients[entnum-1].protocol == SCP_BAD)
sprintf(ov, "bot"); //bots don't have valid ips
else if (svs.clients[entnum-1].realip_status)
NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].realip); NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].realip);
else if (svs.clients[entnum-1].netchan.remote_address.type == NA_INVALID)
sprintf(ov, ""); //bots don't have valid ips
else //FIXME: should we report the spoofable/proxy address if the real ip is not known? else //FIXME: should we report the spoofable/proxy address if the real ip is not known?
NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address); NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address);
} }
@ -6017,7 +6040,7 @@ static void QCBUILTIN PF_checkextension (pubprogfuncs_t *prinst, struct globalva
} }
else if (!PR_EnableEBFSBuiltin(ext->builtinnames[i], 0)) else if (!PR_EnableEBFSBuiltin(ext->builtinnames[i], 0))
{ {
Con_Printf("Failed to initialise builtin \"%s\" for extension \"%s\"", ext->builtinnames[i], s); Con_Printf("Failed to initialise builtin \"%s\" for extension \"%s\"\n", ext->builtinnames[i], s);
return; //whoops, we failed. return; //whoops, we failed.
} }
} }
@ -8491,7 +8514,13 @@ int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *v
} }
else if (entnum <= sv.allocated_client_slots) else if (entnum <= sv.allocated_client_slots)
{ //woo. we found a client. { //woo. we found a client.
char *oldvalue = Info_ValueForKey(svs.clients[entnum-1].userinfo, key); char *oldvalue;
if (svs.clients[entnum-1].state == cs_free)
{
Con_DPrintf("PF_ForceInfoKey: inactive client\n");
return 0;
}
oldvalue = Info_ValueForKey(svs.clients[entnum-1].userinfo, key);
if (strcmp(oldvalue, value)) if (strcmp(oldvalue, value))
{ {
Info_SetValueForStarKey(svs.clients[entnum-1].userinfo, key, value, sizeof(svs.clients[entnum-1].userinfo)); Info_SetValueForStarKey(svs.clients[entnum-1].userinfo, key, value, sizeof(svs.clients[entnum-1].userinfo));
@ -8622,7 +8651,7 @@ static void QCBUILTIN PF_ShowPic(pubprogfuncs_t *prinst, struct globalvars_s *pr
{ //to a single client { //to a single client
entnum = G_EDICTNUM(prinst, OFS_PARM5)-1; entnum = G_EDICTNUM(prinst, OFS_PARM5)-1;
if (entnum < 0 || entnum >= sv.allocated_client_slots) if (entnum < 0 || entnum >= sv.allocated_client_slots)
PR_RunError (prinst, "WriteDest: not a client"); PR_RunError (prinst, "PF_ShowPic: not a client");
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC)) if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh. return; //need an extension for this. duh.
@ -8655,7 +8684,7 @@ static void QCBUILTIN PF_HidePic(pubprogfuncs_t *prinst, struct globalvars_s *pr
{ //to a single client { //to a single client
entnum = G_EDICTNUM(prinst, OFS_PARM1)-1; entnum = G_EDICTNUM(prinst, OFS_PARM1)-1;
if (entnum < 0 || entnum >= sv.allocated_client_slots) if (entnum < 0 || entnum >= sv.allocated_client_slots)
PR_RunError (prinst, "WriteDest: not a client"); PR_RunError (prinst, "PF_HidePic: not a client");
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC)) if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh. return; //need an extension for this. duh.
@ -8690,7 +8719,7 @@ static void QCBUILTIN PF_MovePic(pubprogfuncs_t *prinst, struct globalvars_s *pr
{ //to a single client { //to a single client
entnum = G_EDICTNUM(prinst, OFS_PARM4)-1; entnum = G_EDICTNUM(prinst, OFS_PARM4)-1;
if (entnum < 0 || entnum >= sv.allocated_client_slots) if (entnum < 0 || entnum >= sv.allocated_client_slots)
PR_RunError (prinst, "WriteDest: not a client"); PR_RunError (prinst, "PF_MovePic: not a client");
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC)) if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh. return; //need an extension for this. duh.
@ -8723,7 +8752,7 @@ static void QCBUILTIN PF_ChangePic(pubprogfuncs_t *prinst, struct globalvars_s *
{ //to a single client { //to a single client
entnum = G_EDICTNUM(prinst, OFS_PARM2)-1; entnum = G_EDICTNUM(prinst, OFS_PARM2)-1;
if (entnum < 0 || entnum >= sv.allocated_client_slots) if (entnum < 0 || entnum >= sv.allocated_client_slots)
PR_RunError (prinst, "WriteDest: not a client"); PR_RunError (prinst, "PF_ChangePic: not a client");
if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC)) if (!(svs.clients[entnum].fteprotocolextensions & PEXT_SHOWPIC))
return; //need an extension for this. duh. return; //need an extension for this. duh.
@ -9313,6 +9342,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"precache_sound", PF_precache_sound, 19, 19, 19, 0, D("string(string s)", "Precaches a sound, making it known to clients and loading it from disk. This builtin (strongly) should be called during spawn functions. This builtin must be called for the sound before the sound builtin is called, or it might not even be heard.")}, {"precache_sound", PF_precache_sound, 19, 19, 19, 0, D("string(string s)", "Precaches a sound, making it known to clients and loading it from disk. This builtin (strongly) should be called during spawn functions. This builtin must be called for the sound before the sound builtin is called, or it might not even be heard.")},
{"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.")}, {"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.")}, {"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)", "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 //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, 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.")},
@ -10155,7 +10185,7 @@ static void QCBUILTIN PF_Fixme (pubprogfuncs_t *prinst, struct globalvars_s *pr_
Con_Printf("\n"); Con_Printf("\n");
if (progstype == PROG_QW) if (progstype == PROG_QW && (binum >= 83 && binum < 105))
prinst->RunError(prinst, "\nBuiltin %i:%s not implemented.\nMods designed for mvdsv may need pr_imitatemvdsv to be enabled.", binum, fname); prinst->RunError(prinst, "\nBuiltin %i:%s not implemented.\nMods designed for mvdsv may need pr_imitatemvdsv to be enabled.", binum, fname);
else else
prinst->RunError(prinst, "\nBuiltin %i:%s not implemented.\nMod is not compatible.", binum, fname); prinst->RunError(prinst, "\nBuiltin %i:%s not implemented.\nMod is not compatible.", binum, fname);
@ -10851,6 +10881,7 @@ void PR_DumpPlatform_f(void)
{"SOLID_BSP", "const float", QW|NQ|CS, "Does not collide against other SOLID_BSP entities. Normally paired with MOVETYPE_PUSH.", SOLID_BSP}, {"SOLID_BSP", "const float", QW|NQ|CS, "Does not collide against other SOLID_BSP entities. Normally paired with MOVETYPE_PUSH.", SOLID_BSP},
{"SOLID_CORPSE", "const float", QW|NQ|CS, "Non-solid to SOLID_SLIDEBOX or other SOLID_CORPSE entities. For hitscan weapons to hit corpses, change the player's .solid value to SOLID_BBOX or so, perform the traceline, then revert the player's .solid value.", SOLID_CORPSE}, {"SOLID_CORPSE", "const float", QW|NQ|CS, "Non-solid to SOLID_SLIDEBOX or other SOLID_CORPSE entities. For hitscan weapons to hit corpses, change the player's .solid value to SOLID_BBOX or so, perform the traceline, then revert the player's .solid value.", SOLID_CORPSE},
{"SOLID_LADDER", "const float", QW|NQ|CS, "Obsolete and may be removed at some point. Use skin=CONTENT_LADDER and solid_bsp or solid_trigger instead.", SOLID_LADDER}, {"SOLID_LADDER", "const float", QW|NQ|CS, "Obsolete and may be removed at some point. Use skin=CONTENT_LADDER and solid_bsp or solid_trigger instead.", SOLID_LADDER},
{"SOLID_PORTAL", "const float", QW|NQ|CS, "CSG subtraction volume combined with entity transformations on impact.", SOLID_PORTAL},
{"SOLID_PHYSICS_BOX", "const float", QW|NQ|CS, NULL, SOLID_PHYSICS_BOX}, {"SOLID_PHYSICS_BOX", "const float", QW|NQ|CS, NULL, SOLID_PHYSICS_BOX},
{"SOLID_PHYSICS_SPHERE", "const float", QW|NQ|CS, NULL, SOLID_PHYSICS_SPHERE}, {"SOLID_PHYSICS_SPHERE", "const float", QW|NQ|CS, NULL, SOLID_PHYSICS_SPHERE},
{"SOLID_PHYSICS_CAPSULE", "const float", QW|NQ|CS, NULL, SOLID_PHYSICS_CAPSULE}, {"SOLID_PHYSICS_CAPSULE", "const float", QW|NQ|CS, NULL, SOLID_PHYSICS_CAPSULE},
@ -11000,6 +11031,14 @@ void PR_DumpPlatform_f(void)
{"SERVERKEY_PROTOCOL", "const string", CS, "The protocol we are connected to the server with.", 0, "\"protocol\""}, {"SERVERKEY_PROTOCOL", "const string", CS, "The protocol we are connected to the server with.", 0, "\"protocol\""},
{"SERVERKEY_MAXPLAYERS","const string", CS, "The protocol we are connected to the server with.", 0, "\"maxplayers\""}, {"SERVERKEY_MAXPLAYERS","const string", CS, "The protocol we are connected to the server with.", 0, "\"maxplayers\""},
{"STUFFCMD_IGNOREINDEMO","const float", QW|NQ, "The protocol we are connected to the server with.", STUFFCMD_IGNOREINDEMO},
{"STUFFCMD_DEMOONLY", "const float", QW|NQ, "The protocol we are connected to the server with.", STUFFCMD_DEMOONLY},
{"SOUND_RELIABLE", "const float", QW|NQ, "The sound will be sent reliably, and without regard to phs.", CF_RELIABLE},
{"SOUND_FORCELOOP", "const float", QW|NQ|CS,"The sound will restart once it reaches the end of the sample.", CF_FORCELOOP},
{"SOUND_NOSPACIALISE", "const float", QW|NQ|CS,"The different audio channels are played at the same volume regardless of which way the player is facing, without needing to use 0 attenuation.", CF_NOSPACIALISE},
{"SOUND_ABSVOLUME", "const float", QW|NQ|CS,"The sample's volume is not scaled by the volume cvar. Use with caution", CF_ABSVOLUME},
// edict.flags // edict.flags
{"FL_FLY", "const float", QW|NQ|CS, NULL, FL_FLY}, {"FL_FLY", "const float", QW|NQ|CS, NULL, FL_FLY},
{"FL_SWIM", "const float", QW|NQ|CS, NULL, FL_SWIM}, {"FL_SWIM", "const float", QW|NQ|CS, NULL, FL_SWIM},

View file

@ -744,7 +744,7 @@ static int bi_lua_stuffcmd(lua_State *L)
entnum = lua.tointegerx(L, -1, NULL); entnum = lua.tointegerx(L, -1, NULL);
str = lua.tolstring(L, 2, NULL); str = lua.tolstring(L, 2, NULL);
PF_stuffcmd_Internal(entnum, str); PF_stuffcmd_Internal(entnum, str, 0);
return 0; return 0;
} }
static int bi_lua_centerprint(lua_State *L) static int bi_lua_centerprint(lua_State *L)

View file

@ -1757,10 +1757,12 @@ void QDECL Q1QVMPF_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed,
qboolean PR_LoadQ1QVM(void) qboolean PR_LoadQ1QVM(void)
{ {
static int writable_int;
static float writable; static float writable;
static float dimensionsend = 255; static float dimensionsend = 255;
static float dimensiondefault = 255; static float dimensiondefault = 255;
static float physics_mode = 2; static float physics_mode = 2;
static vec3_t defaultgravity = {0,0,-1};
int i; int i;
gameDataN_t *gd, gdm; gameDataN_t *gd, gdm;
gameData32_t *gd32; gameData32_t *gd32;
@ -1923,6 +1925,15 @@ qboolean PR_LoadQ1QVM(void)
pr_global_ptrs->dimension_default = &dimensiondefault; pr_global_ptrs->dimension_default = &dimensiondefault;
pr_global_ptrs->dimension_send = &dimensionsend; pr_global_ptrs->dimension_send = &dimensionsend;
pr_global_ptrs->physics_mode = &physics_mode; pr_global_ptrs->physics_mode = &physics_mode;
pr_global_ptrs->trace_brush_id = &writable_int;
pr_global_ptrs->trace_brush_faceid = &writable_int;
pr_global_ptrs->global_gravitydir = &defaultgravity;
// ensureglobal(input_timelength, input_timelength_default);
// ensureglobal(input_impulse, input_impulse_default);
// ensureglobal(input_angles, input_angles_default);
// ensureglobal(input_movevalues, input_movevalues_default);
// ensureglobal(input_buttons, input_buttons_default);
dimensionsend = dimensiondefault = 255; dimensionsend = dimensiondefault = 255;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)

View file

@ -93,6 +93,7 @@ typedef struct nqglobalvars_s
vec3_t *input_angles; vec3_t *input_angles;
vec3_t *input_movevalues; vec3_t *input_movevalues;
float *input_buttons; float *input_buttons;
vec3_t *global_gravitydir;
float *spawnparamglobals[NUM_SPAWN_PARMS]; float *spawnparamglobals[NUM_SPAWN_PARMS];
int *serverid; int *serverid;
} globalptrs_t; } globalptrs_t;

View file

@ -381,6 +381,9 @@ enum
#define SPECPRINT_SPRINT 0x2 #define SPECPRINT_SPRINT 0x2
#define SPECPRINT_STUFFCMD 0x4 #define SPECPRINT_STUFFCMD 0x4
#define STUFFCMD_IGNOREINDEMO ( 1<<0) // do not put in mvd demo
#define STUFFCMD_DEMOONLY ( 1<<1) // put in mvd demo only
typedef struct client_s typedef struct client_s
{ {
client_conn_state_t state; client_conn_state_t state;
@ -748,18 +751,23 @@ typedef struct
//============================================================================= //=============================================================================
#define SVSTATS_PERIOD 10
#define STATFRAMES 100
typedef struct typedef struct
{ {
double active; double active;
double idle; double idle;
int count; int count;
int packets; int packets;
double maxresponse; //longest (active) frame time within the current period
int maxpackets; //max packet count in a single frame
double latched_active; double latched_time; //time that the current period ends
double latched_active; //active time in the last period
double latched_idle; double latched_idle;
int latched_count;
int latched_packets; int latched_packets;
int latched_maxpackets;
double latched_maxresponse;
} svstats_t; } svstats_t;
// MAX_CHALLENGES is made large to prevent a denial // MAX_CHALLENGES is made large to prevent a denial

View file

@ -1699,7 +1699,7 @@ static void SV_Status_f (void)
{ {
int i; int i;
client_t *cl; client_t *cl;
float cpu, avg, pak; float cpu;
char *s, *p; char *s, *p;
char adr[MAX_ADR_SIZE]; char adr[MAX_ADR_SIZE];
float pi, po, bi, bo; float pi, po, bi, bo;
@ -1728,12 +1728,10 @@ static void SV_Status_f (void)
cpu = (svs.stats.latched_active+svs.stats.latched_idle); cpu = (svs.stats.latched_active+svs.stats.latched_idle);
if (cpu) if (cpu)
cpu = 100*svs.stats.latched_active/cpu; cpu = 100*svs.stats.latched_active/cpu;
avg = 1000*svs.stats.latched_active / STATFRAMES;
pak = (float)svs.stats.latched_packets/ STATFRAMES;
Con_Printf("cpu utilization : %3i%%\n",(int)cpu); Con_Printf("cpu utilization : %3i%%\n",(int)cpu);
Con_Printf("avg response time: %i ms\n",(int)avg); Con_Printf("avg response time: %i ms (%i max)\n",(int)(1000*svs.stats.latched_active/svs.stats.latched_count), (int)(1000*svs.stats.latched_maxresponse));
Con_Printf("packets/frame : %5.2f\n", pak); //not relevent as a limit. Con_Printf("packets/frame : %5.2f (%i max)\n", (float)svs.stats.latched_packets/svs.stats.latched_count, svs.stats.latched_maxpackets); //not relevent as a limit.
if (NET_GetRates(svs.sockets, &pi, &po, &bi, &bo)) if (NET_GetRates(svs.sockets, &pi, &po, &bi, &bo))
Con_Printf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit. Con_Printf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit.
Con_Printf("server uptime : %s\n", ShowTime(realtime)); Con_Printf("server uptime : %s\n", ShowTime(realtime));

View file

@ -2010,9 +2010,9 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent)
else else
{ {
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.angles[0] = (int)(ent->angles[0] * 65535/360.0f); cmd.angles[0] = (short)(ent->angles[0] * 65535/360.0f);
cmd.angles[1] = (int)(ent->angles[1] * 65535/360.0f); cmd.angles[1] = (short)(ent->angles[1] * 65535/360.0f);
cmd.angles[2] = (int)(ent->angles[2] * 65535/360.0f); cmd.angles[2] = (short)(ent->angles[2] * 65535/360.0f);
} }
if (ent->health <= 0) if (ent->health <= 0)
@ -2035,7 +2035,7 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent)
{ {
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
if (pflags & (PF_VELOCITY1<<i) ) if (pflags & (PF_VELOCITY1<<i) )
MSG_WriteShort (msg, ent->velocity[i]); MSG_WriteShort (msg, (short)(ent->velocity[i]));
} }
else else
{ {
@ -3055,11 +3055,26 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
state->lightpflags = ent->xv->pflags; state->lightpflags = ent->xv->pflags;
state->u.q1.traileffectnum = ent->xv->traileffectnum; state->u.q1.traileffectnum = ent->xv->traileffectnum;
if ((!ent->xv->gravitydir[0] && !ent->xv->gravitydir[1] && !ent->xv->gravitydir[2]) || (ent->xv->gravitydir[2] == -1)) if (ent->xv->gravitydir[2] == -1)
{ {
state->u.q1.gravitydir[0] = 0; state->u.q1.gravitydir[0] = 0;
state->u.q1.gravitydir[1] = 0; state->u.q1.gravitydir[1] = 0;
} }
else if ((!ent->xv->gravitydir[0] && !ent->xv->gravitydir[1] && !ent->xv->gravitydir[2]))// || (ent->xv->gravitydir[2] == -1))
{
vec3_t ang;
if (sv.world.g.defaultgravitydir[2] == -1)
{
state->u.q1.gravitydir[0] = 0;
state->u.q1.gravitydir[1] = 0;
}
else
{
vectoangles(sv.world.g.defaultgravitydir, ang);
state->u.q1.gravitydir[0] = ((ang[0]/360) * 256) - 192;
state->u.q1.gravitydir[1] = (ang[1]/360) * 256;
}
}
else else
{ {
vec3_t ang; vec3_t ang;

View file

@ -1858,6 +1858,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
ptr += sizeof(*client->frameunion.frames[i].resendentnum)*maxents; ptr += sizeof(*client->frameunion.frames[i].resendentnum)*maxents;
client->frameunion.frames[i].resendentbits = (void*)ptr; client->frameunion.frames[i].resendentbits = (void*)ptr;
ptr += sizeof(*client->frameunion.frames[i].resendentbits)*maxents; ptr += sizeof(*client->frameunion.frames[i].resendentbits)*maxents;
client->frameunion.frames[i].senttime = realtime;
} }
//make sure the reset is sent. //make sure the reset is sent.
@ -1870,6 +1871,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
{ {
client->frameunion.frames[i].entities.max_entities = maxpacketentities; client->frameunion.frames[i].entities.max_entities = maxpacketentities;
client->frameunion.frames[i].entities.entities = (entity_state_t*)(client->frameunion.frames+UPDATE_BACKUP) + i*client->frameunion.frames[i].entities.max_entities; client->frameunion.frames[i].entities.entities = (entity_state_t*)(client->frameunion.frames+UPDATE_BACKUP) + i*client->frameunion.frames[i].entities.max_entities;
client->frameunion.frames[i].senttime = realtime;
} }
} }
break; break;
@ -4116,6 +4118,7 @@ SV_GetConsoleCommands
Add them exactly as if they had been typed at the console Add them exactly as if they had been typed at the console
=================== ===================
*/ */
qboolean QCExternalDebuggerCommand(char *text);
void SV_GetConsoleCommands (void) void SV_GetConsoleCommands (void)
{ {
char *cmd; char *cmd;
@ -4125,8 +4128,11 @@ void SV_GetConsoleCommands (void)
cmd = Sys_ConsoleInput (); cmd = Sys_ConsoleInput ();
if (!cmd) if (!cmd)
break; break;
if (QCExternalDebuggerCommand(cmd))
continue;
Log_String(LOG_CONSOLE, cmd); Log_String(LOG_CONSOLE, cmd);
Cbuf_AddText (cmd, RESTRICT_LOCAL); Cbuf_AddText (cmd, RESTRICT_LOCAL);
Cbuf_AddText ("\n", RESTRICT_LOCAL);
} }
} }
@ -4309,18 +4315,19 @@ float SV_Frame (void)
{ {
extern cvar_t pr_imitatemvdsv; extern cvar_t pr_imitatemvdsv;
static double start, end, idletime; static double start, end, idletime;
static int oldpackets;
float oldtime; float oldtime;
qboolean isidle; qboolean isidle;
static int oldpaused; static int oldpaused;
float timedelta; float timedelta;
float delay; float delay;
COM_MainThreadWork();
start = Sys_DoubleTime (); start = Sys_DoubleTime ();
svs.stats.idle += start - end; svs.stats.idle += start - end;
end = start; end = start;
COM_MainThreadWork();
//qw qc uses this for newmis handling //qw qc uses this for newmis handling
svs.framenum++; svs.framenum++;
if (svs.framenum > 0x10000) if (svs.framenum > 0x10000)
@ -4564,16 +4571,28 @@ void SV_MVDStream_Poll(void);
// collect timing statistics // collect timing statistics
end = Sys_DoubleTime (); end = Sys_DoubleTime ();
svs.stats.active += end-start; svs.stats.active += end-start;
if (++svs.stats.count == STATFRAMES) if (svs.stats.maxresponse < end-start)
svs.stats.maxresponse = end-start;
if (svs.stats.maxpackets < svs.stats.packets-oldpackets)
svs.stats.maxpackets = svs.stats.packets-oldpackets;
svs.stats.count++;
if (svs.stats.latched_time < end)
{ {
svs.stats.latched_active = svs.stats.active; svs.stats.latched_active = svs.stats.active;
svs.stats.latched_idle = svs.stats.idle; svs.stats.latched_idle = svs.stats.idle;
svs.stats.latched_packets = svs.stats.packets; svs.stats.latched_packets = svs.stats.packets;
svs.stats.latched_count = svs.stats.count;
svs.stats.latched_maxpackets = svs.stats.maxpackets;
svs.stats.latched_maxresponse = svs.stats.maxresponse;
svs.stats.latched_time = end + SVSTATS_PERIOD;
svs.stats.active = 0; svs.stats.active = 0;
svs.stats.idle = 0; svs.stats.idle = 0;
svs.stats.packets = 0; svs.stats.packets = 0;
svs.stats.count = 0; svs.stats.count = 0;
svs.stats.maxresponse = 0;
svs.stats.maxpackets = 0;
} }
oldpackets = svs.stats.packets;
return delay; return delay;
} }

View file

@ -790,7 +790,7 @@ void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
msg = MVDWrite_Begin (dem_all, 0, 4); msg = MVDWrite_Begin (dem_all, 0, 4);
MSG_WriteByte (msg, svc_updateping); MSG_WriteByte (msg, svc_updateping);
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteShort (msg, SV_CalcPing(player, false)); MSG_WriteShort (msg, SV_CalcPing(player, false)&0xffff);
if (dosizes) if (dosizes)
msg = MVDWrite_Begin (dem_all, 0, 3); msg = MVDWrite_Begin (dem_all, 0, 3);
@ -1191,7 +1191,7 @@ qboolean SV_MVDWritePackets (int num)
MSG_WriteByte (&msg, cl->info.skinnum); MSG_WriteByte (&msg, cl->info.skinnum);
if (flags & DF_EFFECTS) if (flags & DF_EFFECTS)
MSG_WriteByte (&msg, cl->info.effects); MSG_WriteByte (&msg, cl->info.effects & 0xff);
if (flags & DF_WEAPONFRAME) if (flags & DF_WEAPONFRAME)
MSG_WriteByte (&msg, cl->info.weaponframe); MSG_WriteByte (&msg, cl->info.weaponframe);

View file

@ -94,7 +94,6 @@ void WPhys_Init(void)
#define MOVE_EPSILON 0.01 #define MOVE_EPSILON 0.01
static void WPhys_Physics_Toss (world_t *w, wedict_t *ent); static void WPhys_Physics_Toss (world_t *w, wedict_t *ent);
const vec3_t standardgravity = {0, 0, -1};
// warning: SV_CheckAllEnts defined but not used // warning: SV_CheckAllEnts defined but not used
/* /*
@ -1295,7 +1294,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0]) if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0])
gravitydir = ent->xv->gravitydir; gravitydir = ent->xv->gravitydir;
else else
gravitydir = standardgravity; gravitydir = w->g.defaultgravitydir;
// if onground, return without moving // if onground, return without moving
if ( ((int)ent->v->flags & FL_ONGROUND) ) if ( ((int)ent->v->flags & FL_ONGROUND) )
@ -1426,7 +1425,7 @@ static void WPhys_Physics_Step (world_t *w, wedict_t *ent)
if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0]) if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0])
gravitydir = ent->xv->gravitydir; gravitydir = ent->xv->gravitydir;
else else
gravitydir = standardgravity; gravitydir = w->g.defaultgravitydir;
if (-DotProduct(gravitydir, ent->v->velocity) >= (1.0 / 32.0) && (fl & FL_ONGROUND)) if (-DotProduct(gravitydir, ent->v->velocity) >= (1.0 / 32.0) && (fl & FL_ONGROUND))
{ {
@ -2153,7 +2152,7 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0]) if (ent->xv->gravitydir[2] || ent->xv->gravitydir[1] || ent->xv->gravitydir[0])
gravitydir = ent->xv->gravitydir; gravitydir = ent->xv->gravitydir;
else else
gravitydir = standardgravity; gravitydir = w->g.defaultgravitydir;
if (!WPhys_CheckWater (w, ent) && ! ((int)ent->v->flags & FL_WATERJUMP) ) if (!WPhys_CheckWater (w, ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
WPhys_AddGravity (w, ent, gravitydir, ent->xv->gravity); WPhys_AddGravity (w, ent, gravitydir, ent->xv->gravity);
@ -2283,6 +2282,14 @@ void World_Physics_Frame(world_t *w)
wedict_t *ent; wedict_t *ent;
extern cvar_t sv_nqplayerphysics; extern cvar_t sv_nqplayerphysics;
if (w->g.defaultgravitydir)
{
w->g.defaultgravitydir[0] = 0;
w->g.defaultgravitydir[1] = 0;
w->g.defaultgravitydir[2] = -1;
VectorNormalize(w->g.defaultgravitydir);
}
w->framenum++; w->framenum++;
i = *w->g.physics_mode; i = *w->g.physics_mode;
@ -2456,9 +2463,9 @@ qboolean SV_Physics (void)
SV_PreRunCmd(); SV_PreRunCmd();
ucmd.msec = ms; ucmd.msec = ms;
ucmd.angles[0] = (int)(sv_player->v->v_angle[0] * (65535/360.0f)); ucmd.angles[0] = (short)(sv_player->v->v_angle[0] * (65535/360.0f));
ucmd.angles[1] = (int)(sv_player->v->v_angle[1] * (65535/360.0f)); ucmd.angles[1] = (short)(sv_player->v->v_angle[1] * (65535/360.0f));
ucmd.angles[2] = (int)(sv_player->v->v_angle[2] * (65535/360.0f)); ucmd.angles[2] = (short)(sv_player->v->v_angle[2] * (65535/360.0f));
ucmd.forwardmove = sv_player->xv->movement[0]; ucmd.forwardmove = sv_player->xv->movement[0];
ucmd.sidemove = sv_player->xv->movement[1]; ucmd.sidemove = sv_player->xv->movement[1];
ucmd.upmove = sv_player->xv->movement[2]; ucmd.upmove = sv_player->xv->movement[2];

View file

@ -932,19 +932,39 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
if (sv.mvdrecording && ((demo.recorder.fteprotocolextensions & with) == with) && !(demo.recorder.fteprotocolextensions & without)) if (sv.mvdrecording && ((demo.recorder.fteprotocolextensions & with) == with) && !(demo.recorder.fteprotocolextensions & without))
{ {
sizebuf_t *msg; sizebuf_t *msg;
if (!mask)
switch(to)
{ {
/*no distinction between reliable or not*/ //mvds have no idea where the receiver's camera will be.
msg = MVDWrite_Begin(dem_single, pnum, sv.multicast.cursize); //as such, they cannot have any support for pvs/phs
} case MULTICAST_INIT:
else default:
{ case MULTICAST_ALL_R:
if (reliable) case MULTICAST_PHS_R:
case MULTICAST_PVS_R:
msg = MVDWrite_Begin(dem_all, 0, sv.multicast.cursize);
break;
case MULTICAST_ALL:
case MULTICAST_PHS:
case MULTICAST_PVS:
msg = &demo.datagram;
break;
//mvds are all reliables really.
case MULTICAST_ONE_R:
case MULTICAST_ONE:
if (svprogfuncs)
{ {
msg = MVDWrite_Begin(dem_all, 0, sv.multicast.cursize); edict_t *ent = PROG_TO_EDICT(svprogfuncs, pr_global_struct->msg_entity);
pnum = NUM_FOR_EDICT(svprogfuncs, ent) - 1;
} }
else else
msg = &demo.datagram; {
pnum = 0; //FIXME
Con_Printf("SV_MulticastProtExt: unsupported unicast\n");
}
msg = MVDWrite_Begin(dem_single, pnum, sv.multicast.cursize);
break;
} }
SZ_Write(msg, sv.multicast.data, sv.multicast.cursize); SZ_Write(msg, sv.multicast.data, sv.multicast.cursize);
} }

View file

@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static HANDLE hconsoleout; static HANDLE hconsoleout;
extern int isPlugin; //if 2, we qcdebug to external program
qboolean WinNT; //if true, use utf-16 file paths. if false, hope that paths are in ascii. qboolean WinNT; //if true, use utf-16 file paths. if false, hope that paths are in ascii.
@ -1358,7 +1359,10 @@ void Sys_Init (void)
Cmd_AddCommand("hide", Sys_HideConsole); Cmd_AddCommand("hide", Sys_HideConsole);
hconsoleout = GetStdHandle(STD_OUTPUT_HANDLE); if (isPlugin)
hconsoleout = CreateFileA("CONOUT$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
else
hconsoleout = GetStdHandle(STD_OUTPUT_HANDLE);
// SetConsoleCP(CP_UTF8); // SetConsoleCP(CP_UTF8);
// SetConsoleOutputCP(CP_UTF8); // SetConsoleOutputCP(CP_UTF8);
@ -1386,6 +1390,7 @@ void StartQuakeServer(void)
{ {
quakeparms_t parms; quakeparms_t parms;
static char bindir[MAX_OSPATH]; static char bindir[MAX_OSPATH];
int c;
memset(&parms, 0, sizeof(parms)); memset(&parms, 0, sizeof(parms));
@ -1400,6 +1405,23 @@ void StartQuakeServer(void)
TL_InitLanguages(parms.basedir); TL_InitLanguages(parms.basedir);
c = COM_CheckParm("-qcdebug");
if (c)
isPlugin = 3;
else
{
c = COM_CheckParm("-plugin");
if (c)
{
if (c < com_argc && !strcmp(com_argv[c+1], "qcdebug"))
isPlugin = 2;
else
isPlugin = 1;
}
else
isPlugin = 0;
}
SV_Init (&parms); SV_Init (&parms);
// run one frame immediately for first heartbeat // run one frame immediately for first heartbeat

View file

@ -2012,8 +2012,8 @@ void SV_DarkPlacesDownloadChunk(client_t *cl, sizebuf_t *msg)
size = 1024; //fixme size = 1024; //fixme
if (size > cl->datagram.maxsize - cl->datagram.cursize) if (size > msg->maxsize - msg->cursize)
size = cl->datagram.maxsize - cl->datagram.cursize - 16; size = msg->maxsize - msg->cursize - 16;
if (size > MAXDPDOWNLOADCHUNK) //don't clog it too much if (size > MAXDPDOWNLOADCHUNK) //don't clog it too much
size = MAXDPDOWNLOADCHUNK; size = MAXDPDOWNLOADCHUNK;
@ -2843,6 +2843,7 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
vfsfile_t *f = FS_OpenVFS(name+8, "rb", FS_ROOT); vfsfile_t *f = FS_OpenVFS(name+8, "rb", FS_ROOT);
if (f) if (f)
{ {
loc->len = VFS_GETLEN(f);
VFS_CLOSE(f); VFS_CLOSE(f);
return -5; //found package return -5; //found package
} }
@ -6533,7 +6534,11 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
pmove.player_maxs[1] = sv_player->v->maxs[1]; pmove.player_maxs[1] = sv_player->v->maxs[1];
pmove.player_maxs[2] = sv_player->v->maxs[2]; pmove.player_maxs[2] = sv_player->v->maxs[2];
VectorCopy(sv_player->xv->gravitydir, pmove.gravitydir); if (sv_player->xv->gravitydir[2] || sv_player->xv->gravitydir[1] || sv_player->xv->gravitydir[0])
VectorCopy(sv_player->xv->gravitydir, pmove.gravitydir);
else
VectorCopy(sv.world.g.defaultgravitydir, pmove.gravitydir);
VectorCopy(sv_player->v->origin, pmove.origin); VectorCopy(sv_player->v->origin, pmove.origin);
VectorCopy(sv_player->v->oldorigin, pmove.safeorigin); VectorCopy(sv_player->v->oldorigin, pmove.safeorigin);
pmove.safeorigin_known = true; pmove.safeorigin_known = true;

View file

@ -1976,7 +1976,12 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
if (touch == clip.passedict) if (touch == clip.passedict)
continue; continue;
if (touch->v->solid == SOLID_TRIGGER || touch->v->solid == SOLID_LADDER) if (touch->v->solid == SOLID_TRIGGER || touch->v->solid == SOLID_LADDER)
Host_Error ("Trigger (%s) in clipping list", PR_GetString(w->progs, touch->v->classname)); {
if (!(clip.type & MOVE_TRIGGERS))
continue;
if (!((int)touch->v->flags & FL_FINDABLE_NONSOLID))
continue;
}
if (clip.type & MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP) if (clip.type & MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP)
continue; continue;

View file

@ -174,24 +174,10 @@
<File <File
RelativePath=".\hud_common.c" RelativePath=".\hud_common.c"
> >
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath=".\hud_editor.c" RelativePath=".\hud_editor.c"
> >
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath="..\plugin.c" RelativePath="..\plugin.c"

View file

@ -640,6 +640,22 @@ qintptr_t EZHud_Draw(qintptr_t *args)
cls.mvdplayback = !strcmp(val, "mvd"); cls.mvdplayback = !strcmp(val, "mvd");
cls.demoplayback = strcmp(val, ""); cls.demoplayback = strcmp(val, "");
{
static cvar_t *pscr_viewsize = NULL;
int size;
if (!pscr_viewsize)
pscr_viewsize = pCvar_GetNVFDG("viewsize", "100", 0, NULL, NULL);
size = cl.intermission ? 120 : pscr_viewsize->value;
if (size >= 120)
sb_lines = 0; // no status bar at all
else if (size >= 110)
sb_lines = 24; // no inventory
else
sb_lines = 24 + 16 + 8;
}
//cl.faceanimtime //cl.faceanimtime
//cl.simvel //cl.simvel
//cl.item_gettime //cl.item_gettime

View file

@ -129,10 +129,9 @@ char *TP_ItemName(unsigned int itbit);
void Replace_In_String(char *string, size_t strsize, char leadchar, int patterns, ...); void Replace_In_String(char *string, size_t strsize, char leadchar, int patterns, ...);
static qbool Utils_RegExpMatch(char *regexp, char *term) {return true;} static qbool Utils_RegExpMatch(char *regexp, char *term) {return true;}
#define strlen_color strlen
#define clamp(v,min,max) v=bound(min,v,max) #define clamp(v,min,max) v=bound(min,v,max)
#define strlen_color(line) (pDraw_StringWidth(8, 0, line)/8.0)
#define TIMETYPE_CLOCK 0 #define TIMETYPE_CLOCK 0
#define TIMETYPE_GAMECLOCK 1 #define TIMETYPE_GAMECLOCK 1

View file

@ -796,7 +796,6 @@ void SCR_HUD_DrawClock(hud_t *hud)
// draw HUD notify // draw HUD notify
// //
#ifdef HAXX
static void SCR_HUD_DrawNotify(hud_t* hud) static void SCR_HUD_DrawNotify(hud_t* hud)
{ {
static cvar_t* hud_notify_rows = NULL; static cvar_t* hud_notify_rows = NULL;
@ -817,15 +816,20 @@ static void SCR_HUD_DrawNotify(hud_t* hud)
hud_notify_time = HUD_FindVar(hud, "time"); hud_notify_time = HUD_FindVar(hud, "time");
} }
height = Q_rint((con_linewidth / hud_notify_cols->ival) * hud_notify_rows->ival * 8 * hud_notify_scale->value); height = hud_notify_rows->ival * 8 * hud_notify_scale->value;
width = 8 * hud_notify_cols->ival * hud_notify_scale->value; width = 8 * hud_notify_cols->ival * hud_notify_scale->value;
if (HUD_PrepareDraw(hud, width, height, &x, &y)) if (HUD_PrepareDraw(hud, width, height, &x, &y))
{ {
SCR_DrawNotify(x, y, hud_notify_scale->value, hud_notify_time->ival, hud_notify_rows->ival, hud_notify_cols->ival); pCvar_SetFloat("con_notify_x", (float)x / vid.width);
pCvar_SetFloat("con_notify_y", (float)y / vid.height);
pCvar_SetFloat("con_notify_w", (float)width / vid.width);
pCvar_SetFloat("con_numnotifylines",(int)(height/(8*hud_notify_scale->value) + 0.01));
pCvar_SetFloat("con_notifytime", (float)hud_notify_time->ival);
pCvar_SetFloat("con_textsize", 8.0 * hud_notify_scale->value);
// SCR_DrawNotify(x, y, hud_notify_scale->value, hud_notify_time->ival, hud_notify_rows->ival, hud_notify_cols->ival);
} }
} }
#endif
//--------------------- //---------------------
// //
@ -2253,11 +2257,71 @@ void SCR_HUD_DrawArmor(hud_t *hud)
scale->value, style->value, digits->value, align->string); scale->value, style->value, digits->value, align->string);
} }
void Draw_AMFStatLoss (int stat, hud_t* hud); //void Draw_AMFStatLoss (int stat, hud_t* hud);
#if HAXX static int vxdamagecount, vxdamagecount_time, vxdamagecount_oldhealth;
static int vxdamagecountarmour, vxdamagecountarmour_time, vxdamagecountarmour_oldhealth;
void Amf_Reset_DamageStats(void)
{
vxdamagecount = vxdamagecount_time = vxdamagecount_oldhealth = 0;
vxdamagecountarmour = vxdamagecountarmour_time = vxdamagecountarmour_oldhealth = 0;
}
void Draw_AMFStatLoss (int stat, hud_t* hud) {
//fixme: should reset these on pov change
int * vxdmgcnt, * vxdmgcnt_t, * vxdmgcnt_o;
int x;
float alpha;
int elem;
if (stat == STAT_HEALTH) {
vxdmgcnt = &vxdamagecount;
vxdmgcnt_t = &vxdamagecount_time;
vxdmgcnt_o = &vxdamagecount_oldhealth;
x = 136;
elem = 0;
} else {
vxdmgcnt = &vxdamagecountarmour;
vxdmgcnt_t = &vxdamagecountarmour_time;
vxdmgcnt_o = &vxdamagecountarmour_oldhealth;
x = 24;
elem = 1;
}
//VULT STAT LOSS
//Pretty self explanitory, I just thought it would be a nice feature to go with my "what the hell is going on?" theme
//and obscure even more of the screen
if (cl.stats[stat] < (*vxdmgcnt_o - 1))
{
if (*vxdmgcnt_t > cl.time) //add to damage
*vxdmgcnt = *vxdmgcnt + (*vxdmgcnt_o - cl.stats[stat]);
else
*vxdmgcnt = *vxdmgcnt_o - cl.stats[stat];
*vxdmgcnt_t = cl.time + 2 * (HUD_FindVar(hud, "duration")->value);
}
*vxdmgcnt_o = cl.stats[stat];
if (*vxdmgcnt_t > cl.time)
alpha = min(1, (*vxdmgcnt_t - cl.time));
else
alpha = 0;
pDraw_Colour4f(1,1,1,alpha);
{
static cvar_t *scale[2] = {NULL}, *style[2], *digits[2], *align[2];
if (scale[elem] == NULL) // first time called
{
scale[elem] = HUD_FindVar(hud, "scale");
style[elem] = HUD_FindVar(hud, "style");
digits[elem] = HUD_FindVar(hud, "digits");
align[elem] = HUD_FindVar(hud, "align");
}
SCR_HUD_DrawNum (hud, abs(*vxdmgcnt), 1,
scale[elem]->value, style[elem]->value, digits[elem]->ival, align[elem]->string);
}
pDraw_Colour4f(1,1,1,1);
}
static void SCR_HUD_DrawHealthDamage(hud_t *hud) static void SCR_HUD_DrawHealthDamage(hud_t *hud)
{ {
// TODO: This is very naughty, HUD_PrepareDraw(hud, width, height, &x, &y); MUST be called.
Draw_AMFStatLoss (STAT_HEALTH, hud); Draw_AMFStatLoss (STAT_HEALTH, hud);
if (HUD_Stats(STAT_HEALTH) <= 0) if (HUD_Stats(STAT_HEALTH) <= 0)
{ {
@ -2267,10 +2331,8 @@ static void SCR_HUD_DrawHealthDamage(hud_t *hud)
static void SCR_HUD_DrawArmorDamage(hud_t *hud) static void SCR_HUD_DrawArmorDamage(hud_t *hud)
{ {
// TODO: NAUGHTY!! HUD_PrepareDraw(hud, width, height, &x, &y); plz
Draw_AMFStatLoss (STAT_ARMOR, hud); Draw_AMFStatLoss (STAT_ARMOR, hud);
} }
#endif
void SCR_HUD_DrawAmmo(hud_t *hud, int num, void SCR_HUD_DrawAmmo(hud_t *hud, int num,
float scale, int style, int digits, char *s_align) float scale, int style, int digits, char *s_align)
@ -5760,18 +5822,18 @@ void SCR_HUD_DrawScoresTeam(hud_t *hud)
void SCR_HUD_DrawScoresEnemy(hud_t *hud) void SCR_HUD_DrawScoresEnemy(hud_t *hud)
{ {
static cvar_t *scale = NULL, *style, *digits, *align, *colorize; static cvar_t *scale = NULL, *style, *digits, *align, *colorize;
int value = 0; int value = 0;
int i; int i;
if (scale == NULL) // first time called if (scale == NULL) // first time called
{ {
scale = HUD_FindVar(hud, "scale"); scale = HUD_FindVar(hud, "scale");
style = HUD_FindVar(hud, "style"); style = HUD_FindVar(hud, "style");
digits = HUD_FindVar(hud, "digits"); digits = HUD_FindVar(hud, "digits");
align = HUD_FindVar(hud, "align"); align = HUD_FindVar(hud, "align");
colorize = HUD_FindVar(hud, "colorize"); colorize = HUD_FindVar(hud, "colorize");
} }
// //
// AAS: voodoo, again // AAS: voodoo, again
@ -5806,23 +5868,23 @@ void SCR_HUD_DrawScoresEnemy(hud_t *hud)
} }
} }
SCR_HUD_DrawNum(hud, value, (colorize->ival) ? (value < 0 || colorize->ival > 1) : false, scale->value, style->value, digits->value, align->string); SCR_HUD_DrawNum(hud, value, (colorize->ival) ? (value < 0 || colorize->ival > 1) : false, scale->value, style->value, digits->value, align->string);
} }
void SCR_HUD_DrawScoresDifference(hud_t *hud) void SCR_HUD_DrawScoresDifference(hud_t *hud)
{ {
static cvar_t *scale = NULL, *style, *digits, *align, *colorize; static cvar_t *scale = NULL, *style, *digits, *align, *colorize;
int value = 0; int value = 0;
int i; int i;
if (scale == NULL) // first time called if (scale == NULL) // first time called
{ {
scale = HUD_FindVar(hud, "scale"); scale = HUD_FindVar(hud, "scale");
style = HUD_FindVar(hud, "style"); style = HUD_FindVar(hud, "style");
digits = HUD_FindVar(hud, "digits"); digits = HUD_FindVar(hud, "digits");
align = HUD_FindVar(hud, "align"); align = HUD_FindVar(hud, "align");
colorize = HUD_FindVar(hud, "colorize"); colorize = HUD_FindVar(hud, "colorize");
} }
// //
// AAS: more voodoo // AAS: more voodoo
@ -5876,23 +5938,23 @@ void SCR_HUD_DrawScoresDifference(hud_t *hud)
} }
} }
SCR_HUD_DrawNum(hud, value, (colorize->ival) ? (value < 0 || colorize->ival > 1) : false, scale->value, style->value, digits->value, align->string); SCR_HUD_DrawNum(hud, value, (colorize->ival) ? (value < 0 || colorize->ival > 1) : false, scale->value, style->value, digits->value, align->string);
} }
void SCR_HUD_DrawScoresPosition(hud_t *hud) void SCR_HUD_DrawScoresPosition(hud_t *hud)
{ {
static cvar_t *scale = NULL, *style, *digits, *align, *colorize; static cvar_t *scale = NULL, *style, *digits, *align, *colorize;
int value = 0; int value = 0;
int i; int i;
if (scale == NULL) // first time called if (scale == NULL) // first time called
{ {
scale = HUD_FindVar(hud, "scale"); scale = HUD_FindVar(hud, "scale");
style = HUD_FindVar(hud, "style"); style = HUD_FindVar(hud, "style");
digits = HUD_FindVar(hud, "digits"); digits = HUD_FindVar(hud, "digits");
align = HUD_FindVar(hud, "align"); align = HUD_FindVar(hud, "align");
colorize = HUD_FindVar(hud, "colorize"); colorize = HUD_FindVar(hud, "colorize");
} }
// //
// AAS: someone, please stop me // AAS: someone, please stop me
@ -5924,7 +5986,7 @@ void SCR_HUD_DrawScoresPosition(hud_t *hud)
} }
} }
SCR_HUD_DrawNum(hud, value, (colorize->ival) ? (value < 0 || colorize->ival > 1) : false, scale->value, style->value, digits->value, align->string); SCR_HUD_DrawNum(hud, value, (colorize->ival) ? (value < 0 || colorize->ival > 1) : false, scale->value, style->value, digits->value, align->string);
} }
/* /*
@ -5943,13 +6005,13 @@ void SCR_HUD_DrawScoresBar(hud_t *hud)
char buf[256]; char buf[256];
char c, *out, *temp, *in; char c, *out, *temp, *in;
if (scale == NULL) // first time called if (scale == NULL) // first time called
{ {
scale = HUD_FindVar(hud, "scale"); scale = HUD_FindVar(hud, "scale");
style = HUD_FindVar(hud, "style"); style = HUD_FindVar(hud, "style");
format_big = HUD_FindVar(hud, "format_big"); format_big = HUD_FindVar(hud, "format_big");
format_small= HUD_FindVar(hud, "format_small"); format_small= HUD_FindVar(hud, "format_small");
} }
// //
// AAS: nightmare comes back // AAS: nightmare comes back
@ -6170,7 +6232,7 @@ void SCR_HUD_DrawBarArmor(hud_t *hud)
qbool alive = cl.stats[STAT_HEALTH] > 0; qbool alive = cl.stats[STAT_HEALTH] > 0;
if (width == NULL) // first time called if (width == NULL) // first time called
{ {
width = HUD_FindVar(hud, "width"); width = HUD_FindVar(hud, "width");
height = HUD_FindVar(hud, "height"); height = HUD_FindVar(hud, "height");
direction = HUD_FindVar(hud, "direction"); direction = HUD_FindVar(hud, "direction");
@ -6190,7 +6252,7 @@ void SCR_HUD_DrawBarArmor(hud_t *hud)
{ {
SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_unnatural->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_unnatural->vec4, x, y, width->ival, height->ival);
} }
else if (HUD_Stats(STAT_ITEMS) & IT_ARMOR3 && alive) else if (HUD_Stats(STAT_ITEMS) & IT_ARMOR3 && alive)
{ {
SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_noarmor->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_noarmor->vec4, x, y, width->ival, height->ival);
SCR_HUD_DrawBar(direction->ival, armor, 200.0, color_ra->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, armor, 200.0, color_ra->vec4, x, y, width->ival, height->ival);
@ -6200,7 +6262,7 @@ void SCR_HUD_DrawBarArmor(hud_t *hud)
SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_noarmor->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_noarmor->vec4, x, y, width->ival, height->ival);
SCR_HUD_DrawBar(direction->ival, armor, 150.0, color_ya->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, armor, 150.0, color_ya->vec4, x, y, width->ival, height->ival);
} }
else if (HUD_Stats(STAT_ITEMS) & IT_ARMOR1 && alive) else if (HUD_Stats(STAT_ITEMS) & IT_ARMOR1 && alive)
{ {
SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_noarmor->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, 100, 100.0, color_noarmor->vec4, x, y, width->ival, height->ival);
SCR_HUD_DrawBar(direction->ival, armor, 100.0, color_ga->vec4, x, y, width->ival, height->ival); SCR_HUD_DrawBar(direction->ival, armor, 100.0, color_ga->vec4, x, y, width->ival, height->ival);
@ -6219,7 +6281,7 @@ void SCR_HUD_DrawBarHealth(hud_t *hud)
int health = cl.stats[STAT_HEALTH]; int health = cl.stats[STAT_HEALTH];
if (width == NULL) // first time called if (width == NULL) // first time called
{ {
width = HUD_FindVar(hud, "width"); width = HUD_FindVar(hud, "width");
height = HUD_FindVar(hud, "height"); height = HUD_FindVar(hud, "height");
direction = HUD_FindVar(hud, "direction"); direction = HUD_FindVar(hud, "direction");
@ -6262,60 +6324,177 @@ void SCR_HUD_DrawBarHealth(hud_t *hud)
} }
} }
#ifdef WITH_PNG
void SCR_HUD_DrawOwnFrags(hud_t *hud) void SCR_HUD_DrawOwnFrags(hud_t *hud)
{ {
// not implemented yet: scale, color // not implemented yet: scale, color
// fixme: add appropriate opengl functions that will add alpha, scale and color // fixme: add appropriate opengl functions that will add alpha, scale and color
int width = VX_OwnFragTextLen() * LETTERWIDTH; char ownfragtext[256];
int height = LETTERHEIGHT; float age;
int x, y; int width;
double alpha; int height = 8;
static cvar_t int x, y;
*hud_ownfrags_timeout = NULL, double alpha;
*hud_ownfrags_scale = NULL; static cvar_t
// *hud_ownfrags_color = NULL; *hud_ownfrags_timeout = NULL,
*hud_ownfrags_scale = NULL;
// *hud_ownfrags_color = NULL;
extern qbool hud_editor; extern qbool hud_editor;
if (hud_ownfrags_timeout == NULL) // first time if (hud_ownfrags_timeout == NULL) // first time
{ {
hud_ownfrags_scale = HUD_FindVar(hud, "scale"); hud_ownfrags_scale = HUD_FindVar(hud, "scale");
// hud_ownfrags_color = HUD_FindVar(hud, "color"); // hud_ownfrags_color = HUD_FindVar(hud, "color");
hud_ownfrags_timeout = HUD_FindVar(hud, "timeout"); hud_ownfrags_timeout = HUD_FindVar(hud, "timeout");
} }
if (hud_editor) if (hud_editor)
HUD_PrepareDraw(hud, 10 * LETTERWIDTH , height * hud_ownfrags_scale->value, &x, &y); {
strcpy(ownfragtext, "Own Frags");
age = 0;
}
else if (BUILTINISVALID(GetTrackerOwnFrags))
age = pGetTrackerOwnFrags(0, ownfragtext, sizeof(ownfragtext));
else
{
strcpy(ownfragtext, "Engine does not support OwnFrags");
age = 0;
}
width = strlen(ownfragtext);
width *= hud_ownfrags_scale->value;
height *= hud_ownfrags_scale->value;
alpha = 2 - hud_ownfrags_timeout->value / age * 2;
alpha = bound(0, alpha, 1);
if (!HUD_PrepareDraw(hud, width , height, &x, &y))
return;
if (!width) if (!width)
return; return;
if (VX_OwnFragTime() > hud_ownfrags_timeout->value) if (age > hud_ownfrags_timeout->value)
return; return;
width *= hud_ownfrags_scale->value; if (age < hud_ownfrags_timeout->value)
height *= hud_ownfrags_scale->value; Draw_SString(x, y, ownfragtext, hud_ownfrags_scale->value);
}
alpha = 2 - hud_ownfrags_timeout->value / VX_OwnFragTime() * 2; static struct wstats_s *findweapon(struct wstats_s *w, size_t wc, char *wn)
alpha = bound(0, alpha, 1); {
for (; wc>0; wc--, w++)
{
if (!strcmp(wn, w->wname))
return w;
}
return NULL;
}
static void SCR_HUD_DrawWeaponStats(hud_t *hud)
{
char line[1024], *o, *i;
int width;
int height = 8;
int x, y;
static cvar_t *hud_weaponstats_scale = NULL;
static cvar_t *hud_weaponstats_fmt = NULL;
extern qbool hud_editor;
if (!HUD_PrepareDraw(hud, width , height, &x, &y)) int ws;
return; struct wstats_s wstats[16];
if (BUILTINISVALID(GetWeaponStats))
ws = pGetWeaponStats(-1, wstats, countof(wstats));
else
ws = 0;
if (VX_OwnFragTime() < hud_ownfrags_timeout->value) if (hud_editor)
Draw_SString(x, y, VX_OwnFragText(), hud_ownfrags_scale->value); {
ws = 0;
strcpy(wstats[ws].wname, "axe");
wstats[ws].hit = 20;
wstats[ws].total = 100;
ws++;
strcpy(wstats[ws].wname, "rl");
wstats[ws].hit = 60;
wstats[ws].total = 120;
ws++;
strcpy(wstats[ws].wname, "lg");
wstats[ws].hit = 20;
wstats[ws].total = 100;
ws++;
}
if (hud_weaponstats_scale == NULL) // first time
{
hud_weaponstats_scale = HUD_FindVar(hud, "scale");
hud_weaponstats_fmt = HUD_FindVar(hud, "fmt");
// "&c990sg&r:[%sg] &c099ssg&r:[%ssg] &c900rl&r:[#rl] &c009lg&r:[%lg]"
}
height = 8;
for (o = line, i = hud_weaponstats_fmt->string; ws && *i && o < line+countof(line)-1; )
{
if (i[0] == '[' && (i[1] == '%' || i[1] == '#'))
{
struct wstats_s *w;
char wname[16];
int pct = i[1]=='%', j;
i+=2;
for (j = 0; *i && j < countof(wname)-1; j++)
{
if (*i == ']')
{
i++;
break;
}
wname[j] = *i++;
}
wname[j] = 0;
w = findweapon(wstats, ws, wname);
if (pct && w && w->total)
snprintf(wname, sizeof(wname), "%.1f", (100.0 * w->hit) / w->total);
else if (pct)
snprintf(wname, sizeof(wname), "%.1f", 0.0);
else if (w)
snprintf(wname, sizeof(wname), "%u", w->hit);
else
snprintf(wname, sizeof(wname), "%u", 0);
for (j = 0; wname[j] && o < line+countof(line)-1; j++)
*o++ = wname[j];
}
else if (*i == '\n')
{
height += 8;
*o++ = *i++;
}
else
*o++ = *i++;
}
*o++ = 0;
width = 8*strlen_color(line);
width *= hud_weaponstats_scale->value;
height *= hud_weaponstats_scale->value;
if (!HUD_PrepareDraw(hud, width, height, &x, &y))
return;
Draw_SString(x, y, line, hud_weaponstats_scale->value);
} }
void SCR_HUD_DrawKeys(hud_t *hud) void SCR_HUD_DrawKeys(hud_t *hud)
{ {
char line1[4], line2[4]; char line1[32], line2[32];
int width, height, x, y; int width, height, x, y;
usermainbuttons_t b = CL_GetLastCmd(); usercmd_t b;
int i;
static cvar_t* vscale = NULL; static cvar_t* vscale = NULL;
float scale; float scale;
memset(&b, 0, sizeof(b));
if (BUILTINISVALID(GetLastInputFrame))
pGetLastInputFrame(0, &b);
if (!vscale) { if (!vscale) {
vscale = HUD_FindVar(hud, "scale"); vscale = HUD_FindVar(hud, "scale");
} }
@ -6323,27 +6502,26 @@ void SCR_HUD_DrawKeys(hud_t *hud)
scale = vscale->value; scale = vscale->value;
scale = max(0, scale); scale = max(0, scale);
i = 0; snprintf(line1, sizeof(line1), "^{%x}^{%x}^{%x}",
line1[i++] = b.attack ? 'x' + 128 : 'x'; 0xe000 + 'x' + ((b.buttons & 1)?0x80:0),
line1[i++] = b.forward ? '^' + 128 : '^'; 0xe000 + '^' + ((b.forwardmove > 0)?0x80:0),
line1[i++] = b.jump ? 'J' + 128 : 'J'; 0xe000 + 'J' + ((b.buttons & 2)?0x80:0));
line1[i++] = '\0'; snprintf(line2, sizeof(line2), "^{%x}^{%x}^{%x}",
i = 0; 0xe000 + '<' + ((b.sidemove < 0)?0x80:0),
line2[i++] = b.left ? '<' + 128 : '<'; 0xe000 + '_' + ((b.forwardmove < 0)?0x80:0),
line2[i++] = b.back ? '_' + 128 : '_'; 0xe000 + '>' + ((b.sidemove > 0)?0x80:0));
line2[i++] = b.right ? '>' + 128 : '>';
line2[i++] = '\0';
width = LETTERWIDTH * strlen(line1) * scale; width = 8 * 3 * scale;
height = LETTERHEIGHT * 2 * scale; height = 8 * 2 * scale;
if (!HUD_PrepareDraw(hud, width ,height, &x, &y)) if (!HUD_PrepareDraw(hud, width, height, &x, &y))
return; return;
Draw_SString(x, y, line1, scale); Draw_SString(x, y, line1, scale);
Draw_SString(x, y + LETTERHEIGHT*scale, line2, scale); Draw_SString(x, y + 8*scale, line2, scale);
} }
#ifdef WITH_PNG
// What stats to draw. // What stats to draw.
#define HUD_RADAR_STATS_NONE 0 #define HUD_RADAR_STATS_NONE 0
#define HUD_RADAR_STATS_BOTH_TEAMS_HOLD 1 #define HUD_RADAR_STATS_BOTH_TEAMS_HOLD 1
@ -7485,6 +7663,30 @@ void HUD_AfterDraw()
{ {
} }
#ifndef HAXX
static void SCR_HUD_DrawNotImplemented(hud_t *hud)
{
char line1[64];
int width, height, x, y;
snprintf(line1, sizeof(line1), "%s not implemented", hud->name);
width = 8 * strlen(line1);
height = 8;
if (!HUD_PrepareDraw(hud, width, height, &x, &y))
return;
Draw_SString(x, y, line1, 1);
}
#define SCR_HUD_DrawSpeed SCR_HUD_DrawNotImplemented
#define SCR_HUD_DrawTeamHoldBar SCR_HUD_DrawNotImplemented
#define SCR_HUD_DrawTeamHoldInfo SCR_HUD_DrawNotImplemented
#define SCR_HUD_DrawItemsClock SCR_HUD_DrawNotImplemented
#endif
// ---------------- // ----------------
// Init // Init
// and add some common elements to hud (clock etc) // and add some common elements to hud (clock etc)
@ -7543,7 +7745,6 @@ void CommonDraw_Init(void)
"offset","0", "offset","0",
NULL); NULL);
#ifdef HAXX
HUD_Register("notify", NULL, "Shows last console lines", HUD_Register("notify", NULL, "Shows last console lines",
HUD_PLUSMINUS, ca_disconnected, 8, SCR_HUD_DrawNotify, HUD_PLUSMINUS, ca_disconnected, 8, SCR_HUD_DrawNotify,
"0", "top", "left", "top", "0", "0", "0", "0 0 0", NULL, "0", "top", "left", "top", "0", "0", "0", "0 0 0", NULL,
@ -7552,7 +7753,6 @@ void CommonDraw_Init(void)
"scale", "1", "scale", "1",
"time", "4", "time", "4",
NULL); NULL);
#endif
// fps // fps
HUD_Register("fps", NULL, HUD_Register("fps", NULL,
@ -7622,7 +7822,6 @@ void CommonDraw_Init(void)
"period", "1", "period", "1",
NULL); NULL);
#ifdef HAXX
// init speed // init speed
HUD_Register("speed", NULL, "Shows your current running speed. It is measured over XY or XYZ axis depending on \'xyz\' property.", HUD_Register("speed", NULL, "Shows your current running speed. It is measured over XY or XYZ axis depending on \'xyz\' property.",
HUD_PLUSMINUS, ca_active, 7, SCR_HUD_DrawSpeed, HUD_PLUSMINUS, ca_active, 7, SCR_HUD_DrawSpeed,
@ -7642,7 +7841,6 @@ void CommonDraw_Init(void)
"text_align", "1", "text_align", "1",
"style", "0", "style", "0",
NULL); NULL);
#endif
// Init speed2 (half circle thingie). // Init speed2 (half circle thingie).
HUD_Register("speed2", NULL, "Shows your current running speed. It is measured over XY or XYZ axis depending on \'xyz\' property.", HUD_Register("speed2", NULL, "Shows your current running speed. It is measured over XY or XYZ axis depending on \'xyz\' property.",
@ -7993,7 +8191,6 @@ void CommonDraw_Init(void)
"pic_scalemode", "0", "pic_scalemode", "0",
NULL); NULL);
#ifdef HAXX
// healthdamage // healthdamage
HUD_Register("healthdamage", NULL, "Shows amount of damage done to your health.", HUD_Register("healthdamage", NULL, "Shows amount of damage done to your health.",
HUD_INVENTORY, ca_active, 0, SCR_HUD_DrawHealthDamage, HUD_INVENTORY, ca_active, 0, SCR_HUD_DrawHealthDamage,
@ -8015,7 +8212,6 @@ void CommonDraw_Init(void)
"digits", "3", "digits", "3",
"duration", "0.8", "duration", "0.8",
NULL); NULL);
#endif
HUD_Register("frags", NULL, "Show list of player frags in short form.", HUD_Register("frags", NULL, "Show list of player frags in short form.",
0, ca_active, 0, SCR_HUD_DrawFrags, 0, ca_active, 0, SCR_HUD_DrawFrags,
@ -8123,7 +8319,6 @@ void CommonDraw_Init(void)
NULL); NULL);
#endif // WITH_PNG #endif // WITH_PNG
#ifdef HAXX
HUD_Register("teamholdbar", NULL, "Shows how much of the level (in percent) that is currently being held by either team.", HUD_Register("teamholdbar", NULL, "Shows how much of the level (in percent) that is currently being held by either team.",
HUD_PLUSMINUS, ca_active, 0, SCR_HUD_DrawTeamHoldBar, HUD_PLUSMINUS, ca_active, 0, SCR_HUD_DrawTeamHoldBar,
"0", "top", "left", "bottom", "0", "0", "0", "0 0 0", NULL, "0", "top", "left", "bottom", "0", "0", "0", "0 0 0", NULL,
@ -8135,9 +8330,7 @@ void CommonDraw_Init(void)
"show_text", "1", "show_text", "1",
"onlytp", "0", "onlytp", "0",
NULL); NULL);
#endif
#ifdef HAXX
HUD_Register("teamholdinfo", NULL, "Shows which important items in the level that are being held by the teams.", HUD_Register("teamholdinfo", NULL, "Shows which important items in the level that are being held by the teams.",
HUD_PLUSMINUS, ca_active, 0, SCR_HUD_DrawTeamHoldInfo, HUD_PLUSMINUS, ca_active, 0, SCR_HUD_DrawTeamHoldInfo,
"0", "top", "left", "bottom", "0", "0", "0", "0 0 0", NULL, "0", "top", "left", "bottom", "0", "0", "0", "0 0 0", NULL,
@ -8148,9 +8341,7 @@ void CommonDraw_Init(void)
"style", "1", "style", "1",
"itemfilter", "quad ra ya ga mega pent rl quad", "itemfilter", "quad ra ya ga mega pent rl quad",
NULL); NULL);
#endif
#ifdef WITH_PNG
HUD_Register("ownfrags" /* jeez someone give me a better name please */, NULL, "Highlights your own frags", HUD_Register("ownfrags" /* jeez someone give me a better name please */, NULL, "Highlights your own frags",
0, ca_active, 1, SCR_HUD_DrawOwnFrags, 0, ca_active, 1, SCR_HUD_DrawOwnFrags,
"1", "screen", "center", "top", "0", "50", "0.2", "0 0 100", NULL, "1", "screen", "center", "top", "0", "50", "0.2", "0 0 100", NULL,
@ -8168,9 +8359,7 @@ void CommonDraw_Init(void)
"scale", "2", "scale", "2",
NULL NULL
); );
#endif
#ifdef HAXX
HUD_Register("itemsclock", NULL, "Displays upcoming item respawns", HUD_Register("itemsclock", NULL, "Displays upcoming item respawns",
0, ca_active, 1, SCR_HUD_DrawItemsClock, 0, ca_active, 1, SCR_HUD_DrawItemsClock,
"0", "screen", "right", "center", "0", "0", "0", "0 0 0", NULL, "0", "screen", "right", "center", "0", "0", "0", "0 0 0", NULL,
@ -8178,7 +8367,6 @@ void CommonDraw_Init(void)
"style", "0", "style", "0",
NULL NULL
); );
#endif
HUD_Register("score_team", NULL, "Own scores or team scores.", HUD_Register("score_team", NULL, "Own scores or team scores.",
0, ca_active, 0, SCR_HUD_DrawScoresTeam, 0, ca_active, 0, SCR_HUD_DrawScoresTeam,
@ -8263,6 +8451,14 @@ void CommonDraw_Init(void)
NULL NULL
); );
HUD_Register("weaponstats", NULL, "Weapon Stats",
HUD_PLUSMINUS, ca_active, 0, SCR_HUD_DrawWeaponStats,
"0", "screen", "right", "center", "0", "0", "0", "0 0 0", NULL,
"scale", "1",
"fmt", "&c990sg&r:[%sg] &c099ssg&r:[%ssg] &c900rl&r:[#rl] &c009lg&r:[%lg]",
NULL
);
/* hexum -> FIXME? this is used only for debug purposes, I wont bother to port it (it shouldnt be too difficult if anyone cares) /* hexum -> FIXME? this is used only for debug purposes, I wont bother to port it (it shouldnt be too difficult if anyone cares)
#ifdef _DEBUG #ifdef _DEBUG
HUD_Register("framegraph", NULL, "Shows different frame times for debug/profiling purposes.", HUD_Register("framegraph", NULL, "Shows different frame times for debug/profiling purposes.",

View file

@ -150,6 +150,13 @@ BUILTIN(void, GetServerInfo, (char *info, int infolen));
#define ARGNAMES ,key,value #define ARGNAMES ,key,value
BUILTIN(void, SetUserInfo, (const char *key, const char *value)); BUILTIN(void, SetUserInfo, (const char *key, const char *value));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,seat,playercmd
BUILTINR(int, GetLastInputFrame, (int seat, usercmd_t *playercmd));
#undef ARGNAMES
#define ARGNAMES ,seat,text,textsize
BUILTINR(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize));
#undef ARGNAMES
#define ARGNAMES ,pos,buffer,bufferlen #define ARGNAMES ,pos,buffer,bufferlen
BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen)); BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
@ -158,6 +165,9 @@ BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
#define ARGNAMES ,clients,maxclients,showenemies,showself #define ARGNAMES ,clients,maxclients,showenemies,showself
BUILTINR(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself)); BUILTINR(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,player,result,maxresults
BUILTINR(int, GetWeaponStats, (int player, struct wstats_s *result, unsigned int maxresults));
#undef ARGNAMES
#define ARGNAMES ,soundname #define ARGNAMES ,soundname
BUILTIN(void, LocalSound, (const char *soundname)); BUILTIN(void, LocalSound, (const char *soundname));
@ -204,6 +214,9 @@ BUILTIN(void, Draw_CharacterH, (float x, float y, float h, unsigned int flags, u
#define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(h),flags,string #define ARGNAMES ,PASSFLOAT(x),PASSFLOAT(y),PASSFLOAT(h),flags,string
BUILTIN(void, Draw_StringH, (float x, float y, float h, unsigned int flags, const char *string)); BUILTIN(void, Draw_StringH, (float x, float y, float h, unsigned int flags, const char *string));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,PASSFLOAT(h),flags,string
BUILTINR(float, Draw_StringWidth, (float h, unsigned int flags, const char *string));
#undef ARGNAMES
#define ARGNAMES ,palcol,PASSFLOAT(a) #define ARGNAMES ,palcol,PASSFLOAT(a)
BUILTIN(void, Draw_Colourpa, (int palcol, float a)); BUILTIN(void, Draw_Colourpa, (int palcol, float a));
#undef ARGNAMES #undef ARGNAMES
@ -421,6 +434,8 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(GetPlayerInfo); CHECKBUILTIN(GetPlayerInfo);
CHECKBUILTIN(LocalPlayerNumber); CHECKBUILTIN(LocalPlayerNumber);
CHECKBUILTIN(GetLocalPlayerNumbers); CHECKBUILTIN(GetLocalPlayerNumbers);
CHECKBUILTIN(GetLastInputFrame);
CHECKBUILTIN(GetTrackerOwnFrags);
CHECKBUILTIN(GetServerInfo); CHECKBUILTIN(GetServerInfo);
CHECKBUILTIN(SetUserInfo); CHECKBUILTIN(SetUserInfo);
CHECKBUILTIN(LocalSound); CHECKBUILTIN(LocalSound);
@ -428,6 +443,7 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Key_GetKeyCode); CHECKBUILTIN(Key_GetKeyCode);
CHECKBUILTIN(GetLocationName); CHECKBUILTIN(GetLocationName);
CHECKBUILTIN(GetTeamInfo); CHECKBUILTIN(GetTeamInfo);
CHECKBUILTIN(GetWeaponStats);
CHECKBUILTIN(GetNetworkInfo); CHECKBUILTIN(GetNetworkInfo);
//drawing routines //drawing routines
@ -442,6 +458,7 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Draw_String); CHECKBUILTIN(Draw_String);
CHECKBUILTIN(Draw_CharacterH); CHECKBUILTIN(Draw_CharacterH);
CHECKBUILTIN(Draw_StringH); CHECKBUILTIN(Draw_StringH);
CHECKBUILTIN(Draw_StringWidth);
CHECKBUILTIN(Draw_Colourpa); CHECKBUILTIN(Draw_Colourpa);
CHECKBUILTIN(Draw_Colourp); CHECKBUILTIN(Draw_Colourp);
CHECKBUILTIN(Draw_Colour3f); CHECKBUILTIN(Draw_Colour3f);

View file

@ -235,6 +235,8 @@ EBUILTIN(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernu
EBUILTIN(void, GetServerInfo, (char *info, int infolen)); EBUILTIN(void, GetServerInfo, (char *info, int infolen));
EBUILTIN(void, SetUserInfo, (const char *key, const char *value)); EBUILTIN(void, SetUserInfo, (const char *key, const char *value));
EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen)); EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
EBUILTIN(int, GetLastInputFrame, (int seat, usercmd_t *playercmd));
EBUILTIN(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize));
typedef struct typedef struct
{ {
@ -246,6 +248,8 @@ typedef struct
char nick[16]; char nick[16];
} teamplayerinfo_t; } teamplayerinfo_t;
EBUILTIN(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself)); EBUILTIN(int, GetTeamInfo, (teamplayerinfo_t *clients, unsigned int maxclients, int showenemies, int showself));
struct wstats_s;
EBUILTIN(int, GetWeaponStats, (int player, struct wstats_s *result, unsigned int maxresults));
typedef struct { typedef struct {
int seats; int seats;
@ -305,7 +309,8 @@ EBUILTIN(void, Draw_Line, (float x1, float y1, float x2, float y2));
EBUILTIN(void, Draw_Character, (int x, int y, unsigned int character)); EBUILTIN(void, Draw_Character, (int x, int y, unsigned int character));
EBUILTIN(void, Draw_String, (float x, float y, const char *string)); EBUILTIN(void, Draw_String, (float x, float y, const char *string));
EBUILTIN(void, Draw_CharacterH, (float x, float y, float h, unsigned int flags, unsigned int character)); EBUILTIN(void, Draw_CharacterH, (float x, float y, float h, unsigned int flags, unsigned int character));
EBUILTIN(void, Draw_StringH, (float x, float y, float h, unsigned int flags, const char *string)); EBUILTIN(void, Draw_StringH, (float x, float y, float h, unsigned int flags, const char *string)); //returns the vpixel width of the (coloured) string, in the current (variable-width) font.
EBUILTIN(float, Draw_StringWidth, (float h, unsigned int flags, const char *string));
EBUILTIN(void, Draw_Colourpa, (int palcol, float a)); EBUILTIN(void, Draw_Colourpa, (int palcol, float a));
EBUILTIN(void, Draw_Colourp, (int palcol)); EBUILTIN(void, Draw_Colourp, (int palcol));
EBUILTIN(void, Draw_Colour3f, (float r, float g, float b)); EBUILTIN(void, Draw_Colour3f, (float r, float g, float b));

View file

@ -21,7 +21,8 @@ int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs)
float _float; float _float;
int i; int i;
int use0s; int use0s;
int precision, useprepad, plus; int width, useprepad, plus;
int precision;
if (!maxlen) if (!maxlen)
return 0; return 0;
@ -33,9 +34,10 @@ maxlen--;
{ {
case '%': case '%':
plus = 0; plus = 0;
precision= 0; width= 0;
precision=-1;
useprepad=0; useprepad=0;
use0s=0; use0s= 0;
retry: retry:
switch(*(++format)) switch(*(++format))
{ {
@ -45,8 +47,13 @@ retry:
case '+': case '+':
plus = true; plus = true;
goto retry; goto retry;
case '.':
precision = 0;
while (format[1] >= '0' && format[1] <= '9')
precision = precision*10+*++format-'0';
goto retry;
case '0': case '0':
if (!precision) if (!width)
{ {
use0s=true; use0s=true;
goto retry; goto retry;
@ -60,7 +67,7 @@ retry:
case '7': case '7':
case '8': case '8':
case '9': case '9':
precision=precision*10+*format-'0'; width=width*10+*format-'0';
goto retry; goto retry;
case '%': /*emit a %*/ case '%': /*emit a %*/
if (maxlen-- == 0) if (maxlen-- == 0)
@ -71,9 +78,9 @@ retry:
string = va_arg(vargs, char *); string = va_arg(vargs, char *);
if (!string) if (!string)
string = "(null)"; string = "(null)";
if (precision) if (width)
{ {
while (*string && precision--) while (*string && width--)
{ {
if (maxlen-- == 0) if (maxlen-- == 0)
{*buffer++='\0';return tokens;} {*buffer++='\0';return tokens;}
@ -120,15 +127,15 @@ retry:
string[1] = '\0'; string[1] = '\0';
} }
precision -= 62-i; width -= 62-i;
while (precision>0) while (width>0)
{ {
string--; string--;
if (use0s) if (use0s)
*string = '0'; *string = '0';
else else
*string = ' '; *string = ' ';
precision--; width--;
} }
while (*string) while (*string)
@ -203,15 +210,15 @@ Con_Printf("%i bytes left\n", maxlen);
string[1] = '\0'; string[1] = '\0';
} }
precision -= 62-i; width -= 62-i;
/* while (precision>0) /* while (width>0)
{ {
string--; string--;
*string = ' '; *string = ' ';
precision--; width--;
} }
*/ */
while(precision>0) while(width>0)
{ {
if (maxlen-- == 0) if (maxlen-- == 0)
{*buffer++='\0';return tokens;} {*buffer++='\0';return tokens;}
@ -219,7 +226,7 @@ Con_Printf("%i bytes left\n", maxlen);
*buffer++ = '0'; *buffer++ = '0';
else else
*buffer++ = ' '; *buffer++ = ' ';
precision--; width--;
} }
while (*string) while (*string)
@ -270,9 +277,11 @@ Con_Printf("%i bytes left\n", maxlen);
_float -= (int)_float; _float -= (int)_float;
i = 0; i = 0;
tempbuffer[i++] = '.'; tempbuffer[i++] = '.';
if (precision < 0)
precision = 7;
while(_float - (int)_float) while(_float - (int)_float)
{ {
if (i + _int > 7) //remove the excess presision. if (i > precision) //remove the excess presision.
break; break;
_float*=10; _float*=10;

View file

@ -87,10 +87,11 @@ alpha <value>
alphadelta <value> alphadelta <value>
specifies how much the alpha value of the effect changes per second (subtracted) specifies how much the alpha value of the effect changes per second (subtracted)
die <maximum age> die <maximum age> <minimum age>
specifies the maximum age of the particle specifies the maximum age of the particle
diesubrand <value> diesubrand <value>
obsolete (set by die)
specifies the maximum starting age of the particle. specifies the maximum starting age of the particle.
basically the particle will live up to this much less time. the alpha value will also be aged by the amount chosen by this value basically the particle will live up to this much less time. the alpha value will also be aged by the amount chosen by this value
@ -104,8 +105,8 @@ veladd <value>
orgadd <value> orgadd <value>
biases how much to add to the starting origin relative to the requested velocity. biases how much to add to the starting origin relative to the requested velocity.
friction <1> <2> <3> friction <<xyz>|<xy> <z> | <x> <y> <z>>
FIXME Proportion of the particle's speed that should be lost from friction. Negative values are accepted.
gravity <value> gravity <value>
amount that the particle's velocity changes per second, in quake units. amount that the particle's velocity changes per second, in quake units.
@ -130,12 +131,19 @@ assoc <effectname>
Thus allowing two sets of particles from one effect. Thus allowing two sets of particles from one effect.
inwater <effectname> inwater <effectname>
obsolete
Specifies a replacement effect to use when this one is spawned underwater. Specifies a replacement effect to use when this one is spawned underwater.
assoc used is the replacement effect. the assoc value from the replaced effect is ignored (this includes +foo chains). assoc used is the replacement effect. the assoc value from the replaced effect is ignored (this includes +foo chains).
overwater overwater [content names]
specifies that this Specifies that this particle should ONLY be spawned when out of water.
underwater The particle will not spawn under water (this does not affect assoc chains).
Content names are a space-separated list of: water slime lava sky solid fluid. Default is fluid if not specified.
The r_part_contentswitch cvar must be enabled for this to function correctly.
underwater [content names]
Specifies that this particle should ONLY be spawned when underwater.
The particle will not spawn if the spawn position is non-water (this does not affect assoc chains).
colorindex <index> [rand] colorindex <index> [rand]
Specifies a palette index to spawn the particle with. Specifies a palette index to spawn the particle with.
@ -282,13 +290,15 @@ emitstart <seconds>
spawnorg <horiz> [vert] spawnorg <horiz> [vert]
spawnvel <horiz> [vert] spawnvel <horiz> [vert]
obsolete
viewspace [frac] viewspace [frac]
Specifies that this particle type should move relative to the camera. Specifies that this particle type should move relative to the camera.
Not compatible with splitscreen. Not compatible with splitscreen.
Should not normally be used in combination with clipping/bouncing.
perframe perframe
apply inverse frametime to count (causes emits to be per frame) apply inverse frametime to count (causes emits to be per frame).
averageout averageout
average trail points from start to end, useful with t_lightning, etc average trail points from start to end, useful with t_lightning, etc