implemented autotracking, hightrack is no longer quite so obnoxious.

implement cfg_save_all cvar, so cfg_save can save all.
downloads attempt to avoid using the fte/ gamedir
actually registering r_tracker_frags cvar.
fix ezhud wad image issues.
fix mouse binds not working when running fullscreen.
dedicated servers can now use getsurface builtins.
gl_font can now attempt to use conchars subdir too.
terrain editor can now display the areas which cannot accept the selected texture for painting. this should help reduce edges.
attempt to fix some of the less-supported ports.
don't be annoying with entity foo = someclass;
fteqcc now offers to create files if you try opening one that doesn't exist.
plugins can now query ping etc info properly.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4893 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-06-12 14:44:50 +00:00
parent daa4496b7c
commit 3fd21ea6ea
52 changed files with 1097 additions and 437 deletions

View file

@ -37,14 +37,163 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
char cl_spectatorgroup[] = "Spectator Tracking"; char cl_spectatorgroup[] = "Spectator Tracking";
enum
{
TM_USER, //user hit jump and changed pov explicitly
TM_HIGHTRACK, //tracking the player with the highest frags
TM_KILLER, //switch to the previous person's killer.
TM_MODHINTS, //using the mod's //at hints
TM_STATS //parsing mvd stats and making our own choices
} autotrackmode;
int autotrack_hint; //the latest hint from the mod, might be negative for invalid.
int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to.
char *autotrack_statsrule;
static void QDECL CL_AutoTrackChanged(cvar_t *v, char *oldval)
{
Cam_AutoTrack_Update(v->string);
}
// track high fragger // track high fragger
cvar_t cl_autotrack = CVARCD("cl_autotrack", "auto", CL_AutoTrackChanged, "Specifies the default tracking mode at the start of the map. Use the 'autotrack' command to reset/apply an auto-tracking mode without changing the default.\nValid values are: high, ^hkiller^h, mod, user. Other values are treated as weighting scripts for mvd playback, where available.");
cvar_t cl_hightrack = SCVAR("cl_hightrack", "0"); cvar_t cl_hightrack = SCVAR("cl_hightrack", "0");
cvar_t cl_chasecam = SCVAR("cl_chasecam", "1");
cvar_t cl_selfcam = SCVAR("cl_selfcam", "1");
//cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" }; //cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" };
//cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" }; //cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" };
cvar_t cl_chasecam = SCVAR("cl_chasecam", "1");
cvar_t cl_selfcam = SCVAR("cl_selfcam", "1");
void Cam_AutoTrack_Update(const char *mode)
{
if (!mode)
mode = cl_autotrack.string;
Z_Free(autotrack_statsrule);
autotrack_statsrule = NULL;
if (!*mode || !Q_strcasecmp(mode, "auto"))
{
if (cl_hightrack.ival)
autotrackmode = TM_HIGHTRACK;
else
autotrackmode = TM_MODHINTS;
}
else if (!Q_strcasecmp(mode, "high"))
autotrackmode = TM_HIGHTRACK;
else if (!Q_strcasecmp(mode, "killer"))
autotrackmode = TM_KILLER;
else if (!Q_strcasecmp(mode, "mod"))
autotrackmode = TM_MODHINTS;
else if (!Q_strcasecmp(mode, "user") || !Q_strcasecmp(mode, "off"))
autotrackmode = TM_USER;
else
{
autotrackmode = TM_STATS;
autotrack_statsrule = Z_StrDup(mode);
}
}
static void Cam_AutoTrack_f(void)
{
if (*Cmd_Argv(1))
Cam_AutoTrack_Update(Cmd_Argv(1));
else
Cam_AutoTrack_Update(NULL);
}
static float CL_TrackScore(player_info_t *pl, char *rule)
{
float score = 0;
float val;
int r;
while (*rule)
{
r = *rule++;
if (r == 'f')
val = pl->frags;
else if (r == 'l')
val = pl->ping;
else if (r == 'h')
val = pl->statsf[STAT_HEALTH];
else if (r == 'q')
val = (pl->stats[STAT_ITEMS] & IT_QUAD)?1:0;
else if (r == 'p')
val = (pl->stats[STAT_ITEMS] & IT_INVULNERABILITY)?1:0;
else if (r == 's')
{
int i = strtol(rule, &rule, 10);
val = pl->statsf[i];
}
else if (r == '#')
val = strtod(rule, &rule);
else
val = 0;
if (*rule == '*')
{
val *= strtod(rule+1, &rule);
}
score += val;
if (*rule == '+')
rule++;
else
break;
}
return score;
}
//returns the player with the highest frags
static int CL_FindHighTrack(int seat, char *rule)
{
int j = -1;
int i, k;
float max, score;
player_info_t *s;
//set a default to the currently tracked player, to reuse the current player we're tracking if someone lower equalises.
j = cl.playerview[seat].cam_spec_track;
if (j >= 0)
max = CL_TrackScore(&cl.players[j], rule);
else
max = -9999;
for (i = 0; i < cl.allocated_client_slots; i++)
{
s = &cl.players[i];
score = CL_TrackScore(s, rule);
if (s->name[0] && !s->spectator && score > max)
{
if (j == i) //this was our default.
continue;
//skip it if an earlier seat is watching it already
for (k = 0; k < seat; k++)
{
if (Cam_TrackNum(&cl.playerview[k]) == i)
break;
}
if (cl.teamplay && seat && cl.playerview[0].cam_spec_track >= 0 && strcmp(cl.players[cl.playerview[0].cam_spec_track].team, s->team))
continue; //when using multiview, keep tracking the team
if (k == seat)
{
max = CL_TrackScore(s, rule);
j = i;
}
}
}
return j;
}
static int CL_AutoTrack_Choose(int seat)
{
int best = -1;
if (autotrackmode == TM_KILLER)
best = autotrack_killer;
if (autotrackmode == TM_MODHINTS && seat == 0 && autotrack_hint >= 0)
best = autotrack_hint;
if (autotrackmode == TM_STATS && cls.demoplayback == DPB_MVD)
best = CL_FindHighTrack(seat, autotrack_statsrule);
if (autotrackmode == TM_HIGHTRACK || best == -1)
best = CL_FindHighTrack(seat, "f");
//TM_USER should generally avoid autotracking
autotrack_killer = best; //killer should continue to track whatever is currently tracked until its changed by frag message parsing
return best;
}
static int Cam_FindSortedPlayer(int number); static int Cam_FindSortedPlayer(int number);
@ -111,6 +260,8 @@ void Cam_Lock(playerview_t *pv, int playernum)
memcpy(&pv->stats, cl.players[playernum].stats, sizeof(pv->stats)); memcpy(&pv->stats, cl.players[playernum].stats, sizeof(pv->stats));
pv->cam_locked = true; //instantly lock if the player is valid. pv->cam_locked = true; //instantly lock if the player is valid.
pv->viewentity = playernum+1; pv->viewentity = playernum+1;
if (cls.z_ext & Z_EXT_VIEWHEIGHT)
pv->viewheight = cl.players[playernum].statsf[STAT_VIEWHEIGHT];
} }
Sbar_Changed(); Sbar_Changed();
@ -245,32 +396,13 @@ static qboolean InitFlyby(playerview_t *pv, vec3_t selforigin, vec3_t playerorig
static void Cam_CheckHighTarget(playerview_t *pv) static void Cam_CheckHighTarget(playerview_t *pv)
{ {
int i, j, max; int j;
player_info_t *s;
playerview_t *spv; playerview_t *spv;
j = -1; j = CL_AutoTrack_Choose(pv - cl.playerview);
for (i = 0, max = -9999; i < cl.allocated_client_slots; i++)
{
s = &cl.players[i];
if (s->name[0] && !s->spectator && s->frags > max)
{
//skip it if an earlier seat is watching it already
for (spv = pv-1; spv >= cl.playerview && spv < &cl.playerview[cl.splitclients]; spv--)
{
if (Cam_TrackNum(spv) == i)
break;
}
if (!(spv >= cl.playerview && spv < &cl.playerview[cl.splitclients]))
{
max = s->frags;
j = i;
}
}
}
if (j >= 0) if (j >= 0)
{ {
if (!pv->cam_locked || cl.players[j].frags > cl.players[pv->cam_spec_track].frags) if (!pv->cam_locked || pv->cam_spec_track != j)
{ {
Cam_Lock(pv, j); Cam_Lock(pv, j);
//un-lock any higher seats watching our new target. this keeps things ordered. //un-lock any higher seats watching our new target. this keeps things ordered.
@ -350,7 +482,7 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
if (!cl.spectator || !cl.worldmodel) //can happen when the server changes level if (!cl.spectator || !cl.worldmodel) //can happen when the server changes level
return; return;
if (cl_hightrack.value && !pv->cam_locked) if (autotrackmode != TM_USER && !pv->cam_locked)
Cam_CheckHighTarget(pv); Cam_CheckHighTarget(pv);
if (!pv->cam_auto || cls.state != ca_active || cl.worldmodel->loadstate != MLS_LOADED) if (!pv->cam_auto || cls.state != ca_active || cl.worldmodel->loadstate != MLS_LOADED)
@ -359,7 +491,7 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
if (pv->cam_locked && (!cl.players[pv->cam_spec_track].name[0] || cl.players[pv->cam_spec_track].spectator)) if (pv->cam_locked && (!cl.players[pv->cam_spec_track].name[0] || cl.players[pv->cam_spec_track].spectator))
{ {
pv->cam_locked = false; pv->cam_locked = false;
if (cl_hightrack.value) if (autotrackmode != TM_USER)
Cam_CheckHighTarget(pv); Cam_CheckHighTarget(pv);
else else
Cam_Unlock(pv); Cam_Unlock(pv);
@ -443,7 +575,18 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
void Cam_SetAutoTrack(int userid) void Cam_SetAutoTrack(int userid)
{ //this is a hint from the server about who to track { //this is a hint from the server about who to track
int slot;
playerview_t *pv = &cl.playerview[0];
autotrack_hint = -1;
for (slot = 0; slot < cl.allocated_client_slots; slot++)
{
if (cl.players[slot].userid == userid)
{
autotrack_hint = slot;
return;
}
}
Con_Printf("//at: invalid userid\n");
} }
void Cam_TrackCrosshairedPlayer(playerview_t *pv) void Cam_TrackCrosshairedPlayer(playerview_t *pv)
@ -594,11 +737,16 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
} }
} }
if (pv->cam_auto && cl_hightrack.ival) if (pv->cam_auto && autotrackmode != TM_USER)
{
if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP))
autotrackmode = TM_USER;
else
{ {
Cam_CheckHighTarget(pv); Cam_CheckHighTarget(pv);
return; return;
} }
}
if (pv->cam_locked) if (pv->cam_locked)
{ {
@ -692,7 +840,7 @@ static int Cam_FindSortedPlayer(int number)
void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg) void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg)
{ {
playerview_t *pv = &cl.playerview[seat]; playerview_t *pv = &cl.playerview[seat];
int slot, sortednum; int slot;
player_info_t *s; player_info_t *s;
char *e; char *e;
@ -840,12 +988,14 @@ void Cam_Track4_f(void)
void CL_InitCam(void) void CL_InitCam(void)
{ {
Cvar_Register (&cl_autotrack, cl_spectatorgroup);
Cvar_Register (&cl_hightrack, cl_spectatorgroup); Cvar_Register (&cl_hightrack, cl_spectatorgroup);
Cvar_Register (&cl_chasecam, cl_spectatorgroup); Cvar_Register (&cl_chasecam, cl_spectatorgroup);
// Cvar_Register (&cl_camera_maxpitch, cl_spectatorgroup); // Cvar_Register (&cl_camera_maxpitch, cl_spectatorgroup);
// Cvar_Register (&cl_camera_maxyaw, cl_spectatorgroup); // Cvar_Register (&cl_camera_maxyaw, cl_spectatorgroup);
// Cvar_Register (&cl_selfcam, cl_spectatorgroup); // Cvar_Register (&cl_selfcam, cl_spectatorgroup);
Cmd_AddCommand("autotrack", Cam_AutoTrack_f); //reset it, if they jumped or something.
Cmd_AddCommand("track", Cam_Track_f); Cmd_AddCommand("track", Cam_Track_f);
Cmd_AddCommand("track1", Cam_Track1_f); Cmd_AddCommand("track1", Cam_Track1_f);
Cmd_AddCommand("track2", Cam_Track2_f); Cmd_AddCommand("track2", Cam_Track2_f);

View file

@ -473,6 +473,9 @@ qboolean CL_GetDemoMessage (void)
if (cls.timedemo) if (cls.timedemo)
if (cls.td_startframe == -1 && cls.state == ca_active) if (cls.td_startframe == -1 && cls.state == ca_active)
{ //start the timer only once we are connected. { //start the timer only once we are connected.
//make sure everything is loaded, to avoid stalls
COM_WorkerFullSync();
cls.td_starttime = Sys_DoubleTime(); cls.td_starttime = Sys_DoubleTime();
cls.td_startframe = host_framecount; cls.td_startframe = host_framecount;
@ -748,6 +751,7 @@ readit:
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{ {
int seat; int seat;
cl.defaultnetsplit = 0;
switch(cls_lasttype) switch(cls_lasttype)
{ {
case dem_multiple: case dem_multiple:
@ -764,21 +768,31 @@ readit:
olddemotime = demotime; olddemotime = demotime;
goto readnext; goto readnext;
} }
cl.defaultnetsplit = seat;
break; break;
case dem_single: case dem_single:
for (seat = 0; seat < cl.splitclients; seat++) {
int maxseat = cl.splitclients;
//only accept single messages that are directed to the first player view.
//this is too problematic otherwise (apparently mvdsv doesn't use dem_multiple for team says any more).
if (1)
maxseat = 1;
for (seat = 0; seat < maxseat; seat++)
{ {
tracknum = cl.playerview[seat].cam_spec_track; tracknum = cl.playerview[seat].cam_spec_track;
if (!cl.playerview[seat].cam_auto) if (!cl.playerview[seat].cam_auto)
tracknum = -1; tracknum = -1;
if (tracknum == -1 || !(cls_lastto != tracknum)) if (tracknum == -1 || (cls_lastto != tracknum))
continue; continue;
break;
} }
if (seat == cl.splitclients) if (seat == maxseat)
{ {
olddemotime = demotime; olddemotime = demotime;
goto readnext; goto readnext;
} }
cl.defaultnetsplit = seat;
}
break; break;
case dem_all: case dem_all:
if (c & ~dem_mask) if (c & ~dem_mask)

View file

@ -2015,6 +2015,7 @@ void CL_InitInput (void)
Cmd_AddCommand ("+jump", IN_JumpDown); Cmd_AddCommand ("+jump", IN_JumpDown);
Cmd_AddCommand ("-jump", IN_JumpUp); Cmd_AddCommand ("-jump", IN_JumpUp);
Cmd_AddCommand ("impulse", IN_Impulse); Cmd_AddCommand ("impulse", IN_Impulse);
Cmd_AddCommandD("weapon", IN_Impulse, "Partial implementation for compatibility"); //for pseudo-compat with ezquake.
Cmd_AddCommand ("+klook", IN_KLookDown); Cmd_AddCommand ("+klook", IN_KLookDown);
Cmd_AddCommand ("-klook", IN_KLookUp); Cmd_AddCommand ("-klook", IN_KLookUp);
Cmd_AddCommand ("+mlook", IN_MLookDown); Cmd_AddCommand ("+mlook", IN_MLookDown);

View file

@ -62,7 +62,8 @@ extern cvar_t net_compress;
cvar_t cl_defaultport = CVARAFD("cl_defaultport", STRINGIFY(PORT_QWSERVER), "port", 0, "The default port to connect to servers.\nQW: "STRINGIFY(PORT_QWSERVER)", NQ: "STRINGIFY(PORT_NQSERVER)", Q2: "STRINGIFY(PORT_Q2SERVER)"."); cvar_t cl_defaultport = CVARAFD("cl_defaultport", STRINGIFY(PORT_QWSERVER), "port", 0, "The default port to connect to servers.\nQW: "STRINGIFY(PORT_QWSERVER)", NQ: "STRINGIFY(PORT_NQSERVER)", Q2: "STRINGIFY(PORT_Q2SERVER)".");
cvar_t cfg_save_name = CVARF("cfg_save_name", "fte", CVAR_ARCHIVE|CVAR_NOTFROMSERVER); cvar_t cfg_save_name = CVARFD("cfg_save_name", "fte", CVAR_ARCHIVE|CVAR_NOTFROMSERVER, "This is the config name that is saved by default when no argument is specified.");
cvar_t cfg_save_all = CVARFD("cfg_save_all", "", CVAR_ARCHIVE|CVAR_NOTFROMSERVER, "If 1, cfg_save ALWAYS saves all cvars. If 0, cfg_save only ever saves archived cvars. If empty, cfg_saves all cvars only when an explicit filename was given.");
cvar_t cl_splitscreen = CVARD("cl_splitscreen", "0", "Enables splitscreen support. See also: allow_splitscreen, in_rawinput*, the \"p\" command."); cvar_t cl_splitscreen = CVARD("cl_splitscreen", "0", "Enables splitscreen support. See also: allow_splitscreen, in_rawinput*, the \"p\" command.");
@ -297,6 +298,12 @@ void CL_UpdateWindowTitle(void)
Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, sv.name); Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, sv.name);
else else
#endif #endif
if (cls.demoplayback)
{
extern char lastdemoname[];
Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, lastdemoname);
}
else
Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, cls.servername); Q_snprintfz(title, sizeof(title), "%s: %s", fs_gamename.string, cls.servername);
break; break;
case ca_disconnected: case ca_disconnected:
@ -3551,6 +3558,7 @@ void CL_Init (void)
Cvar_Register (&developer, cl_controlgroup); Cvar_Register (&developer, cl_controlgroup);
Cvar_Register (&cfg_save_name, cl_controlgroup); Cvar_Register (&cfg_save_name, cl_controlgroup);
Cvar_Register (&cfg_save_all, cl_controlgroup);
Cvar_Register (&cl_sendguid, cl_controlgroup); Cvar_Register (&cl_sendguid, cl_controlgroup);
Cvar_Register (&cl_defaultport, cl_controlgroup); Cvar_Register (&cl_defaultport, cl_controlgroup);
@ -3809,6 +3817,7 @@ void CL_Init (void)
Ignore_Init(); Ignore_Init();
Stats_Init();
CL_ClearState(); //make sure the cl.* fields are set properly if there's no ssqc or whatever. CL_ClearState(); //make sure the cl.* fields are set properly if there's no ssqc or whatever.
} }

View file

@ -357,7 +357,7 @@ int CL_CalcNet (float scale)
return percent; return percent;
} }
float CL_CalcNet2 (float *ping, float *ping_min, float *ping_max, float *ping_stddev) void CL_CalcNet2 (float *pings, float *pings_min, float *pings_max, float *pingms_stddev, float *pingfr, int *pingfr_min, int *pingfr_max, float *dropped, float *choked, float *invalid)
{ {
int i; int i;
outframe_t *frame; outframe_t *frame;
@ -365,11 +365,19 @@ float CL_CalcNet2 (float *ping, float *ping_min, float *ping_max, float *ping_st
int pending = 0; int pending = 0;
int sent; int sent;
int valid = 0; int valid = 0;
int fr;
int nchoked = 0;
int ninvalid = 0;
// char st[80]; // char st[80];
*ping = 0; *pings = 0;
*ping_max = 0; *pings_max = 0;
*ping_min = 1000000000000; *pings_min = 1000000000000;
*pingfr = 0;
*pingfr_max = 0;
*pingfr_min = 0x7fffffff;
*pingms_stddev = 0;
sent = NET_TIMINGS; sent = NET_TIMINGS;
@ -386,28 +394,53 @@ float CL_CalcNet2 (float *ping, float *ping_min, float *ping_max, float *ping_st
else if (frame->latency == -1) else if (frame->latency == -1)
lost++; // lost lost++; // lost
else if (frame->latency == -2) else if (frame->latency == -2)
; // choked nchoked++; // choked
else if (frame->latency == -3) else if (frame->latency == -3)
sent--; // c2spps sent--; // c2spps
// else if (frame->invalid) else if (frame->latency == -4)
// packet_latency[i&NET_TIMINGSMASK] = 9998; // invalid delta ninvalid++; //corrupt/wrong/dodgy/egads
else else
{ {
*ping += frame->latency; *pings += frame->latency;
if (*ping_max < frame->latency) if (*pings_max < frame->latency)
*ping_max = frame->latency; *pings_max = frame->latency;
if (*ping_min > frame->latency) if (*pings_min > frame->latency)
*ping_min = frame->latency; *pings_min = frame->latency;
fr = frame->cmd_sequence-frame->server_message_num;
*pingfr += fr;
if (*pingfr_max < fr)
*pingfr_max = fr;
if (*pingfr_min > fr)
*pingfr_min = fr;
valid++; valid++;
} }
} }
*ping /= valid; if (valid)
{
*pings /= valid;
*pingfr /= valid;
//determine stddev, in milliseconds instead of seconds.
for (i=cl.movesequence-UPDATE_BACKUP+1; i <= cl.movesequence; i++)
{
frame = &cl.outframes[i&UPDATE_MASK];
if (i <= cl.lastackedmovesequence && frame->latency >= 0)
{
float dev = (frame->latency - *pings) * 1000;
*pingms_stddev += dev*dev;
}
}
*pingms_stddev = sqrt(*pingms_stddev/valid);
}
if (pending == sent || sent < 1) if (pending == sent || sent < 1)
return 1; //shouldn't ever happen. *dropped = 1; //shouldn't ever happen.
else else
return lost / sent; *dropped = (float)lost / sent;
*choked = (float)nchoked / sent;
*invalid = (float)ninvalid / sent;
} }
void CL_AckedInputFrame(int inseq, int outseq, qboolean worldstateokay) void CL_AckedInputFrame(int inseq, int outseq, qboolean worldstateokay)
@ -1725,7 +1758,7 @@ qboolean DL_Begun(qdownload_t *dl)
else if (!strncmp(dl->tempname,"skins/",6)) else if (!strncmp(dl->tempname,"skins/",6))
dl->fsroot = FS_PUBBASEGAMEONLY; //shared between gamedirs, so only use the basegame. dl->fsroot = FS_PUBBASEGAMEONLY; //shared between gamedirs, so only use the basegame.
else else
dl->fsroot = FS_GAMEONLY; //other files are relative to the active gamedir. dl->fsroot = FS_PUBGAMEONLY;//FS_GAMEONLY; //other files are relative to the active gamedir.
Q_snprintfz(dl->dclname, sizeof(dl->dclname), "%s.dcl", dl->tempname); Q_snprintfz(dl->dclname, sizeof(dl->dclname), "%s.dcl", dl->tempname);
@ -3040,6 +3073,7 @@ void CLQW_ParseServerData (void)
// now waiting for downloads, etc // now waiting for downloads, etc
cls.state = ca_onserver; cls.state = ca_onserver;
Cam_AutoTrack_Update(NULL);
cl.sendprespawn = false; cl.sendprespawn = false;
@ -3107,6 +3141,7 @@ void CLQ2_ParseServerData (void)
cl.minpitch = -89; cl.minpitch = -89;
cl.maxpitch = 89; cl.maxpitch = 89;
cl.servercount = svcnt; cl.servercount = svcnt;
Cam_AutoTrack_Update(NULL);
Stats_NewMap(); Stats_NewMap();
@ -3352,6 +3387,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
cls.signon = 0; cls.signon = 0;
cls.state = ca_onserver; cls.state = ca_onserver;
Cam_AutoTrack_Update(NULL);
//fill in the csqc stuff //fill in the csqc stuff
@ -5500,14 +5536,17 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags)
// CL_PrintStandardMessage: takes non-chat net messages and performs name coloring // CL_PrintStandardMessage: takes non-chat net messages and performs name coloring
// NOTE: msg is considered destroyable // NOTE: msg is considered destroyable
char acceptedchars[] = {'.', '?', '!', '\'', ',', ':', ' ', '\0'}; char acceptedchars[] = {'.', '?', '!', '\'', ',', ':', ' ', '\0'};
void CL_PrintStandardMessage(char *msg, int printlevel) void CL_PrintStandardMessage(char *msgtext, int printlevel)
{ {
int i; int i;
player_info_t *p; player_info_t *p;
extern cvar_t cl_standardmsg; extern cvar_t cl_standardmsg, msg;
char *begin = msg; char *begin = msgtext;
char fullmessage[2048]; char fullmessage[2048];
if (printlevel < msg.ival)
return;
fullmessage[0] = 0; fullmessage[0] = 0;
// search for player names in message // search for player names in message
@ -5523,7 +5562,7 @@ void CL_PrintStandardMessage(char *msg, int printlevel)
if (!(*name)) if (!(*name))
continue; continue;
len = strlen(name); len = strlen(name);
v = strstr(msg, name); v = strstr(msgtext, name);
while (v) while (v)
{ {
// name parsing rules // name parsing rules
@ -5554,8 +5593,8 @@ void CL_PrintStandardMessage(char *msg, int printlevel)
*v = 0; // cut off message *v = 0; // cut off message
// print msg chunk // print msg chunk
Q_strncatz(fullmessage, msg, sizeof(fullmessage)); Q_strncatz(fullmessage, msgtext, sizeof(fullmessage));
msg = v + len; // update search point msgtext = v + len; // update search point
// get name color // get name color
if (p->spectator || cl_standardmsg.ival) if (p->spectator || cl_standardmsg.ival)
@ -5573,7 +5612,7 @@ void CL_PrintStandardMessage(char *msg, int printlevel)
} }
// print final chunk // print final chunk
Q_strncatz(fullmessage, msg, sizeof(fullmessage)); Q_strncatz(fullmessage, msgtext, sizeof(fullmessage));
Con_Printf("%s", fullmessage); Con_Printf("%s", fullmessage);
} }
@ -5704,6 +5743,11 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
{ {
Cam_SetAutoTrack(atoi(stufftext+5)); Cam_SetAutoTrack(atoi(stufftext+5));
} }
else if (!strncmp(stufftext, "//wps ", 5))
{
//weapon stats, eg:
//wps CLIENT WNAME attacks hits
}
else if (!strncmp(stufftext, "//kickfile ", 11)) else if (!strncmp(stufftext, "//kickfile ", 11))
{ {
flocation_t loc; flocation_t loc;
@ -5958,7 +6002,7 @@ void CLQW_ParseServerMessage (void)
cmd = MSG_ReadByte(); cmd = MSG_ReadByte();
} }
else else
destsplit = 0; destsplit = cl.defaultnetsplit;
if (cmd == -1) if (cmd == -1)
{ {

View file

@ -529,12 +529,20 @@ typedef struct {
int seats; int seats;
struct struct
{ {
float avg; float s_avg;
float mn; float s_mn;
float mx; float s_mx;
float stddev; float ms_stddev;
float loss; float fr_avg;
int fr_mn;
int fr_mx;
} ping; } ping;
struct
{ //decimals
float dropped;
float choked;
float invalid;
} loss;
float mlatency; float mlatency;
float mrate; float mrate;
float vlatency; float vlatency;
@ -555,6 +563,7 @@ typedef struct {
float out_pps; float out_pps;
float out_bps; float out_bps;
} svrate; } svrate;
int capturing;
} vmnetinfo_t; } vmnetinfo_t;
#define has(x) (((quintptr_t)&((vmnetinfo_t*)NULL)->x + sizeof(((vmnetinfo_t*)NULL)->x)) <= outlen) #define has(x) (((quintptr_t)&((vmnetinfo_t*)NULL)->x + sizeof(((vmnetinfo_t*)NULL)->x)) <= outlen)
//aka: misc other hud timing crap //aka: misc other hud timing crap
@ -565,10 +574,19 @@ static qintptr_t VARGS Plug_GetNetworkInfo(void *offset, quintptr_t mask, const
if (VM_OOB(arg[0], outlen)) if (VM_OOB(arg[0], outlen))
return false; return false;
if (has(capturing))
{
#ifdef NOMEDIA
outptr->capturing = 0;
#else
outptr->capturing = Media_Capturing();
#endif
}
if (has(seats)) if (has(seats))
outptr->seats = cl.splitclients; outptr->seats = cl.splitclients;
if (has(ping)) if (has(ping))
outptr->ping.loss = CL_CalcNet2 (&outptr->ping.avg, &outptr->ping.mn, &outptr->ping.mx, &outptr->ping.stddev); CL_CalcNet2 (&outptr->ping.s_avg, &outptr->ping.s_mn, &outptr->ping.s_mx, &outptr->ping.ms_stddev, &outptr->ping.fr_avg, &outptr->ping.fr_mn, &outptr->ping.fr_mx, &outptr->loss.dropped, &outptr->loss.choked, &outptr->loss.invalid);
if (has(mlatency)) if (has(mlatency))
outptr->mlatency = 0; outptr->mlatency = 0;
@ -975,7 +993,7 @@ void Plug_Client_Init(void)
Plug_RegisterBuiltin("GetLocalPlayerNumbers", Plug_GetLocalPlayerNumbers, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetLocalPlayerNumbers", Plug_GetLocalPlayerNumbers, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER);
// Plug_RegisterBuiltin("GetNetworkInfo", Plug_GetNetworkInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetNetworkInfo", Plug_GetNetworkInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER);

View file

@ -1399,38 +1399,6 @@ void SCR_DrawFPS (void)
SCR_StringXY(str, show_fps_x.value, show_fps_y.value); SCR_StringXY(str, show_fps_x.value, show_fps_y.value);
} }
void SCR_DrawUPS (void)
{
extern cvar_t show_speed;
static double lastupstime;
double t;
static float lastups;
char str[80];
float *vel;
int track;
if (!show_speed.ival)
return;
t = Sys_DoubleTime();
if ((t - lastupstime) >= 1.0/20)
{
if (cl.spectator)
track = Cam_TrackNum(&cl.playerview[0]);
else
track = -1;
if (track != -1)
vel = cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[track].velocity;
else
vel = cl.playerview[0].simvel;
lastups = sqrt((vel[0]*vel[0]) + (vel[1]*vel[1]));
lastupstime = t;
}
sprintf(str, "%3.1f UPS", lastups);
SCR_StringXY(str, show_speed_x.value, show_speed_y.value);
}
void SCR_DrawClock(void) void SCR_DrawClock(void)
{ {
struct tm *newtime; struct tm *newtime;
@ -2486,7 +2454,6 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
SCR_DrawNet (); SCR_DrawNet ();
SCR_DrawDisk(); SCR_DrawDisk();
SCR_DrawFPS (); SCR_DrawFPS ();
SCR_DrawUPS ();
SCR_DrawClock(); SCR_DrawClock();
SCR_DrawGameClock(); SCR_DrawGameClock();
SCR_DrawTurtle (); SCR_DrawTurtle ();
@ -2494,12 +2461,7 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
SCR_ShowPics_Draw(); SCR_ShowPics_Draw();
} }
else else
{
SCR_DrawFPS (); SCR_DrawFPS ();
SCR_DrawUPS ();
SCR_DrawClock();
SCR_DrawGameClock();
}
SCR_CheckDrawCenterString (); SCR_CheckDrawCenterString ();
} }

View file

@ -191,7 +191,7 @@ typedef struct player_info_s
int prevcount; int prevcount;
int stats[MAX_CL_STATS]; int stats[MAX_CL_STATS];
int statsf[MAX_CL_STATS]; float statsf[MAX_CL_STATS];
} player_info_t; } player_info_t;
@ -708,6 +708,7 @@ typedef struct
//when running splitscreen, we have multiple viewports all active at once //when running splitscreen, we have multiple viewports all active at once
int splitclients; //we are running this many clients split screen. int splitclients; //we are running this many clients split screen.
playerview_t playerview[MAX_SPLITS]; playerview_t playerview[MAX_SPLITS];
int defaultnetsplit;//which multiview splitscreen to parse the message for (set by mvd playback code)
// localized movement vars // localized movement vars
float bunnyspeedcap; float bunnyspeedcap;
@ -1092,7 +1093,7 @@ void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result);
#define NET_TIMINGSMASK 255 #define NET_TIMINGSMASK 255
extern int packet_latency[NET_TIMINGS]; extern int packet_latency[NET_TIMINGS];
int CL_CalcNet (float scale); int CL_CalcNet (float scale);
float CL_CalcNet2 (float *ping, float *ping_min, float *ping_max, float *ping_stddev); void CL_CalcNet2 (float *pings, float *pings_min, float *pings_max, float *pingms_stddev, float *pingfr, int *pingfr_min, int *pingfr_max, float *dropped, float *choked, float *invalid);
void CL_ClearParseState(void); void CL_ClearParseState(void);
void CL_Parse_Disconnected(void); void CL_Parse_Disconnected(void);
void CL_DumpPacket(void); void CL_DumpPacket(void);
@ -1284,6 +1285,7 @@ void Cam_Reset(void);
void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg); void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg);
void Cam_Lock(playerview_t *pv, int playernum); void Cam_Lock(playerview_t *pv, int playernum);
void CL_InitCam(void); void CL_InitCam(void);
void Cam_AutoTrack_Update(const char *mode);
void QDECL vectoangles(vec3_t fwd, vec3_t ang); void QDECL vectoangles(vec3_t fwd, vec3_t ang);
@ -1484,6 +1486,7 @@ int qm_stricmp(char *s1, char *s2);
qboolean Stats_ParsePrintLine(char *line); qboolean Stats_ParsePrintLine(char *line);
void Stats_NewMap(void); void Stats_NewMap(void);
void Stats_Clear(void); void Stats_Clear(void);
void Stats_Init(void);
enum uploadfmt; enum uploadfmt;
typedef struct typedef struct

View file

@ -524,6 +524,10 @@ void Stats_Clear(void)
#define Z_Copy(tk) tz = Z_Malloc(strlen(tk)+1);strcpy(tz, tk) //remember the braces #define Z_Copy(tk) tz = Z_Malloc(strlen(tk)+1);strcpy(tz, tk) //remember the braces
void Stats_Init(void)
{
Cvar_Register(&r_tracker_frags, NULL);
}
static void Stats_LoadFragFile(char *name) static void Stats_LoadFragFile(char *name)
{ {
char filename[MAX_QPATH]; char filename[MAX_QPATH];

View file

@ -2281,6 +2281,7 @@ static void Image_LoadTextureMips(void *ctx, void *data, size_t a, size_t b)
{ {
texid_t tex = ctx; texid_t tex = ctx;
struct pendingtextureinfo *mips = data; struct pendingtextureinfo *mips = data;
tex->width = mips->mip[0].width; tex->width = mips->mip[0].width;
tex->height = mips->mip[0].height; tex->height = mips->mip[0].height;
if (rf->IMG_LoadTextureMips(tex, mips)) if (rf->IMG_LoadTextureMips(tex, mips))
@ -2288,6 +2289,16 @@ static void Image_LoadTextureMips(void *ctx, void *data, size_t a, size_t b)
else else
tex->status = TEX_FAILED; tex->status = TEX_FAILED;
BZ_Free(mips); BZ_Free(mips);
if (!strncmp(tex->ident, "gfx/", 4))
{
qpic_t *pic = W_SafeGetLumpName(tex->ident+4);
if (pic)
{
tex->width = pic->width;
tex->height = pic->height;
}
}
} }
#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT #ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
@ -4432,6 +4443,8 @@ void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, in
Image_GenerateMips(&mips, flags); Image_GenerateMips(&mips, flags);
Image_ChangeFormat(&mips, fmt); Image_ChangeFormat(&mips, fmt);
rf->IMG_LoadTextureMips(tex, &mips); rf->IMG_LoadTextureMips(tex, &mips);
tex->width = mips.mip[0].width;
tex->height = mips.mip[0].height;
tex->status = TEX_LOADED; tex->status = TEX_LOADED;
} }

View file

@ -2314,9 +2314,12 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
if (key == K_MOUSE1 && IN_MouseDevIsTouch(devid)) if (key == K_MOUSE1 && IN_MouseDevIsTouch(devid))
{ {
dc = SCR_ShowPics_ClickCommand(mousecursor_x, mousecursor_y); char *button = SCR_ShowPics_ClickCommand(mousecursor_x, mousecursor_y);
if (dc) if (button)
{
dc = button;
bl = RESTRICT_INSECURE; bl = RESTRICT_INSECURE;
}
else else
{ {
int bkey = Sbar_TranslateHudClick(); int bkey = Sbar_TranslateHudClick();
@ -2327,7 +2330,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
} }
} }
if (!dc) //no buttons to click, if (!button) //no buttons to click,
{ {
bkey = IN_TranslateMButtonPress(devid); bkey = IN_TranslateMButtonPress(devid);
if (bkey) if (bkey)
@ -2335,7 +2338,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
dc = keybindings[bkey][modifierstate]; dc = keybindings[bkey][modifierstate];
bl = bindcmdlevel[bkey][modifierstate]; bl = bindcmdlevel[bkey][modifierstate];
} }
else else if (!Key_MouseShouldBeFree())
{ {
key_repeats[key] = 0; key_repeats[key] = 0;
return; return;

View file

@ -2536,6 +2536,7 @@ struct capture_raw_ctx
vfsfile_t *audio; vfsfile_t *audio;
}; };
qboolean FS_FixPath(char *path, size_t pathsize);
static void *QDECL capture_raw_begin (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits) static void *QDECL capture_raw_begin (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits)
{ {
struct capture_raw_ctx *ctx = Z_Malloc(sizeof(*ctx)); struct capture_raw_ctx *ctx = Z_Malloc(sizeof(*ctx));
@ -2550,6 +2551,11 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
Z_Free(ctx); Z_Free(ctx);
return NULL; return NULL;
} }
if (!FS_FixPath(ctx->videonameprefix, sizeof(ctx->videonameprefix)))
{
Z_Free(ctx);
return NULL;
}
ctx->fsroot = FS_SYSTEM; ctx->fsroot = FS_SYSTEM;
ctx->audio = NULL; ctx->audio = NULL;
if (*sndkhz) if (*sndkhz)
@ -2563,7 +2569,7 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
*sndchannels = 6; *sndchannels = 6;
if (*sndchannels < 1) if (*sndchannels < 1)
*sndchannels = 1; *sndchannels = 1;
Q_snprintfz(filename, sizeof(filename), "%s/audio_%ichan_%ikhz_%ib.raw", ctx->videonameprefix, *sndchannels, *sndkhz/1000, *sndbits); Q_snprintfz(filename, sizeof(filename), "%saudio_%ichan_%ikhz_%ib.raw", ctx->videonameprefix, *sndchannels, *sndkhz/1000, *sndbits);
FS_CreatePath(filename, ctx->fsroot); FS_CreatePath(filename, ctx->fsroot);
ctx->audio = FS_OpenVFS(filename, "wb", ctx->fsroot); ctx->audio = FS_OpenVFS(filename, "wb", ctx->fsroot);
} }
@ -2580,7 +2586,7 @@ static void QDECL capture_raw_video (void *vctx, void *data, int frame, int widt
struct capture_raw_ctx *ctx = vctx; struct capture_raw_ctx *ctx = vctx;
char filename[MAX_OSPATH]; char filename[MAX_OSPATH];
ctx->frames = frame+1; ctx->frames = frame+1;
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension); Q_snprintfz(filename, sizeof(filename), "%s%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
SCR_ScreenShot(filename, ctx->fsroot, data, width, height); SCR_ScreenShot(filename, ctx->fsroot, data, width, height);
} }
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes) static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
@ -3205,6 +3211,12 @@ void Media_RecordDemo_f(void)
} }
CL_PlayDemo(Cmd_Argv(1), false); CL_PlayDemo(Cmd_Argv(1), false);
if (!cls.demoplayback)
{
Con_Printf("unable to play demo, not capturing\n");
return;
}
//FIXME: mamke sure it loaded okay
if (Cmd_Argc() > 2) if (Cmd_Argc() > 2)
Cmd_ShiftArgs(1, false); Cmd_ShiftArgs(1, false);
Media_RecordFilm_f(); Media_RecordFilm_f();

View file

@ -105,7 +105,7 @@ void M_DrawTextBox (int x, int y, int width, int lines)
M_DrawScalePic (cx, cy+8, 8, 8, p); M_DrawScalePic (cx, cy+8, 8, 8, p);
} }
int M_FindKeysForBind (char *command, int *keylist, int *keymods, int total) int M_FindKeysForBind (const char *command, int *keylist, int *keymods, int total)
{ {
int count; int count;
int j, m; int j, m;

View file

@ -468,7 +468,7 @@ void M_Keyup (int key, int unicode);
void M_Draw (int uimenu); void M_Draw (int uimenu);
#endif #endif
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys); void M_FindKeysForCommand (int pnum, const char *command, int *twokeys);
int M_FindKeysForBind (char *command, int *keylist, int *keymods, int total); int M_FindKeysForBind (const char *command, int *keylist, int *keymods, int total);
void M_Media_Draw (void); void M_Media_Draw (void);
void M_Media_Key (int key); void M_Media_Key (int key);

View file

@ -389,7 +389,10 @@ static void PClassic_DrawParticles(void)
particleframe = -1; particleframe = -1;
} }
if (r_refdef.useperspective)
r_partscale = 0.004 * tan (r_refdef.fov_x * (M_PI / 180) * 0.5f); r_partscale = 0.004 * tan (r_refdef.fov_x * (M_PI / 180) * 0.5f);
else
r_partscale = 0;
VectorScale (vup, 1.5, up); VectorScale (vup, 1.5, up);
VectorScale (vright, 1.5, right); VectorScale (vright, 1.5, right);

View file

@ -1310,17 +1310,21 @@ void buildmatricies(void)
float modelview[16]; float modelview[16];
float proj[16]; float proj[16];
float ofovx = r_refdef.fov_x,ofovy=r_refdef.fov_y; float ofovx = r_refdef.fov_x,ofovy=r_refdef.fov_y;
extern cvar_t gl_mindist, gl_maxdist;
V_ApplyAFov(csqc_playerview); V_ApplyAFov(csqc_playerview);
/*build modelview and projection*/ /*build view and projection matricies*/
Matrix4x4_CM_ModelViewMatrix(modelview, r_refdef.viewangles, r_refdef.vieworg); Matrix4x4_CM_ModelViewMatrix(modelview, r_refdef.viewangles, r_refdef.vieworg);
if (r_refdef.useperspective)
Matrix4x4_CM_Projection2(proj, r_refdef.fov_x, r_refdef.fov_y, 4); Matrix4x4_CM_Projection2(proj, r_refdef.fov_x, r_refdef.fov_y, 4);
else
Matrix4x4_CM_Orthographic(proj, -r_refdef.fov_x/2, r_refdef.fov_x/2, -r_refdef.fov_y/2, r_refdef.fov_y/2, gl_mindist.value, gl_maxdist.value>=1?gl_maxdist.value:9999);
/*build the project matrix*/ /*build the vp matrix*/
Matrix4_Multiply(proj, modelview, csqc_proj_matrix); Matrix4_Multiply(proj, modelview, csqc_proj_matrix);
/*build the unproject matrix (inverted project matrix)*/ /*build the unproject matrix (inverted vp matrix)*/
Matrix4_Invert(csqc_proj_matrix, csqc_proj_matrix_inverse); Matrix4_Invert(csqc_proj_matrix, csqc_proj_matrix_inverse);
csqc_rebuildmatricies = false; csqc_rebuildmatricies = false;
@ -1378,7 +1382,7 @@ static void QCBUILTIN PF_cs_unproject (pubprogfuncs_t *prinst, struct globalvars
ty = 1-ty; ty = 1-ty;
v[0] = tx*2-1; v[0] = tx*2-1;
v[1] = ty*2-1; v[1] = ty*2-1;
v[2] = in[2];//*2-1; v[2] = in[2]*2-1; //gl projection matrix scales -1 to 1 (unlike d3d, which is 0 to 1)
v[3] = 1; v[3] = 1;
//don't use 1, because the far clip plane really is an infinite distance away. and that tends to result division by infinity. //don't use 1, because the far clip plane really is an infinite distance away. and that tends to result division by infinity.
@ -4229,7 +4233,7 @@ qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state)
csqcdelta_playerents[playernum] = ent; csqcdelta_playerents[playernum] = ent;
return true; return G_FLOAT(OFS_RETURN);
} }
else if (csqcdelta_playerents[playernum]) else if (csqcdelta_playerents[playernum])
{ {

View file

@ -366,23 +366,12 @@ mpic_t *R2D_SafeCachePic (const char *path)
mpic_t *R2D_SafePicFromWad (const char *name) mpic_t *R2D_SafePicFromWad (const char *name)
{ {
char newnamewad[32]; void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs);
char newnamegfx[32];
shader_t *s; shader_t *s;
if (!qrenderer)
snprintf(newnamewad, sizeof(newnamewad), "wad/%s", name); return NULL;
snprintf(newnamegfx, sizeof(newnamegfx), "gfx/%s", name); s = R_RegisterCustom (va("gfx/%s", name), SUF_2D, Shader_Default2D, "wad");
/*
s = R_RegisterPic(newnamewad);
if (!(s->flags & SHADER_NOIMAGE))
return s; return s;
*/
s = R_RegisterPic(newnamegfx);
// if (!(s->flags & SHADER_NOIMAGE))
return s;
// return NULL;
} }

View file

@ -2615,6 +2615,42 @@ static void Sbar_Voice(int y)
#endif #endif
} }
void SCR_StringXY(char *str, float x, float y);
void SCR_DrawClock(void);
void SCR_DrawGameClock(void);
static void Sbar_DrawUPS(playerview_t *pv)
{
extern cvar_t show_speed;
static double lastupstime;
double t;
static float lastups;
char str[80];
float *vel;
int track;
extern cvar_t show_speed_x;
extern cvar_t show_speed_y;
if (!show_speed.ival)
return;
t = Sys_DoubleTime();
if ((t - lastupstime) >= 1.0/20)
{
if (cl.spectator)
track = Cam_TrackNum(pv);
else
track = -1;
if (track != -1)
vel = cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[track].velocity;
else
vel = pv->simvel;
lastups = sqrt((vel[0]*vel[0]) + (vel[1]*vel[1]));
lastupstime = t;
}
sprintf(str, "%3.1f UPS", lastups);
SCR_StringXY(str, show_speed_x.value, show_speed_y.value);
}
/* /*
=============== ===============
@ -2807,6 +2843,11 @@ void Sbar_Draw (playerview_t *pv)
if (scr_chatmode) if (scr_chatmode)
Sbar_ChatModeOverlay(pv); Sbar_ChatModeOverlay(pv);
} }
Sbar_DrawUPS (pv);
SCR_DrawClock();
SCR_DrawGameClock();
} }
//============================================================================= //=============================================================================

View file

@ -2455,9 +2455,11 @@ void S_StopAllSounds(qboolean clear)
if (sc->channel[i].sfx) if (sc->channel[i].sfx)
{ {
s = sc->channel[i].sfx; s = sc->channel[i].sfx;
sc->channel[i].sfx = NULL;
if (s->loadstate == SLS_LOADING) if (s->loadstate == SLS_LOADING)
COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING); ;//COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING);
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. if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly.
{ {
@ -2466,6 +2468,7 @@ void S_StopAllSounds(qboolean clear)
if (sc->ChannelUpdate) if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, &sc->channel[i], true); sc->ChannelUpdate(sc, &sc->channel[i], true);
} }
}
sc->total_chans = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS + NUM_MUSICS; // no statics sc->total_chans = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS + NUM_MUSICS; // no statics

View file

@ -34,16 +34,16 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{ {
char soname[MAX_OSPATH]; char soname[MAX_OSPATH];
int i; int i;
dllhandle_t lib; dllhandle_t *lib;
lib = NULL; lib = NULL;
if (!lib) if (!lib)
{ {
Q_snprintfz(soname, sizeof(soname), "%s.so", name); Q_snprintfz(soname, sizeof(soname), "%s.so", name);
lib = dlopen (soname, RTLD_LAZY); lib = (dllhandle_t*)dlopen (soname, RTLD_LAZY);
} }
if (!lib) if (!lib)
lib = dlopen (name, RTLD_LAZY); lib = (dllhandle_t*)dlopen (name, RTLD_LAZY);
if (!lib) if (!lib)
{ {
Con_Printf("%s\n", dlerror()); Con_Printf("%s\n", dlerror());
@ -578,7 +578,7 @@ vfsfile_t *VFSPIPE_Open(void)
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
qboolean MyRegGetStringValue(HKEY base, const char *keyname, const char *valuename, void *data, size_t datalen) qboolean MyRegGetStringValue(void *base, const char *keyname, const char *valuename, void *data, size_t datalen)
{ {
qboolean result = false; qboolean result = false;
HKEY subkey; HKEY subkey;

View file

@ -721,7 +721,7 @@ void Sys_Sleep (double seconds)
#ifdef HAVEAUTOUPDATE #ifdef HAVEAUTOUPDATE
int Sys_GetAutoUpdateSetting(void); int Sys_GetAutoUpdateSetting(void)
{ {
return -1; return -1;
} }

View file

@ -2883,21 +2883,23 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
if (*updatedpath) if (*updatedpath)
{ {
//fixme: unicode paths/commandline.
GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1);
if (CreateProcess(updatedpath, va("\"%s\" %s --fromfrontend \"%s\" \"%s\"", frontendpath, COM_Parse(GetCommandLineA()), SVNREVISIONSTR, frontendpath), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) if (CreateProcess(updatedpath, va("%s --fromfrontend \"%s\" \"%s\"", GetCommandLineA(), SVNREVISIONSTR, frontendpath), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo))
return true; return true;
} }
} }
else else
{ {
char frontendpath[MAX_OSPATH]; // char frontendpath[MAX_OSPATH];
//com_argv[ffe+1] is frontend revision //com_argv[ffe+1] is frontend revision
//com_argv[ffe+2] is frontend location //com_argv[ffe+2] is frontend location
if (atoi(com_argv[ffe+1]) > atoi(SVNREVISIONSTR)) if (atoi(com_argv[ffe+1]) > atoi(SVNREVISIONSTR))
{ {
wchar_t wide1[2048];
//ping-pong it back, to make sure we're running the most recent version. //ping-pong it back, to make sure we're running the most recent version.
GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); // GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1);
if (CreateProcess(com_argv[ffe+2], va("--fromfrontend \"%s\" \"%s\" %s", "", "", COM_Parse(GetCommandLineA())), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) if (CreateProcessW(widen(wide1, sizeof(wide1), com_argv[ffe+2]), GetCommandLineW(), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo))
return true; return true;
} }
if (com_argv[ffe+2]) if (com_argv[ffe+2])
@ -3167,7 +3169,11 @@ int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType)
#ifdef WEBCLIENT #ifdef WEBCLIENT
//using this like posix' access function, but with much more code, microsoftisms, and no errno codes/info //using this like posix' access function, but with much more code, microsoftisms, and no errno codes/info
//no, I don't really have a clue why it needs to be so long. //no, I don't really have a clue why it needs to be so long.
#include <svrapi.h> //#include <svrapi.h>
#ifndef ACCESS_READ
#define ACCESS_READ 0x1
#define ACCESS_WRITE 0x2
#endif
static BOOL microsoft_accessW(LPWSTR pszFolder, DWORD dwAccessDesired) static BOOL microsoft_accessW(LPWSTR pszFolder, DWORD dwAccessDesired)
{ {
HANDLE hToken; HANDLE hToken;
@ -3354,8 +3360,8 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
} }
} }
break; break;
case BFFM_IUNKNOWN: // case BFFM_IUNKNOWN:
break; // break;
} }
return 0; return 0;
} }

View file

@ -526,23 +526,27 @@ void Validation_Apply_Ruleset(void)
rulesetrule_t *rule; rulesetrule_t *rule;
cvar_t *var; cvar_t *var;
int i; int i;
char *rulesetname = ruleset.string;
if (!strcmp(rulesetname, "smackdown")) //officially, smackdown cannot authorise this, thus we do not use that name. however, imported configs tend to piss people off.
rulesetname = "strict";
#ifdef warningmsg #ifdef warningmsg
#pragma warningmsg("fixme: the following line should not be needed. ensure this is the case") #pragma warningmsg("fixme: the following line should not be needed. ensure this is the case")
#endif #endif
Validation_DelatchRulesets(); //make sure there's no old one Validation_DelatchRulesets(); //make sure there's no old one
if (!*ruleset.string || !strcmp(ruleset.string, "none") || !strcmp(ruleset.string, "default")) if (!*rulesetname || !strcmp(rulesetname, "none") || !strcmp(rulesetname, "default"))
return; //no ruleset is set return; //no ruleset is set
for (rs = rulesets; rs->rulesetname; rs++) for (rs = rulesets; rs->rulesetname; rs++)
{ {
if (!stricmp(rs->rulesetname, ruleset.string)) if (!stricmp(rs->rulesetname, rulesetname))
break; break;
} }
if (!rs->rulesetname) if (!rs->rulesetname)
{ {
Con_Printf("Cannot apply ruleset %s - not recognised\n", ruleset.string); Con_Printf("Cannot apply ruleset %s - not recognised\n", rulesetname);
return; return;
} }

View file

@ -2950,6 +2950,7 @@ void Cmd_WriteConfig_f(void)
char fname[MAX_OSPATH]; char fname[MAX_OSPATH];
char sysname[MAX_OSPATH]; char sysname[MAX_OSPATH];
qboolean all = true; qboolean all = true;
extern cvar_t cfg_save_all;
if (Cmd_IsInsecure() && Cmd_Argc() > 1) if (Cmd_IsInsecure() && Cmd_Argc() > 1)
{ {
@ -2969,7 +2970,7 @@ void Cmd_WriteConfig_f(void)
FS_CreatePath(fname, FS_GAMEONLY); FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wbp", FS_GAMEONLY); f = FS_OpenVFS(fname, "wbp", FS_GAMEONLY);
all = false; all = cfg_save_all.ival;
} }
else else
{ {
@ -2985,7 +2986,7 @@ void Cmd_WriteConfig_f(void)
FS_CreatePath(fname, FS_BASEGAMEONLY); FS_CreatePath(fname, FS_BASEGAMEONLY);
f = FS_OpenVFS(fname, "wbp", FS_BASEGAMEONLY); f = FS_OpenVFS(fname, "wbp", FS_BASEGAMEONLY);
all = true; all = cfg_save_all.ival || !*cfg_save_all.string;
} }
if (!f) if (!f)
{ {

View file

@ -1937,7 +1937,7 @@ void COM_FileBase (const char *in, char *out, int outlen)
s = in + strlen(in) - 1; s = in + strlen(in) - 1;
while (s > in && *s != '.') while (s > in && *s != '.' && *s != '/')
s--; s--;
for (s2 = s ; s2 > in && *s2 && *s2 != '/' ; s2--) for (s2 = s ; s2 > in && *s2 && *s2 != '/' ; s2--)

View file

@ -436,7 +436,8 @@ enum fs_relative{
FS_ROOT, //./ (the root basepath or root homepath.) FS_ROOT, //./ (the root basepath or root homepath.)
FS_GAMEONLY, //$gamedir/ FS_GAMEONLY, //$gamedir/
FS_GAMEDOWNLOADCACHE, //typically the same as FS_GAMEONLY FS_GAMEDOWNLOADCACHE, //typically the same as FS_GAMEONLY
FS_BASEGAMEONLY, //fte/ (fixme: should be the last basegame.) FS_BASEGAMEONLY, //fte/
FS_PUBGAMEONLY, //$gamedir/ or qw/ but not fte/
FS_PUBBASEGAMEONLY, //qw/ (fixme: should be the last non-private basedir) FS_PUBBASEGAMEONLY, //qw/ (fixme: should be the last non-private basedir)
FS_SYSTEM //a system path. absolute paths are explicitly allowed and expected. FS_SYSTEM //a system path. absolute paths are explicitly allowed and expected.
}; };

View file

@ -1438,6 +1438,24 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out
else else
snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname); snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname);
break; break;
case FS_PUBGAMEONLY:
last = NULL;
for (i = 0; i < sizeof(fs_manifest->gamepath)/sizeof(fs_manifest->gamepath[0]); i++)
{
if (fs_manifest->gamepath[i].path)
{
if (*fs_manifest->gamepath[i].path == '*')
continue;
last = fs_manifest->gamepath[i].path;
}
}
if (!last)
return false; //eep?
if (com_homepathenabled)
snprintf(out, outlen, "%s%s/%s", com_homepath, last, fname);
else
snprintf(out, outlen, "%s%s/%s", com_gamepath, last, fname);
break;
case FS_PUBBASEGAMEONLY: case FS_PUBBASEGAMEONLY:
last = NULL; last = NULL;
for (i = 0; i < sizeof(fs_manifest->gamepath)/sizeof(fs_manifest->gamepath[0]); i++) for (i = 0; i < sizeof(fs_manifest->gamepath)/sizeof(fs_manifest->gamepath[0]); i++)
@ -1512,14 +1530,19 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
return VFSOS_Open(fullname, mode); return VFSOS_Open(fullname, mode);
} }
return NULL; return NULL;
case FS_PUBGAMEONLY:
FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
if (*mode == 'w')
COM_CreatePath(fullname);
return VFSOS_Open(fullname, mode);
case FS_GAME: //load from paks in preference to system paths. overwriting be damned. case FS_GAME: //load from paks in preference to system paths. overwriting be damned.
case FS_PUBBASEGAMEONLY: //load from paks in preference to system paths. overwriting be damned. case FS_PUBBASEGAMEONLY: //load from paks in preference to system paths. overwriting be damned.
FS_NativePath(filename, relativeto, fullname, sizeof(fullname)); FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
break; break;
case FS_BINARYPATH: case FS_BINARYPATH:
FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
if (*mode == 'w') if (*mode == 'w')
COM_CreatePath(fullname); COM_CreatePath(fullname);
FS_NativePath(filename, relativeto, fullname, sizeof(fullname));
return VFSOS_Open(fullname, mode); return VFSOS_Open(fullname, mode);
case FS_ROOT: //always bypass packs and gamedirs case FS_ROOT: //always bypass packs and gamedirs
if (com_installer) if (com_installer)
@ -3327,13 +3350,13 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
Q_snprintfz(syspath, sizeof(syspath), "%sid1/pak0.pak", prefix[i]); Q_snprintfz(syspath, sizeof(syspath), "%sid1/pak0.pak", prefix[i]);
if (GetFileAttributesU(syspath) != INVALID_FILE_ATTRIBUTES) if (GetFileAttributesU(syspath) != INVALID_FILE_ATTRIBUTES)
{ {
Q_strncpyz(basepath, prefix[i], sizeof(basepath)); Q_strncpyz(basepath, prefix[i], basepathlen);
return true; return true;
} }
Q_snprintfz(syspath, sizeof(syspath), "%squake.exe", prefix[i]); Q_snprintfz(syspath, sizeof(syspath), "%squake.exe", prefix[i]);
if (GetFileAttributesU(syspath) != INVALID_FILE_ATTRIBUTES) if (GetFileAttributesU(syspath) != INVALID_FILE_ATTRIBUTES)
{ {
Q_strncpyz(basepath, prefix[i], sizeof(basepath)); Q_strncpyz(basepath, prefix[i], basepathlen);
return true; return true;
} }
} }

View file

@ -83,7 +83,7 @@ fragmentation works like IP, offset and morefrags. offset is *8 (decode: (offset
int net_drop; int net_drop;
cvar_t showpackets = SCVAR("showpackets", "0"); cvar_t showpackets = SCVAR("showpackets", "0");
cvar_t showdrop = SCVAR("showdrop", "0"); cvar_t showdrop = SCVAR("showdrop", "0");
cvar_t qport = CVARF("qport", "0", CVAR_NOSAVE); cvar_t qport = CVARF("qport_", "0", CVAR_NOSAVE);
cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation."); cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets."); cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets.");

View file

@ -2338,8 +2338,15 @@ int FTENET_Generic_GetLocalAddresses(struct ftenet_generic_connection_s *con, un
!*(int*)&adr.address.ip6[12]) !*(int*)&adr.address.ip6[12])
{ {
//ipv6 socket bound to the ipv4-any address is a bit weird, but oh well. //ipv6 socket bound to the ipv4-any address is a bit weird, but oh well.
//FIXME: should we first validate that we support hybrid sockets? #ifdef _WIN32
//win32 is buggy and treats binding to [::] as [::ffff:0.0.0.0] (even with pure ipv6 sockets)
//explicitly binding to [::ffff:0.0.0.0] appears to fail in windows, thus any such socket will definitely support ipv6.
qboolean canipv4 = (con->addrtype[0] == NA_IP) || (con->addrtype[1] == NA_IP);
found = FTENET_GetLocalAddress(adr.port, false, canipv4, true, adrflags, addresses, maxaddresses);
#else
//FIXME: we should validate that we support hybrid sockets?
found = FTENET_GetLocalAddress(adr.port, false, true, false, adrflags, addresses, maxaddresses); found = FTENET_GetLocalAddress(adr.port, false, true, false, adrflags, addresses, maxaddresses);
#endif
} }
else else
{ {
@ -2357,13 +2364,7 @@ int FTENET_Generic_GetLocalAddresses(struct ftenet_generic_connection_s *con, un
ipx = true; ipx = true;
else if (adr.type == NA_IPV6) else if (adr.type == NA_IPV6)
{ {
#ifdef IPV6_V6ONLY ipv4 = (con->addrtype[0] == NA_IP) || (con->addrtype[1] == NA_IP);
int ipv6only = true;
int optlen = sizeof(ipv6only);
getsockopt(con->thesocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optlen);
if (!ipv6only)
ipv4 = true;
#endif
ipv6 = true; ipv6 = true;
} }
@ -2633,6 +2634,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
*/ */
((struct sockaddr_in6*)&qs)->sin6_port = port; ((struct sockaddr_in6*)&qs)->sin6_port = port;
temp = sizeof(struct sockaddr_in6); temp = sizeof(struct sockaddr_in6);
adr.type = NA_IPV6;
hybrid = true; hybrid = true;
} }
else else
@ -5000,6 +5002,7 @@ void NET_PrintAddresses(ftenet_connections_t *collection)
netadr_t addr[64]; netadr_t addr[64];
struct ftenet_generic_connection_s *con[sizeof(addr)/sizeof(addr[0])]; struct ftenet_generic_connection_s *con[sizeof(addr)/sizeof(addr[0])];
int flags[sizeof(addr)/sizeof(addr[0])]; int flags[sizeof(addr)/sizeof(addr[0])];
qboolean warn = true;
if (!collection) if (!collection)
return; return;
@ -5008,11 +5011,73 @@ void NET_PrintAddresses(ftenet_connections_t *collection)
for (i = 0; i < m; i++) for (i = 0; i < m; i++)
{ {
if (addr[i].type == NA_INVALID) if (addr[i].type != NA_INVALID)
Con_Printf("net address (%s): no addresses\n", con[i]->name); {
else warn = false;
Con_Printf("net address (%s): %s\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i])); if (addr[i].type == NA_LOOPBACK)
{
//we don't list 127.0.0.1 or ::1, so don't bother with this either. its not interesting.
// Con_Printf("internal address (%s): %s\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
} }
if (addr[i].type == NA_IPV6)
{
if ((*(int*)addr[i].address.ip6&BigLong(0xffc00000)) == BigLong(0xfe800000)) //fe80::/10
{
Con_Printf("lan address (%s): %s (link-local)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if ((*(int*)addr[i].address.ip6&BigLong(0xfe000000)) == BigLong(0xfc00000)) //fc::/7
{
Con_Printf("lan address (%s): %s (ULA/private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if (*(int*)addr[i].address.ip6 == BigLong(0x20010000)) //2001::/32
{
Con_Printf("net address (%s): %s (toredo)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if ((*(int*)addr[i].address.ip6&BigLong(0xffff0000)) == BigLong(0x20020000)) //2002::/16
{
Con_Printf("net address (%s): %s (6to4)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
}
if (addr[i].type == NA_IP)
{
if ((*(int*)addr[i].address.ip&BigLong(0xffff0000)) == BigLong(0xA9FE0000)) //169.254.x.x/16
{
Con_Printf("lan address (%s): %s (link-local)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if ((*(int*)addr[i].address.ip&BigLong(0xff000000)) == BigLong(0x0a000000)) //10.x.x.x/8
{
Con_Printf("lan address (%s): %s (private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if ((*(int*)addr[i].address.ip&BigLong(0xfff00000)) == BigLong(0xac100000)) //172.16.x.x/12
{
Con_Printf("lan address (%s): %s (private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if ((*(int*)addr[i].address.ip&BigLong(0xffff0000)) == BigLong(0xc0a80000)) //192.168.x.x/16
{
Con_Printf("lan address (%s): %s (private)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
if ((*(int*)addr[i].address.ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //10.64.x.x/10
{
Con_Printf("lan address (%s): %s (CGNAT)\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
continue;
}
}
Con_Printf("net address (%s): %s\n", con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
}
}
if (warn)
Con_Printf("net address (%s): no addresses\n", con[i]->name);
} }
//============================================================================= //=============================================================================

View file

@ -279,7 +279,10 @@ int QDECL QCEditor (pubprogfuncs_t *prinst, const char *filename, int *line, int
if (wantquit) if (wantquit)
return DEBUG_TRACE_ABORT; return DEBUG_TRACE_ABORT;
if (!*filename || !line || !*line) //don't try editing an empty line, it won't work if (!*filename || !line || !*line) //don't try editing an empty line, it won't work
{
Con_Printf("Unable to debug, pelase disable optimisations\n");
return DEBUG_TRACE_OFF; return DEBUG_TRACE_OFF;
}
Sys_SendKeyEvents(); Sys_SendKeyEvents();
debuggerresume = -1; debuggerresume = -1;
debuggerresumeline = *line; debuggerresumeline = *line;
@ -532,6 +535,13 @@ void VARGS PR_CB_Free(void *mem)
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
//model functions //model functions
//DP_QC_GETSURFACE //DP_QC_GETSURFACE
static void PF_BuildSurfaceMesh(model_t *model, unsigned int surfnum)
{
void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *cookie);
if (model->fromgame == fg_quake)
ModQ1_Batches_BuildQ1Q2Poly(model, &model->surfaces[surfnum], NULL);
//fixme: q3...
}
// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
void QCBUILTIN PF_getsurfacenumpoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_getsurfacenumpoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -551,9 +561,11 @@ void QCBUILTIN PF_getsurfacenumpoints(pubprogfuncs_t *prinst, struct globalvars_
{ {
surfnum += model->firstmodelsurface; surfnum += model->firstmodelsurface;
if (!model->surfaces[surfnum].mesh) if (!model->surfaces[surfnum].mesh)
G_FLOAT(OFS_RETURN) = 0; //not loaded properly. PF_BuildSurfaceMesh(model, surfnum);
else if (model->surfaces[surfnum].mesh)
G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numvertexes; G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numvertexes;
else
G_FLOAT(OFS_RETURN) = 0; //not loaded properly.
} }
} }
// #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
@ -701,6 +713,13 @@ static float getsurface_clippointtri(model_t *model, msurface_t *surf, vec3_t po
float dist; float dist;
int e; int e;
float *v1, *v2; float *v1, *v2;
if (!mesh)
{
PF_BuildSurfaceMesh(model, surf - model->surfaces);
mesh = surf->mesh;
if (!mesh)
return 0;
}
for (j = 0; j < mesh->numindexes; j+=3) for (j = 0; j < mesh->numindexes; j+=3)
{ {
//calculate the distance from the plane //calculate the distance from the plane
@ -765,7 +784,7 @@ void QCBUILTIN PF_getsurfacenearpoint(pubprogfuncs_t *prinst, struct globalvars_
if (!model || model->type != mod_brush) if (!model || model->type != mod_brush)
return; return;
if (model->fromgame == fg_quake) if (model->fromgame == fg_quake || model->fromgame == fg_quake2)
{ {
//all polies, we can skip parts. special case. //all polies, we can skip parts. special case.
surf = model->surfaces + model->firstmodelsurface; surf = model->surfaces + model->firstmodelsurface;
@ -855,7 +874,12 @@ void QCBUILTIN PF_getsurfacenumtriangles(pubprogfuncs_t *prinst, struct globalva
else else
{ {
surfnum += model->firstmodelsurface; surfnum += model->firstmodelsurface;
if (!model->surfaces[surfnum].mesh)
PF_BuildSurfaceMesh(model, surfnum);
if (model->surfaces[surfnum].mesh)
G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numindexes/3; G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numindexes/3;
else
G_FLOAT(OFS_RETURN) = 0;
} }
} }
// #629 float(entity e, float s) getsurfacetriangle // #629 float(entity e, float s) getsurfacetriangle
@ -876,6 +900,9 @@ void QCBUILTIN PF_getsurfacetriangle(pubprogfuncs_t *prinst, struct globalvars_s
{ {
surfnum += model->firstmodelsurface; surfnum += model->firstmodelsurface;
if (!model->surfaces[surfnum].mesh)
PF_BuildSurfaceMesh(model, surfnum);
if (model->surfaces[surfnum].mesh)
if (firstidx+2 < model->surfaces[surfnum].mesh->numindexes) if (firstidx+2 < model->surfaces[surfnum].mesh->numindexes)
{ {
G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].mesh->indexes[firstidx+0]; G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].mesh->indexes[firstidx+0];
@ -905,6 +932,8 @@ void QCBUILTIN PF_getsurfacepointattribute(pubprogfuncs_t *prinst, struct global
if (model && model->type == mod_brush && surfnum < model->nummodelsurfaces) if (model && model->type == mod_brush && surfnum < model->nummodelsurfaces)
{ {
surfnum += model->firstmodelsurface; surfnum += model->firstmodelsurface;
if (!model->surfaces[surfnum].mesh)
PF_BuildSurfaceMesh(model, surfnum);
if (model->surfaces[surfnum].mesh) if (model->surfaces[surfnum].mesh)
if (pointnum < model->surfaces[surfnum].mesh->numvertexes) if (pointnum < model->surfaces[surfnum].mesh->numvertexes)
{ {
@ -1367,12 +1396,20 @@ void QCBUILTIN PF_memalloc (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
{ {
int size = G_INT(OFS_PARM0); int size = G_INT(OFS_PARM0);
void *ptr = prinst->AddressableAlloc(prinst, size); void *ptr = prinst->AddressableAlloc(prinst, size);
if (ptr)
{
memset(ptr, 0, size); memset(ptr, 0, size);
G_INT(OFS_RETURN) = (char*)ptr - prinst->stringtable; G_INT(OFS_RETURN) = (char*)ptr - prinst->stringtable;
}
else
G_INT(OFS_RETURN) = 0;
} }
void QCBUILTIN PF_memfree (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_memfree (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
prinst->AddressableFree(prinst, prinst->stringtable + G_INT(OFS_PARM0)); int qcptr = G_INT(OFS_PARM0);
void *cptr = prinst->stringtable + G_INT(OFS_PARM0);
if (qcptr)
prinst->AddressableFree(prinst, cptr);
} }
void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -1731,7 +1768,7 @@ qboolean QC_FixFileName(const char *name, const char **result, const char **fall
*fallbackread = name; *fallbackread = name;
//if its a user config, ban any fallback locations so that csqc can't read passwords or whatever. //if its a user config, ban any fallback locations so that csqc can't read passwords or whatever.
if ((!strchr(name, '/') || strnicmp(name, "configs/", 8)) && !stricmp(COM_FileExtension(name, ext, sizeof(ext)), "cfg")) if ((!strchr(name, '/') || strnicmp(name, "configs/", 8)) && !stricmp(COM_FileExtension(name, ext, sizeof(ext)), "cfg") && strnicmp(name, "particles/", 10))
*fallbackread = NULL; *fallbackread = NULL;
*result = va("data/%s", name); *result = va("data/%s", name);
return true; return true;

View file

@ -736,6 +736,8 @@ enum terrainedit_e
// ter_autopaint_h, //vector pos, float radius, float percent, string tex1, string tex2 (paint tex1/tex2 // ter_autopaint_h, //vector pos, float radius, float percent, string tex1, string tex2 (paint tex1/tex2
// ter_autopaint_n //vector pos, float radius, float percent, string tex1, string tex2 // ter_autopaint_n //vector pos, float radius, float percent, string tex1, string tex2
ter_tex_mask //string tex
}; };
enum enum

View file

@ -135,8 +135,6 @@ typedef struct areanode_s
link_t edicts; link_t edicts;
} areanode_t; } areanode_t;
#define AREA_DEPTH 4
#define AREA_NODES 32 //pow(2, AREA_DEPTH+1)
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,wedict_t,area) #define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,wedict_t,area)
typedef struct wedict_s wedict_t; typedef struct wedict_s wedict_t;
@ -186,7 +184,8 @@ struct world_s
struct pubprogfuncs_s *progs; struct pubprogfuncs_s *progs;
qboolean usesolidcorpse; //to disable SOLID_CORPSE when running hexen2 due to conflict. qboolean usesolidcorpse; //to disable SOLID_CORPSE when running hexen2 due to conflict.
model_t *worldmodel; model_t *worldmodel;
areanode_t areanodes[AREA_NODES]; areanode_t *areanodes;
int areanodedepth;
int numareanodes; int numareanodes;
areanode_t portallist; areanode_t portallist;

View file

@ -1371,7 +1371,7 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename)
//default to only map the ascii-compatible chars from the quake font. //default to only map the ascii-compatible chars from the quake font.
if (*fontfilename) if (*fontfilename)
{ {
f->singletexture = R_LoadHiResTexture(fontfilename, "fonts", IF_UIPIC|IF_NOMIPMAP); f->singletexture = R_LoadHiResTexture(fontfilename, "fonts:charsets", IF_UIPIC|IF_NOMIPMAP);
if (f->singletexture->status == TEX_LOADING) if (f->singletexture->status == TEX_LOADING)
COM_WorkerPartialSync(f->singletexture, &f->singletexture->status, TEX_LOADING); COM_WorkerPartialSync(f->singletexture, &f->singletexture->status, TEX_LOADING);
} }

View file

@ -341,6 +341,7 @@ typedef struct heightmap_s
char *texmask; //for editing - visually masks off the areas which CANNOT accept this texture
struct relight_ctx_s *relightcontext; struct relight_ctx_s *relightcontext;
struct llightinfo_s *lightthreadmem; struct llightinfo_s *lightthreadmem;
qboolean inheritedlightthreadmem; qboolean inheritedlightthreadmem;
@ -462,6 +463,7 @@ static qboolean Terr_InitLightmap(hmsection_t *s, qboolean initialise)
hm->numusedlmsects++; hm->numusedlmsects++;
Z_Free(lms); Z_Free(lms);
initialise = true;
} }
if (initialise && s->lightmap >= 0) if (initialise && s->lightmap >= 0)
@ -1873,7 +1875,7 @@ static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy
for (x = 0; x < SECTIONSPERBLOCK; x++) for (x = 0; x < SECTIONSPERBLOCK; x++)
{ {
s = Terr_GetSection(hm, sx+x, sy+y, TGS_WAITLOAD|TGS_NODOWNLOAD); s = Terr_GetSection(hm, sx+x, sy+y, TGS_WAITLOAD|TGS_NODOWNLOAD);
if (s && s->loadstate == TSLS_LOADED) if (s && s->loadstate == TSLS_LOADED && Terr_InitLightmap(s, false))
{ {
dbh.offset[y*SECTIONSPERBLOCK + x] = VFS_TELL(f); dbh.offset[y*SECTIONSPERBLOCK + x] = VFS_TELL(f);
Terr_Save(hm, s, f, sx+x, sy+y, writever); Terr_Save(hm, s, f, sx+x, sy+y, writever);
@ -1974,6 +1976,7 @@ static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, unsigned int
if (section->loadstate == TSLS_FAILED && (flags & TGS_DEFAULTONFAIL)) if (section->loadstate == TSLS_FAILED && (flags & TGS_DEFAULTONFAIL))
{ {
section->flags = (section->flags & ~TSF_EDITED); section->flags = (section->flags & ~TSF_EDITED);
section->loadstate = TSLS_LOADED;
Terr_ClearSection(section); Terr_ClearSection(section);
Terr_GenerateDefault(hm, section); Terr_GenerateDefault(hm, section);
} }
@ -2972,6 +2975,24 @@ void Terr_DrawInBounds(struct tdibctx *ctx, int x, int y, int w, int h)
if (R_CullBox(mins, maxs)) if (R_CullBox(mins, maxs))
return; return;
if (hm->texmask)
{
for (i = 0; i < 4; i++)
{
if (!*s->texname[i])
break;
if (!strcmp(s->texname[i], hm->texmask))
break;
}
if (i == 4)
{ //flicker if the surface cannot accept the named texture
int xor = (x&1)^(y&1);
if (((int)(realtime*10) & 1) ^ xor)
return;
}
}
b = BE_GetTempBatch(); b = BE_GetTempBatch();
if (!b) if (!b)
return; return;
@ -3864,8 +3885,8 @@ qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec
*/ */
//make sure the start tile is valid //make sure the start tile is valid
for (y = pos[1] + emins[1]; y <= pos[1] + emaxs[1]; y++) for (y = pos[1] + emins[1]; y <= (int)(pos[1] + emaxs[1]); y++)
for (x = pos[0] + emins[0]; x <= pos[0] + emaxs[0]; x++) for (x = pos[0] + emins[0]; x <= (int)(pos[0] + emaxs[0]); x++)
Heightmap_Trace_Square(&hmtrace, x, y); Heightmap_Trace_Square(&hmtrace, x, y);
for(;;) for(;;)
{ {
@ -4239,7 +4260,7 @@ static void ted_texpaint(void *ctx, hmsection_t *s, int idx, float wx, float wy,
unsigned char *lm = ted_getlightmap(s, idx); unsigned char *lm = ted_getlightmap(s, idx);
const char *texname = ctx; const char *texname = ctx;
int t; int t;
vec3_t newval; vec4_t newval;
if (w > 1) if (w > 1)
w = 1; w = 1;
@ -4249,12 +4270,21 @@ static void ted_texpaint(void *ctx, hmsection_t *s, int idx, float wx, float wy,
{ {
if (!strncmp(s->texname[t], texname, sizeof(s->texname[t])-1)) if (!strncmp(s->texname[t], texname, sizeof(s->texname[t])-1))
{ {
int extra;
newval[0] = (t == 0); newval[0] = (t == 0);
newval[1] = (t == 1); newval[1] = (t == 1);
newval[2] = (t == 2); newval[2] = (t == 2);
newval[3] = (t == 3);
extra = 255 - (lm[0]+lm[1]+lm[2]);
lm[2] = lm[2]*(1-w) + (255*newval[0]*(w)); lm[2] = lm[2]*(1-w) + (255*newval[0]*(w));
lm[1] = lm[1]*(1-w) + (255*newval[1]*(w)); lm[1] = lm[1]*(1-w) + (255*newval[1]*(w));
lm[0] = lm[0]*(1-w) + (255*newval[2]*(w)); lm[0] = lm[0]*(1-w) + (255*newval[2]*(w));
extra = extra*(1-w) + (255*newval[3]*(w));
//the extra stuff is to cope with numerical precision. add any lost values to the new texture instead of the implicit one
extra = 255 - (extra+lm[0]+lm[1]+lm[2]);
if (t != 3)
lm[2-t] += extra;
return; return;
} }
} }
@ -4651,6 +4681,15 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
G_INT(OFS_RETURN) = PR_TempString(prinst, s->texname[x]); G_INT(OFS_RETURN) = PR_TempString(prinst, s->texname[x]);
} }
break; break;
case ter_tex_mask:
Z_Free(hm->texmask);
hm->texmask = NULL;
if (G_INT(OFS_PARM1) == 0)
hm->texmask = NULL;
else
hm->texmask = Z_StrDup(PR_GetStringOfs(prinst, OFS_PARM1));
break;
case ter_tex_kill: case ter_tex_kill:
{ {
int x, y; int x, y;

View file

@ -2531,7 +2531,6 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *
return true; return true;
} }
#ifndef SERVERONLY
void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *cookie) void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *cookie)
{ {
unsigned int vertidx; unsigned int vertidx;
@ -2543,6 +2542,22 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
int sty; int sty;
// int w,h; // int w,h;
if (!mesh)
{
mesh = surf->mesh = ZG_Malloc(&mod->memgroup, sizeof(mesh_t) + (sizeof(vecV_t)+sizeof(vec2_t)*(1+1)+sizeof(vec3_t)*3+sizeof(vec4_t)*1)* surf->numedges + sizeof(index_t)*(surf->numedges-2)*3);
mesh->numvertexes = surf->numedges;
mesh->numindexes = (mesh->numvertexes-2)*3;
mesh->istrifan = true;
mesh->xyz_array = (vecV_t*)(mesh+1);
mesh->st_array = (vec2_t*)(mesh->xyz_array+mesh->numvertexes);
mesh->lmst_array[0] = (vec2_t*)(mesh->st_array+mesh->numvertexes);
mesh->normals_array = (vec3_t*)(mesh->lmst_array[0]+mesh->numvertexes);
mesh->snormals_array = (vec3_t*)(mesh->normals_array+mesh->numvertexes);
mesh->tnormals_array = (vec3_t*)(mesh->snormals_array+mesh->numvertexes);
mesh->colors4f_array[0] = (vec4_t*)(mesh->tnormals_array+mesh->numvertexes);
mesh->indexes = (index_t*)(mesh->colors4f_array[0]+mesh->numvertexes);
}
//output the mesh's indicies //output the mesh's indicies
for (i=0 ; i<mesh->numvertexes-2 ; i++) for (i=0 ; i<mesh->numvertexes-2 ; i++)
{ {
@ -2580,10 +2595,15 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
else else
*/ */
{ {
mesh->st_array[i][0] = s/surf->texinfo->texture->width; mesh->st_array[i][0] = s;
mesh->st_array[i][1] = t/surf->texinfo->texture->height; mesh->st_array[i][1] = t;
if (surf->texinfo->texture->width)
mesh->st_array[i][0] /= surf->texinfo->texture->width;
if (surf->texinfo->texture->height)
mesh->st_array[i][1] /= surf->texinfo->texture->height;
} }
#ifndef SERVERONLY
if (gl_lightmap_average.ival) if (gl_lightmap_average.ival)
{ {
for (sty = 0; sty < 1; sty++) for (sty = 0; sty < 1; sty++)
@ -2593,6 +2613,7 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
} }
} }
else else
#endif
{ {
for (sty = 0; sty < 1; sty++) for (sty = 0; sty < 1; sty++)
{ {
@ -2635,6 +2656,7 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
} }
} }
#ifndef SERVERONLY
static void Mod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxindicies, void (*build)(model_t *mod, msurface_t *surf, builddata_t *bd), builddata_t *bd) static void Mod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxindicies, void (*build)(model_t *mod, msurface_t *surf, builddata_t *bd), builddata_t *bd)
{ {
batch_t *batch; batch_t *batch;

View file

@ -489,7 +489,7 @@ void R_SetupGL (float stereooffset)
} }
else else
{ {
Matrix4x4_CM_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, -fov_y/2, fov_y/2, 0, gl_maxdist.value>=1?gl_maxdist.value:9999); Matrix4x4_CM_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, -fov_y/2, fov_y/2, gl_mindist.value, gl_maxdist.value>=1?gl_maxdist.value:9999);
} }
newa[0] = r_refdef.viewangles[0]; newa[0] = r_refdef.viewangles[0];

View file

@ -3253,8 +3253,6 @@ void Shader_Reset(shader_t *s)
Shader_Free(s); Shader_Free(s);
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
s->flags |= SHADER_IMAGEPENDING;
s->remapto = s; s->remapto = s;
s->id = id; s->id = id;
s->width = w; s->width = w;
@ -5127,7 +5125,7 @@ void Shader_DefaultBSPVertex(const char *shortname, shader_t *s, const void *arg
s->numpasses = 1; s->numpasses = 1;
s->numdeforms = 0; s->numdeforms = 0;
s->flags = SHADER_IMAGEPENDING|SHADER_DEPTHWRITE|SHADER_CULL_FRONT; s->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT;
s->sort = SHADER_SORT_OPAQUE; s->sort = SHADER_SORT_OPAQUE;
s->uses = 1; s->uses = 1;
} }
@ -5138,7 +5136,7 @@ void Shader_DefaultBSPFlare(const char *shortname, shader_t *s, const void *args
return; return;
pass = &s->passes[0]; pass = &s->passes[0];
pass->flags = SHADER_IMAGEPENDING|SHADER_PASS_NOCOLORARRAY; pass->flags = SHADER_PASS_NOCOLORARRAY;
pass->shaderbits |= SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ONE; pass->shaderbits |= SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ONE;
pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0); pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0);
pass->rgbgen = RGB_GEN_VERTEX_LIGHTING; pass->rgbgen = RGB_GEN_VERTEX_LIGHTING;
@ -5156,7 +5154,7 @@ void Shader_DefaultBSPFlare(const char *shortname, shader_t *s, const void *args
s->numpasses = 1; s->numpasses = 1;
s->numdeforms = 0; s->numdeforms = 0;
s->flags = SHADER_IMAGEPENDING|SHADER_FLARE; s->flags = SHADER_FLARE;
s->sort = SHADER_SORT_ADDITIVE; s->sort = SHADER_SORT_ADDITIVE;
s->uses = 1; s->uses = 1;
@ -5243,7 +5241,7 @@ void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs)
"sort additive\n" "sort additive\n"
"}\n" "}\n"
); );
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, NULL, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP));
} }
else else
{ {
@ -5260,7 +5258,7 @@ void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs)
"sort additive\n" "sort additive\n"
"}\n" "}\n"
); );
TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, NULL, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); TEXASSIGN(s->defaulttextures->base, R_LoadHiResTexture(s->name, genargs, IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP));
} }
} }
@ -5374,7 +5372,7 @@ static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
parsestate.mode = parsemode; parsestate.mode = parsemode;
// set defaults // set defaults
s->flags = SHADER_IMAGEPENDING|SHADER_CULL_FRONT; s->flags = SHADER_CULL_FRONT;
s->uses = 1; s->uses = 1;
while (Shader_ReadShaderTerms(s, &shadersource, parsemode, &conddepth, sizeof(cond)/sizeof(cond[0]), cond)) while (Shader_ReadShaderTerms(s, &shadersource, parsemode, &conddepth, sizeof(cond)/sizeof(cond[0]), cond))
@ -5849,7 +5847,7 @@ int R_GetShaderSizes(shader_t *shader, int *width, int *height, qboolean blockti
{ {
if (!shader) if (!shader)
return false; return false;
if (shader->flags & SHADER_IMAGEPENDING) if (!shader->width && !shader->height)
{ {
int i; int i;
if (width) if (width)
@ -5872,7 +5870,6 @@ int R_GetShaderSizes(shader_t *shader, int *width, int *height, qboolean blockti
} }
} }
shader->flags &= ~SHADER_IMAGEPENDING;
for (i = 0; i < shader->numpasses; i++) for (i = 0; i < shader->numpasses; i++)
{ {
if (shader->passes[i].texgen == T_GEN_SINGLEMAP) if (shader->passes[i].texgen == T_GEN_SINGLEMAP)

View file

@ -530,7 +530,7 @@ struct shader_s
SHADER_DEFORMV_BULGE = 1 << 5, SHADER_DEFORMV_BULGE = 1 << 5,
SHADER_AUTOSPRITE = 1 << 6, SHADER_AUTOSPRITE = 1 << 6,
SHADER_FLARE = 1 << 7, SHADER_FLARE = 1 << 7,
SHADER_IMAGEPENDING = 1 << 8, //FIXME //8
SHADER_ENTITY_MERGABLE = 1 << 9, SHADER_ENTITY_MERGABLE = 1 << 9,
SHADER_VIDEOMAP = 1 << 10, SHADER_VIDEOMAP = 1 << 10,
SHADER_DEPTHWRITE = 1 << 11, //some pass already wrote depth. not used by the renderer. SHADER_DEPTHWRITE = 1 << 11, //some pass already wrote depth. not used by the renderer.

View file

@ -395,7 +395,7 @@ static void FSPPAPI_ClosePath(searchpathfuncs_t *handle)
Z_Free(handle); Z_Free(handle);
} }
int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(const char *, qofs_t, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath) int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath)
{ {
int rootlen = strlen(rootpath); int rootlen = strlen(rootpath);
char *sub; char *sub;
@ -412,7 +412,7 @@ int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(con
sub++; sub++;
if (wildcmp(match, sub)) if (wildcmp(match, sub))
{ {
if (!func(sub, f->length, parm, spath)) if (!func(sub, f->length, (time_t)0, parm, spath))
return false; return false;
} }
} }

View file

@ -333,7 +333,7 @@ void startquake(char *manif)
Sys_Printf("Starting up (Built "__DATE__ ", " __TIME__")\n"); Sys_Printf("Starting up (Built "__DATE__ ", " __TIME__")\n");
COM_InitArgv(parms.argc, parms.argv); COM_InitArgv(parms.argc, parms.argv);
TL_InitLanguages(); TL_InitLanguages("");
#ifdef SERVERONLY #ifdef SERVERONLY
SV_Init(&parms); SV_Init(&parms);
#else #else

View file

@ -6408,6 +6408,92 @@ QCC_sref_t QCC_PR_GenerateLogicalNot(QCC_sref_t e, const char *errormessage)
} }
} }
QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit)
{
//casting from an accessor uses the base type of that accessor (this allows us to properly read void* accessors)
if (src.cast->type == ev_accessor)
src.cast = src.cast->parentclass;
/*you may cast from a type to itself*/
if (!typecmp(src.cast, cast))
{
//no-op
}
/*you may cast from const 0 to any other basic type for free (from either int or float for simplicity). things get messy when its a struct*/
else if (QCC_SRef_IsNull(src) && cast->type != ev_struct && cast->type != ev_union)
{
QCC_FreeTemp(src);
if (cast->size == 3)// || cast->type == ev_variant)
src = QCC_MakeVectorConst(0,0,0);
else
src = QCC_MakeIntConst(0);
src.cast = cast;
}
/*cast from int->float will convert*/
else if (cast->type == ev_float && src.cast->type == ev_integer)
src = QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], src, nullsref, NULL);
/*cast from float->int will convert*/
else if (cast->type == ev_integer && src.cast->type == ev_float)
src = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], src, nullsref, NULL);
else if (cast->type == ev_entity && src.cast->type == ev_entity)
{
if (implicit)
{ //this is safe if the source inherits from the dest type
//but we should warn if the other way around
QCC_type_t *t = src.cast;
while(t)
{
if (!typecmp_lax(t, cast))
break;
t = t->parentclass;
}
if (!t)
{
char typea[256];
char typeb[256];
TypeName(src.cast, typea, sizeof(typea));
TypeName(cast, typeb, sizeof(typeb));
QCC_PR_ParseWarning(0, "Implicit cast from %s to %s\n", typea, typeb);
}
}
src.cast = cast;
}
/*variants can be cast from/to anything without warning, even implicitly. FIXME: size issues*/
else if (cast->type == ev_variant || src.cast->type == ev_variant)
src.cast = cast;
/*these casts are fine when explicit*/
else if (
/*you may explicitly cast between pointers and ints (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/
((cast->type == ev_pointer || cast->type == ev_string || cast->type == ev_integer) && (src.cast->type == ev_pointer || src.cast->type == ev_string || src.cast->type == ev_integer))
//functions can be explicitly cast from one to another
|| (cast->type == ev_function && src.cast->type == ev_function)
//ents->ints || ints->ents. WARNING: the integer value of ent types is engine specific.
|| (cast->type == ev_entity && src.cast->type == ev_integer)
|| (cast->type == ev_integer && src.cast->type == ev_entity)
)
{
//direct cast
if (implicit && typecmp_lax(src.cast, cast))
{
char typea[256];
char typeb[256];
TypeName(src.cast, typea, sizeof(typea));
TypeName(cast, typeb, sizeof(typeb));
QCC_PR_ParseWarning(0, "Implicit cast from %s to %s\n", typea, typeb);
}
src.cast = cast;
}
else
{
char typea[256];
char typeb[256];
TypeName(src.cast, typea, sizeof(typea));
TypeName(cast, typeb, sizeof(typeb));
QCC_PR_ParseError(0, "Cannot cast from %s to %s\n", typea, typeb);
}
return src;
}
/* /*
============ ============
PR_Term PR_Term
@ -6583,55 +6669,7 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
//not a single term, so we can cast the result of function calls. just make sure its not too high a priority //not a single term, so we can cast the result of function calls. just make sure its not too high a priority
//and yeah, okay, use defs not refs. whatever. //and yeah, okay, use defs not refs. whatever.
e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA);
e = QCC_EvaluateCast(e, newtype, false);
//casting from an accessor uses the base type of that accessor (this allows us to properly read void* accessors)
if (e.cast->type == ev_accessor)
e.cast = e.cast->parentclass;
/*you may cast from a type to itself*/
if (!typecmp(e.cast, newtype))
{
}
/*you may cast from const 0 to any type of same size for free (from either int or float for simplicity)*/
else if (newtype->size == e.cast->size && QCC_SRef_IsNull(e))
{
e.sym->referenced = true;
//direct cast
return QCC_PR_BuildRef(retbuf, REF_GLOBAL, e, nullsref, newtype, true);
}
/*cast from int->float will convert*/
else if (newtype->type == ev_float && e.cast->type == ev_integer)
return QCC_DefToRef(retbuf, QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, nullsref, NULL));
/*cast from float->int will convert*/
else if (newtype->type == ev_integer && e.cast->type == ev_float)
return QCC_DefToRef(retbuf, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, nullsref, NULL));
/*you may freely cast between pointers (and ints, as this is explicit) (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/
else if (
//pointers
((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e.cast->type == ev_pointer || e.cast->type == ev_string || e.cast->type == ev_integer))
//ents/classs
|| (newtype->type == ev_entity && e.cast->type == ev_entity)
//functions can be explicitly cast from one to another
|| (newtype->type == ev_function && e.cast->type == ev_function)
//variants are fine too
|| (newtype->type == ev_variant || e.cast->type == ev_variant)
// || (newtype->type == ev_accessor && newtype->parentclass->type == e.cast->type)
// || (e->type->type == ev_accessor && e.cast->parentclass->type == newtype->type)
|| !typecmp(e.cast, newtype)
)
{
e.sym->referenced = true;
//direct cast
return QCC_PR_BuildRef(retbuf, REF_GLOBAL, e, nullsref, newtype, true);
}
else
{
char typea[256];
char typeb[256];
TypeName(e.cast, typea, sizeof(typea));
TypeName(newtype, typeb, sizeof(typeb));
QCC_PR_ParseError(0, "Cannot cast from %s to %s\n", typea, typeb);
}
} }
return QCC_DefToRef(retbuf, e); return QCC_DefToRef(retbuf, e);
} }
@ -11468,10 +11506,10 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
{ {
//arrays go recursive //arrays go recursive
QCC_PR_Expect("{"); QCC_PR_Expect("{");
if (!QCC_PR_CheckToken("}"))
{
for (i = 0; i < arraysize; i++) for (i = 0; i < arraysize; i++)
{ {
if (QCC_PR_CheckToken("}"))
break;
QCC_PR_ParseInitializerType(0, basedef, def); QCC_PR_ParseInitializerType(0, basedef, def);
def.ofs += def.cast->size; def.ofs += def.cast->size;
if (!QCC_PR_CheckToken(",")) if (!QCC_PR_CheckToken(","))
@ -11479,6 +11517,9 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
QCC_PR_Expect("}"); QCC_PR_Expect("}");
break; break;
} }
if (QCC_PR_CheckToken("}"))
break;
}
} }
} }
else else
@ -11649,35 +11690,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
else else
{ {
tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
if (typecmp(type, tmp.cast)) tmp = QCC_EvaluateCast(tmp, type, true);
{
/*you can cast from const 0 to anything*/
if (tmp.cast->size == type->size && QCC_SRef_IsNull(tmp))
{
}
/*universal pointers can assign without casts*/
else if (type->type == ev_pointer && tmp.cast->type == ev_pointer && (type->aux_type->type == ev_void || tmp.cast->aux_type->type == ev_void || type->aux_type->type == ev_variant || tmp.cast->aux_type->type == ev_variant))
{
}
/*cast from int->float will convert*/
else if (type->type == ev_float && tmp.cast->type == ev_integer)
tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], tmp, nullsref, NULL);
/*cast from float->int will convert*/
else if (type->type == ev_integer && tmp.cast->type == ev_float)
tmp = QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], tmp, nullsref, NULL);
else if ( (type->type == ev_accessor && type->parentclass->type == tmp.cast->type)
|| (tmp.cast->type == ev_accessor && tmp.cast->parentclass->type == type->type))
{
}
else
{
char gottype[256];
char needtype[256];
TypeName(tmp.cast, gottype, sizeof(gottype));
TypeName(type, needtype, sizeof(needtype));
QCC_PR_ParseErrorPrintSRef (ERR_BADIMMEDIATETYPE, def, "wrong initializer type for %s. got %s, needed %s", QCC_GetSRefName(def), gottype, needtype);
}
}
} }
if (!pr_scope || basedef->constant || basedef->isstatic) if (!pr_scope || basedef->constant || basedef->isstatic)
@ -11686,7 +11699,14 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
if (!tmp.sym->constant) if (!tmp.sym->constant)
{ {
QCC_PR_ParseWarning(ERR_BADIMMEDIATETYPE, "initializer is not constant"); QCC_PR_ParseWarning(ERR_BADIMMEDIATETYPE, "initializer is not constant");
QCC_PR_ParsePrintSRef(ERR_BADIMMEDIATETYPE, def); QCC_PR_ParsePrintSRef(ERR_BADIMMEDIATETYPE, tmp);
}
if (!tmp.sym->initialized)
{
//FIXME: we NEED to support relocs somehow
QCC_PR_ParseWarning(WARN_UNINITIALIZED, "initializer is not initialised, %s will be treated as 0", QCC_GetSRefName(tmp));
QCC_PR_ParsePrintSRef(WARN_UNINITIALIZED, tmp);
} }
if (basedef->initialized && basedef->initialized != 3) if (basedef->initialized && basedef->initialized != 3)
@ -12237,7 +12257,11 @@ void QCC_PR_ParseDefs (char *classname)
break; break;
} }
else if (depth == 1 && QCC_PR_CheckToken(",")) else if (depth == 1 && QCC_PR_CheckToken(","))
{
if (QCC_PR_CheckToken("}"))
break;
arraysize++; arraysize++;
}
else if (QCC_PR_CheckToken("{") || QCC_PR_CheckToken("[")) else if (QCC_PR_CheckToken("{") || QCC_PR_CheckToken("["))
depth++; depth++;
else if (QCC_PR_CheckToken("}") || QCC_PR_CheckToken("]")) else if (QCC_PR_CheckToken("}") || QCC_PR_CheckToken("]"))
@ -12444,7 +12468,10 @@ void QCC_PR_ParseDefs (char *classname)
else else
{ {
QCC_PR_CheckToken("#"); QCC_PR_CheckToken("#");
do
{
QCC_PR_Lex(); QCC_PR_Lex();
} while (*pr_token && strcmp(pr_token, ",") && strcmp(pr_token, ";"));
} }
} }
QCC_FreeDef(def); QCC_FreeDef(def);

View file

@ -3824,6 +3824,10 @@ int typecmp_lax(QCC_type_t *a, QCC_type_t *b)
if (typecmp_lax(a->aux_type, b->aux_type)) if (typecmp_lax(a->aux_type, b->aux_type))
return 1; return 1;
//variants and args don't make sense, and are considered equivelent(ish).
if (a->type == ev_variant || b->type == ev_variant)
return 0;
//optional arg types must match, even if they're not specified in one. //optional arg types must match, even if they're not specified in one.
for (t = 0; t < minargs; t++) for (t = 0; t < minargs; t++)
{ {
@ -4308,6 +4312,8 @@ extern char *basictypenames[];
extern QCC_type_t **basictypes[]; extern QCC_type_t **basictypes[];
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags); QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags);
void QCC_PR_ParseInitializerDef(QCC_def_t *def);
pbool type_inlinefunction; pbool type_inlinefunction;
/*newtype=true: creates a new type always /*newtype=true: creates a new type always
silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL
@ -4576,6 +4582,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_def_t *d; QCC_def_t *d;
QCC_type_t *pc; QCC_type_t *pc;
pbool found = false; pbool found = false;
int assumevirtual = 0; //0=erk, 1=yes, -1=no
parmname = QCC_PR_ParseName(); parmname = QCC_PR_ParseName();
classname = qccHunkAlloc(strlen(parmname)+1); classname = qccHunkAlloc(strlen(parmname)+1);
@ -4643,6 +4650,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
pbool isnonvirt = false; pbool isnonvirt = false;
pbool isstatic = false; pbool isstatic = false;
pbool isignored = false; pbool isignored = false;
pbool ispublic = false;
pbool isprivate = false;
pbool isprotected = false;
while(1) while(1)
{ {
if (QCC_PR_CheckKeyword(1, "nonvirtual")) if (QCC_PR_CheckKeyword(1, "nonvirtual"))
@ -4655,9 +4665,23 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
isignored = true; isignored = true;
else if (QCC_PR_CheckKeyword(1, "strip")) else if (QCC_PR_CheckKeyword(1, "strip"))
isignored = true; isignored = true;
else if (QCC_PR_CheckKeyword(1, "public"))
ispublic = true;
else if (QCC_PR_CheckKeyword(1, "private"))
isprivate = true;
else if (QCC_PR_CheckKeyword(1, "protected"))
isprotected = true;
else else
break; break;
} }
if (QCC_PR_CheckToken(":"))
{
if (isvirt && !isnonvirt)
assumevirtual = 1;
else if (isnonvirt && !isvirt)
assumevirtual = -1;
continue;
}
newparm = QCC_PR_ParseType(false, false); newparm = QCC_PR_ParseType(false, false);
if (!newparm) if (!newparm)
@ -4693,8 +4717,12 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
} }
else if (!isvirt && !isnonvirt && !isstatic) else if (!isvirt && !isnonvirt && !isstatic)
{ {
QCC_PR_ParseWarning(WARN_MISSINGMEMBERQUALIFIER, "%s::%s was not qualified. Assuming non-virtual.", classname, parmname); if (assumevirtual == 1)
isvirt = true;
else if (assumevirtual == -1)
isnonvirt = true; isnonvirt = true;
else
QCC_PR_ParseWarning(WARN_MISSINGMEMBERQUALIFIER, "%s::%s was not qualified. Assuming non-virtual.", classname, parmname);
} }
if (isvirt+isnonvirt+isstatic != 1) if (isvirt+isnonvirt+isstatic != 1)
QCC_PR_ParseError(ERR_INTERNAL, "Multiple conflicting qualifiers on %s::%s.", classname, pr_token); QCC_PR_ParseError(ERR_INTERNAL, "Multiple conflicting qualifiers on %s::%s.", classname, pr_token);
@ -4718,7 +4746,6 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (havebody) if (havebody)
{ {
QCC_def_t *def; QCC_def_t *def;
QCC_function_t *f;
if (pr_scope) if (pr_scope)
QCC_Error(ERR_INTERNAL, "Nested function declaration"); QCC_Error(ERR_INTERNAL, "Nested function declaration");
@ -4748,6 +4775,15 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{ {
if (autoprototype || isignored) if (autoprototype || isignored)
{ {
if (QCC_PR_CheckToken("["))
{
while (!QCC_PR_CheckToken("]"))
{
if (pr_token_type == tt_eof)
break;
QCC_PR_Lex();
}
}
QCC_PR_Expect("{"); QCC_PR_Expect("{");
{ {
@ -4769,12 +4805,16 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
else else
{ {
pr_classtype = newt; pr_classtype = newt;
QCC_PR_ParseInitializerDef(def);
QCC_FreeDef(def);
pr_classtype = NULL;
/*
f = QCC_PR_ParseImmediateStatements (def, newparm); f = QCC_PR_ParseImmediateStatements (def, newparm);
pr_classtype = NULL; pr_classtype = NULL;
pr_scope = NULL; pr_scope = NULL;
def->symboldata[def->ofs].function = f - functions; def->symboldata[def->ofs].function = f - functions;
f->def = def; f->def = def;
def->initialized = 1; def->initialized = 1;*/
} }
} }
} }

View file

@ -71,6 +71,7 @@ void GUI_RevealOptions(void);
#define SCI_GETLINE 2153 #define SCI_GETLINE 2153
#define SCI_LINEFROMPOSITION 2166 #define SCI_LINEFROMPOSITION 2166
#define SCI_POSITIONFROMLINE 2167 #define SCI_POSITIONFROMLINE 2167
#define SCI_REPLACESEL 2170
#define SCI_SETTEXT 2181 #define SCI_SETTEXT 2181
#define SCI_GETTEXT 2182 #define SCI_GETTEXT 2182
#define SCI_CALLTIPSHOW 2200 #define SCI_CALLTIPSHOW 2200
@ -757,6 +758,8 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
EditFile(line+10, -1, false); EditFile(line+10, -1, false);
else if (!strncmp(line, "prototyping ", 12)) else if (!strncmp(line, "prototyping ", 12))
EditFile(line+12, -1, false); EditFile(line+12, -1, false);
else if (!strncmp(line, "Couldn't open file ", 19))
EditFile(line+19, -1, false);
Edit_SetSel(hWnd, selrange.cpMin, selrange.cpMin); //deselect it. Edit_SetSel(hWnd, selrange.cpMin, selrange.cpMin); //deselect it.
} }
} }
@ -1709,7 +1712,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
if (pos == linestart) if (pos == linestart)
{ {
scin_get_line_indent(editor->editpane, lineidx, linebuf, sizeof(linebuf)); scin_get_line_indent(editor->editpane, lineidx, linebuf, sizeof(linebuf));
SendMessage(editor->editpane, EM_REPLACESEL, 0, (LPARAM)linebuf); SendMessage(editor->editpane, SCI_REPLACESEL, 0, (LPARAM)linebuf);
} }
} }
else if (0)//(!SendMessage(editor->editpane, SCI_AUTOCACTIVE, 0, 0)) else if (0)//(!SendMessage(editor->editpane, SCI_AUTOCACTIVE, 0, 0))
@ -1912,8 +1915,8 @@ void EditFile(char *name, int line, pbool setcontrol)
if (QCC_RawFileSize(name) == -1) if (QCC_RawFileSize(name) == -1)
{ {
QC_snprintfz(title, sizeof(title), "File not found.\n%s", name); QC_snprintfz(title, sizeof(title), "File not found:\n%s\nCreate it?", name);
MessageBox(NULL, title, "Error", 0); if (MessageBox(NULL, title, "Error", MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2) != IDYES)
return; return;
} }

View file

@ -298,6 +298,7 @@ static void ASMCALL CStateOp (pubprogfuncs_t *prinst, float first, float last, f
e->v->nextthink = pr_global_struct->time+0.1; e->v->nextthink = pr_global_struct->time+0.1;
e->v->think = currentfunc; e->v->think = currentfunc;
if (pr_global_ptrs->cycle_wrapped)
pr_global_struct->cycle_wrapped = false; pr_global_struct->cycle_wrapped = false;
if (first > last) if (first > last)
@ -319,6 +320,7 @@ static void ASMCALL CStateOp (pubprogfuncs_t *prinst, float first, float last, f
frame += step; frame += step;
if (frame < min || frame > max) if (frame < min || frame > max)
{ //became out of range, must have wrapped { //became out of range, must have wrapped
if (pr_global_ptrs->cycle_wrapped)
pr_global_struct->cycle_wrapped = true; pr_global_struct->cycle_wrapped = true;
frame = first; frame = first;
} }
@ -8034,6 +8036,23 @@ static void QCBUILTIN PF_te_beam(pubprogfuncs_t *prinst, struct globalvars_s *pr
SV_beam_tempentity(G_EDICTNUM(prinst, OFS_PARM0), G_VECTOR(OFS_PARM1), G_VECTOR(OFS_PARM2), TEQW_BEAM); SV_beam_tempentity(G_EDICTNUM(prinst, OFS_PARM0), G_VECTOR(OFS_PARM1), G_VECTOR(OFS_PARM2), TEQW_BEAM);
} }
static void QCBUILTIN PF_te_muzzleflash(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
edict_t *e = G_EDICT(prinst, OFS_PARM0);
//this is for lamers with old (or unsupported) clients
if (progstype == PROG_QW)
{
MSG_WriteByte (&sv.multicast, svc_muzzleflash);
MSG_WriteEntity (&sv.multicast, NUM_FOR_EDICT(prinst, e));
SV_MulticastProtExt (e->v->origin, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0);
}
else
{ //consistent with nq, this'll be cleaned up elsewhere.
e->v->effects = (int)e->v->effects | EF_MUZZLEFLASH;
}
}
//DP_TE_SPARK //DP_TE_SPARK
static void QCBUILTIN PF_te_spark(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_te_spark(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -9443,7 +9462,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"fgets", PF_fgets, 0, 0, 0, 112, "string(filestream fhandle)"}, // (FRIK_FILE) {"fgets", PF_fgets, 0, 0, 0, 112, "string(filestream fhandle)"}, // (FRIK_FILE)
{"fputs", PF_fputs, 0, 0, 0, 113, "void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)"}, // (FRIK_FILE) {"fputs", PF_fputs, 0, 0, 0, 113, "void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)"}, // (FRIK_FILE)
{"strlen", PF_strlen, 0, 0, 0, 114, "float(string s)"}, // (FRIK_FILE) {"strlen", PF_strlen, 0, 0, 0, 114, "float(string s)"}, // (FRIK_FILE)
{"strcat", PF_strcat, 0, 0, 0, 115, "string(string s1, optional string s2, ...)"}, // (FRIK_FILE) {"strcat", PF_strcat, 0, 0, 0, 115, "string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, string s8)"}, // (FRIK_FILE)
{"substring", PF_substring, 0, 0, 0, 116, "string(string s, float start, float length)"}, // (FRIK_FILE) {"substring", PF_substring, 0, 0, 0, 116, "string(string s, float start, float length)"}, // (FRIK_FILE)
{"stov", PF_stov, 0, 0, 0, 117, "vector(string s)"}, // (FRIK_FILE) {"stov", PF_stov, 0, 0, 0, 117, "vector(string s)"}, // (FRIK_FILE)
#ifdef QCGC #ifdef QCGC
@ -9528,6 +9547,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"skinforname", PF_skinforname, 0, 0, 0, 237, "float(float mdlindex, string skinname)"}, // #237 {"skinforname", PF_skinforname, 0, 0, 0, 237, "float(float mdlindex, string skinname)"}, // #237
{"shaderforname", PF_Fixme, 0, 0, 0, 238, D("float(string shadername, optional string defaultshader, ...)", "Caches the named shader and returns a handle to it.\nIf the shader could not be loaded from disk (missing file or ruleset_allow_shaders 0), it will be created from the 'defaultshader' string if specified, or a 'skin shader' default will be used.\ndefaultshader if not empty should include the outer {} that you would ordinarily find in a shader.")}, {"shaderforname", PF_Fixme, 0, 0, 0, 238, D("float(string shadername, optional string defaultshader, ...)", "Caches the named shader and returns a handle to it.\nIf the shader could not be loaded from disk (missing file or ruleset_allow_shaders 0), it will be created from the 'defaultshader' string if specified, or a 'skin shader' default will be used.\ndefaultshader if not empty should include the outer {} that you would ordinarily find in a shader.")},
{"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239, "void(vector org, optional float count)"}, {"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239, "void(vector org, optional float count)"},
{"te_muzzleflash", PF_te_muzzleflash, 0, 0, 0, 0, "void(entity ent)"},
{"checkpvs", PF_checkpvs, 0, 0, 0, 240, "float(vector viewpos, entity entity)"}, {"checkpvs", PF_checkpvs, 0, 0, 0, 240, "float(vector viewpos, entity entity)"},
{"matchclientname", PF_matchclient, 0, 0, 0, 241, "entity(string match, optional float matchnum)"}, {"matchclientname", PF_matchclient, 0, 0, 0, 241, "entity(string match, optional float matchnum)"},
@ -11101,11 +11121,12 @@ void PR_DumpPlatform_f(void)
{"TEREDIT_TEX_UNIFY", "const float", CS, NULL, ter_tex_concentrate}, {"TEREDIT_TEX_UNIFY", "const float", CS, NULL, ter_tex_concentrate},
{"TEREDIT_TEX_NOISE", "const float", CS, NULL, ter_tex_noise}, {"TEREDIT_TEX_NOISE", "const float", CS, NULL, ter_tex_noise},
{"TEREDIT_TEX_BLUR", "const float", CS, NULL, ter_tex_blur}, {"TEREDIT_TEX_BLUR", "const float", CS, NULL, ter_tex_blur},
{"TEREDIT_TEX_REPLACE", "const float", CS, NULL, ter_tex_replace},
{"TEREDIT_TEX_SETMASK", "const float", CS, NULL, ter_tex_mask},
{"TEREDIT_WATER_SET", "const float", CS, NULL, ter_water_set}, {"TEREDIT_WATER_SET", "const float", CS, NULL, ter_water_set},
{"TEREDIT_MESH_ADD", "const float", CS, NULL, ter_mesh_add}, {"TEREDIT_MESH_ADD", "const float", CS, NULL, ter_mesh_add},
{"TEREDIT_MESH_KILL", "const float", CS, NULL, ter_mesh_kill}, {"TEREDIT_MESH_KILL", "const float", CS, NULL, ter_mesh_kill},
{"TEREDIT_TINT", "const float", CS, NULL, ter_tint}, {"TEREDIT_TINT", "const float", CS, NULL, ter_tint},
{"TEREDIT_TEX_REPLACE", "const float", CS, NULL, ter_tex_replace},
{"TEREDIT_RESET_SECT", "const float", CS, NULL, ter_reset}, {"TEREDIT_RESET_SECT", "const float", CS, NULL, ter_reset},
{"TEREDIT_RELOAD_SECT", "const float", CS, NULL, ter_reloadsect}, {"TEREDIT_RELOAD_SECT", "const float", CS, NULL, ter_reloadsect},

View file

@ -247,6 +247,8 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldfloat(style,"Used by the light util to decide how an entity's light should animate. On an entity with pflags set, this also affects realtime lights.")\ comfieldfloat(style,"Used by the light util to decide how an entity's light should animate. On an entity with pflags set, this also affects realtime lights.")\
comfieldfloat(pflags,"Realtime lighting flags")\ comfieldfloat(pflags,"Realtime lighting flags")\
comfieldfloat(clientcolors,NULL)\ comfieldfloat(clientcolors,NULL)\
/*comfieldfloat(baseframe,"Specifies the current frame(group) to use for the lower (numerically) bones of a skeletal model. The basebone field specifies the bone where the regular frame field takes over.")*/ /*FTESS_QC_BASEFRAME*/\
/*comfieldfloat(basebone,"Specifies the bone at which the baseframe* fields stop being effective.")*/ /*FTE_SSQC_BASEFRAME*/\
comfieldfloat(dimension_see,"This is the dimension mask (bitfield) that the client is allowed to see. Entities and events not in this dimension mask will be invisible.")/*EXT_DIMENSION_VISIBLE*/\ comfieldfloat(dimension_see,"This is the dimension mask (bitfield) that the client is allowed to see. Entities and events not in this dimension mask will be invisible.")/*EXT_DIMENSION_VISIBLE*/\
comfieldfloat(dimension_seen,"This is the dimension mask (bitfield) that the client is visible within. Clients that cannot see this dimension mask will not see this entity.")/*EXT_DIMENSION_VISIBLE*/\ comfieldfloat(dimension_seen,"This is the dimension mask (bitfield) that the client is visible within. Clients that cannot see this dimension mask will not see this entity.")/*EXT_DIMENSION_VISIBLE*/\
comfieldfloat(dimension_ghost,"If this entity is visible only within these dimensions, it will become transparent, as if a ghost.")/*EXT_DIMENSION_GHOST*/\ comfieldfloat(dimension_ghost,"If this entity is visible only within these dimensions, it will become transparent, as if a ghost.")/*EXT_DIMENSION_GHOST*/\

View file

@ -76,22 +76,23 @@ extern cvar_t password;
#endif #endif
cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator
cvar_t allow_download = CVAR("allow_download", "1"); cvar_t allow_download = CVARD("allow_download", "1", "If 1, permits downloading. Set to 0 to unconditionally block *ALL* downloads.");
cvar_t allow_download_skins = CVAR("allow_download_skins", "1"); cvar_t allow_download_skins = CVARD("allow_download_skins", "1", "0 blocks downloading of any file in the skins/ directory");
cvar_t allow_download_models = CVAR("allow_download_models", "1"); cvar_t allow_download_models = CVARD("allow_download_models", "1", "0 blocks downloading of any file in the progs/ or models/ directory");
cvar_t allow_download_sounds = CVAR("allow_download_sounds", "1"); cvar_t allow_download_sounds = CVARD("allow_download_sounds", "1", "0 blocks downloading of any file in the sound/ directory");
cvar_t allow_download_demos = CVAR("allow_download_demos", "1"); cvar_t allow_download_demos = CVARD("allow_download_demos", "1", "0 blocks downloading of any file in the demos/ directory");
cvar_t allow_download_maps = CVAR("allow_download_maps", "1"); cvar_t allow_download_maps = CVARD("allow_download_maps", "1", "0 blocks downloading of any file in the maps/ directory");
cvar_t allow_download_anymap = CVAR("allow_download_pakmaps", "0"); cvar_t allow_download_logs = CVARD("allow_download_logs", "0", "1 permits downloading files with the extension .log\n"CON_ERROR"THIS IS DANGEROUS AS IT POTENTIALLY ALLOWS PEOPLE TO SEE PASSWORDS OR OTHER PRIVATE INFORMATION.\nNote that it can be switch on/off via rcon.");
cvar_t allow_download_pakcontents = CVARD("allow_download_pakcontents", "1", "controls whether clients connected to this server are allowed to download files from within packages. Does NOT implicitly allow downloading bsps, set allow_download_pakmaps to enable that."); cvar_t allow_download_anymap = CVARD("allow_download_pakmaps", "0", "If 1, permits downloading of maps from within packages. This is normally disabled in order to prevent copyrighted content from being downloaded.");
cvar_t allow_download_root = CVARD("allow_download_root", "0", "If set, enables downloading from the root of the gamedir (not the basedir). This setting is dangerous as it can allow downloading configs."); cvar_t allow_download_pakcontents = CVARD("allow_download_pakcontents", "1", "controls whether clients connected to this server are allowed to download files from within packages.\nDoes NOT implicitly allow downloading bsps, set allow_download_pakmaps to enable that.\nWhile treating each file contained within packages is often undesirable, this is often needed for compatibility with legacy clients (despite it potentially allowing copyright violations).");
cvar_t allow_download_textures = CVAR("allow_download_textures", "1"); cvar_t allow_download_root = CVARD("allow_download_root", "0", "If set, enables downloading from the root of the gamedir (not the basedir). This setting has a lower priority than extension-based checks.");
cvar_t allow_download_packages = CVAR("allow_download_packages", "1"); cvar_t allow_download_textures = CVARD("allow_download_textures", "1", "0 blocks downloading of any file in the textures/ directory");
cvar_t allow_download_packages = CVARD("allow_download_packages", "1", "if 1, permits downloading files (from root directory or elsewhere) with known package extensions (eg: pak+pk3). Packages with a name starting 'pak' are covered by allow_download_copyrighted as well. This does not prevent ");
cvar_t allow_download_refpackages = CVARD("allow_download_refpackages", "1", "If set to 1, packages that contain files needed during spawn functions will be become 'referenced' and automatically downloaded to clients.\nThis cvar should probably not be set if you have large packages that provide replacement pickup models on public servers.\nThe path command will show a '(ref)' tag next to packages which clients will automatically attempt to download."); cvar_t allow_download_refpackages = CVARD("allow_download_refpackages", "1", "If set to 1, packages that contain files needed during spawn functions will be become 'referenced' and automatically downloaded to clients.\nThis cvar should probably not be set if you have large packages that provide replacement pickup models on public servers.\nThe path command will show a '(ref)' tag next to packages which clients will automatically attempt to download.");
cvar_t allow_download_wads = CVAR("allow_download_wads", "1"); cvar_t allow_download_wads = CVARD("allow_download_wads", "1", "0 blocks downloading of any file in the wads/ directory, or is in the root directory with the extension .wad");
cvar_t allow_download_configs = CVAR("allow_download_configs", "0"); cvar_t allow_download_configs = CVARD("allow_download_configs", "0", "1 allows downloading of config files, either with the extension .cfg or in the subdir configs/.\n"CON_ERROR"THIS IS DANGEROUS AS IT CAN ALLOW PEOPLE TO READ YOUR RCON PASSWORD.");
cvar_t allow_download_copyrighted = CVAR("allow_download_copyrighted", "0"); cvar_t allow_download_copyrighted = CVARD("allow_download_copyrighted", "0", "0 blocks download of packages that are considered copyrighted. Specifically, this means packages with a leading 'pak' prefix on the filename.\nIf you take your copyrights seriously, you should also set allow_download_pakmaps 0 and allow_download_pakcontents 0.");
cvar_t allow_download_other = CVAR("allow_download_other", "0"); cvar_t allow_download_other = CVARD("allow_download_other", "0", "0 blocks downloading of any file that was not covered by any of the directory download blocks.");
cvar_t sv_serverip = CVARD("sv_serverip", "", "Set this cvar to the server's public ip address if the server is behind a firewall and cannot detect its own public address. Providing a port is required if the firewall/nat remaps it, but is otherwise optional."); cvar_t sv_serverip = CVARD("sv_serverip", "", "Set this cvar to the server's public ip address if the server is behind a firewall and cannot detect its own public address. Providing a port is required if the firewall/nat remaps it, but is otherwise optional.");
cvar_t sv_public = CVAR("sv_public", "0"); cvar_t sv_public = CVAR("sv_public", "0");

View file

@ -2657,6 +2657,7 @@ qboolean SV_AllowDownload (const char *name)
extern cvar_t allow_download_packages; extern cvar_t allow_download_packages;
extern cvar_t allow_download_wads; extern cvar_t allow_download_wads;
extern cvar_t allow_download_root; extern cvar_t allow_download_root;
extern cvar_t allow_download_logs;
extern cvar_t allow_download_configs; extern cvar_t allow_download_configs;
extern cvar_t allow_download_copyrighted; extern cvar_t allow_download_copyrighted;
extern cvar_t allow_download_other; extern cvar_t allow_download_other;
@ -2689,7 +2690,9 @@ qboolean SV_AllowDownload (const char *name)
//block attempts to download logs //block attempts to download logs
if (!Q_strcasecmp("log", ext)) if (!Q_strcasecmp("log", ext))
return false; return !!allow_download_logs.value;
if (strncmp(name, "logs/", 5) == 0)
return !!allow_download_logs.value;
if (!strncmp(name, "package/", 8)) if (!strncmp(name, "package/", 8))
{ {
@ -2727,10 +2730,13 @@ qboolean SV_AllowDownload (const char *name)
if (strncmp(name, "textures/", 9) == 0) if (strncmp(name, "textures/", 9) == 0)
return !!allow_download_textures.value; return !!allow_download_textures.value;
if (strncmp(name, "config/", 9) == 0)
return !!allow_download_configs.value;
//wads //wads
if (strncmp(name, "wads/", 5) == 0) if (strncmp(name, "wads/", 5) == 0)
return !!allow_download_wads.value; return !!allow_download_wads.value;
if (!strcmp("wad", ext)) if (!strchr(name, '/') && !strcmp("wad", ext))
return !!allow_download_wads.value; return !!allow_download_wads.value;
//pak/pk3s. //pak/pk3s.
@ -2739,7 +2745,7 @@ qboolean SV_AllowDownload (const char *name)
if (strnicmp(name, "pak", 3)) //don't give out core pak/pk3 files. This matches q3 logic. if (strnicmp(name, "pak", 3)) //don't give out core pak/pk3 files. This matches q3 logic.
return !!allow_download_packages.value; return !!allow_download_packages.value;
else else
return !!allow_download_copyrighted.value; return !!allow_download_packages.value && !!allow_download_copyrighted.value;
} }
if (!strcmp("cfg", ext)) if (!strcmp("cfg", ext))
@ -2754,7 +2760,7 @@ qboolean SV_AllowDownload (const char *name)
} }
//any other subdirs are allowed //any other subdirs are allowed
return !!allow_download_other.value;; return !!allow_download_other.value;
} }
static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementname, qboolean redirectpaks) static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementname, qboolean redirectpaks)
@ -3360,6 +3366,12 @@ void SV_Say (qboolean team)
if (PR_QCChat(p, team)) //true if handled. if (PR_QCChat(p, team)) //true if handled.
return; return;
if (strstr(p, "password"))
{
Z_Free(host_client->centerprintstring);
host_client->centerprintstring = Z_StrDup("big brother is watching you");
}
Q_strcat(text, p); Q_strcat(text, p);
//filter out '\n' and '\r' //filter out '\n' and '\r'

View file

@ -225,7 +225,7 @@ static areanode_t *World_CreateAreaNode (world_t *w, int depth, vec3_t mins, vec
ClearLink (&anode->edicts); ClearLink (&anode->edicts);
if (depth == AREA_DEPTH) if (depth == w->areanodedepth)
{ {
anode->axis = -1; anode->axis = -1;
anode->children[0] = anode->children[1] = NULL; anode->children[0] = anode->children[1] = NULL;
@ -260,23 +260,37 @@ SV_ClearWorld
*/ */
void World_ClearWorld (world_t *w) void World_ClearWorld (world_t *w)
{ {
int maxdepth;
vec3_t mins, maxs;
if (w->worldmodel)
{
VectorCopy(w->worldmodel->mins, mins);
VectorCopy(w->worldmodel->maxs, maxs);
}
else
{
VectorSet(mins, -4096, -4096, -4096);
VectorSet(maxs, 4096, 4096, 4096);
}
World_InitBoxHull (); World_InitBoxHull ();
memset (&w->portallist, 0, sizeof(w->portallist)); memset (&w->portallist, 0, sizeof(w->portallist));
ClearLink (&w->portallist.edicts); ClearLink (&w->portallist.edicts);
w->portallist.axis = -1; w->portallist.axis = -1;
memset (w->areanodes, 0, sizeof(w->areanodes)); maxdepth = 4;
w->numareanodes = 0;
if (!w->worldmodel) if (!w->areanodes || w->areanodedepth != maxdepth)
{ {
vec3_t mins, maxs; Z_Free(w->areanodes);
VectorSet(mins, -4096, -4096, -4096); w->areanodedepth = maxdepth;
VectorSet(maxs, 4096, 4096, 4096); w->areanodes = Z_Malloc(sizeof(*w->areanodes) * pow(2, w->areanodedepth+1));
World_CreateAreaNode (w, 0, mins, maxs);
} }
else else
World_CreateAreaNode (w, 0, w->worldmodel->mins, w->worldmodel->maxs); memset (w->areanodes, 0, sizeof(w->areanodes));
w->numareanodes = 0;
World_CreateAreaNode (w, 0, mins, maxs);
} }

View file

@ -223,8 +223,51 @@ char *TP_ItemName(unsigned int itbit)
return "Dunno"; return "Dunno";
} }
void Replace_In_String(char *string, size_t strsize, char leadchar, int patterns, ...) void Replace_In_String(char *src, size_t strsize, char leadchar, int patterns, ...)
{ {
char orig[1024];
char *out, *outstop;
va_list ap;
int i;
strlcpy(orig, src, sizeof(orig));
out = src;
outstop = out + strsize-1;
src = orig;
while(*src)
{
if (out == outstop)
break;
if (*src != leadchar)
*out++ = *src++;
else if (*++src == leadchar)
*out++ = leadchar;
else
{
va_start(ap, patterns);
for (i = 0; i < patterns; i++)
{
const char *arg = va_arg(ap, const char *);
const char *val = va_arg(ap, const char *);
size_t alen = strlen(arg);
if (!strncmp(src, arg, strlen(arg)))
{
strlcpy(out, val, (outstop-out)+1);
out += strlen(out);
src += alen;
break;
}
}
if (i == patterns)
{
strlcpy(out, "unknown", (outstop-out)+1);
out += strlen(out);
}
va_end(ap);
}
}
*out = 0;
} }
int SCR_GetClockStringWidth(const char *s, qbool big, float scale) int SCR_GetClockStringWidth(const char *s, qbool big, float scale)
@ -356,6 +399,13 @@ void SCR_DrawSmallClock(int x, int y, int style, int blink, float scale, const c
} }
} }
#include "builtin_huds.h"
void EZHud_UseNquake_f(void)
{
const char *hudstr = builtin_hud_nquake;
pCmd_AddText(hudstr, true);
}
struct struct
{ {
xcommand_t cmd; xcommand_t cmd;
@ -577,6 +627,7 @@ qintptr_t Plug_Init(qintptr_t *args)
Plug_Export("Tick", EZHud_Tick) && Plug_Export("Tick", EZHud_Tick) &&
Plug_Export("ExecuteCommand", EZHud_ExecuteCommand)) Plug_Export("ExecuteCommand", EZHud_ExecuteCommand))
{ {
Cmd_AddCommand("ezhud_nquake", EZHud_UseNquake_f);
HUD_Init(); HUD_Init();
HUD_Editor_Init(); HUD_Editor_Init();
return 1; return 1;

View file

@ -393,6 +393,10 @@ void SCR_HUD_DrawFPS(hud_t *hud)
if (HUD_PrepareDraw(hud, strlen(st)*8, 8, &x, &y)) if (HUD_PrepareDraw(hud, strlen(st)*8, 8, &x, &y))
{ {
vmnetinfo_t *netinfo = GetNetworkInfo();
if (netinfo->capturing == 2) //don't show fps if its locked to something anyway.
return;
if ((hud_fps_style->value) == 1) if ((hud_fps_style->value) == 1)
Draw_Alt_String(x, y, st); Draw_Alt_String(x, y, st);
else if ((hud_fps_style->value) == 2) { else if ((hud_fps_style->value) == 2) {
@ -674,11 +678,11 @@ static void SCR_HUD_DrawPing(hud_t *hud)
// period = max(hud_ping_period->value, 0); // period = max(hud_ping_period->value, 0);
ping_avg = (int)(netinfo->ping.avg*1000 + 0.5); ping_avg = (int)(netinfo->ping.s_avg*1000 + 0.5);
ping_min = (int)(netinfo->ping.mn*1000 + 0.5); ping_min = (int)(netinfo->ping.s_mn*1000 + 0.5);
ping_max = (int)(netinfo->ping.mx*1000 + 0.5); ping_max = (int)(netinfo->ping.s_mx*1000 + 0.5);
ping_dev = netinfo->ping.stddev; ping_dev = netinfo->ping.ms_stddev;
pl = netinfo->ping.loss*100; pl = netinfo->loss.dropped*100;
clamp(ping_avg, 0, 999); clamp(ping_avg, 0, 999);
clamp(ping_min, 0, 999); clamp(ping_min, 0, 999);
@ -937,28 +941,28 @@ static void SCR_NetStats(int x, int y, float period, vmnetinfo_t *netinfo)
last_calculated = t; last_calculated = t;
ping_avg = (int)(netinfo->ping.avg + 0.5); ping_avg = (int)(netinfo->ping.s_avg*1000 + 0.5);
ping_min = (int)(netinfo->ping.mn + 0.5); ping_min = (int)(netinfo->ping.s_mn*1000 + 0.5);
ping_max = (int)(netinfo->ping.mx + 0.5); ping_max = (int)(netinfo->ping.s_mx*1000 + 0.5);
ping_dev = netinfo->ping.stddev; ping_dev = netinfo->ping.ms_stddev;
clamp(ping_avg, 0, 999); clamp(ping_avg, 0, 999);
clamp(ping_min, 0, 999); clamp(ping_min, 0, 999);
clamp(ping_max, 0, 999); clamp(ping_max, 0, 999);
clamp(ping_dev, 0, 99.9); clamp(ping_dev, 0, 99.9);
f_avg = -1;//(int)(result.ping_f_avg + 0.5); f_avg = (int)(netinfo->ping.fr_avg+0.5);
f_min = -1;//(int)(result.ping_f_min + 0.5); f_min = netinfo->ping.fr_mn;
f_max = -1;//(int)(result.ping_f_max + 0.5); f_max = netinfo->ping.fr_mx;
clamp(f_avg, 0, 99.9); clamp(f_avg, 0, 99);
clamp(f_min, 0, 99.9); clamp(f_min, 0, 99);
clamp(f_max, 0, 99.9); clamp(f_max, 0, 99);
lost_lost = (int)(netinfo->ping.loss + 0.5); lost_lost = (int)(netinfo->loss.dropped*100 + 0.5);
lost_rate = -1;//(int)(result.lost_rate + 0.5); lost_rate = (int)(netinfo->loss.choked*100 + 0.5);
lost_delta = -1;//(int)(result.lost_delta + 0.5); lost_delta = (int)(netinfo->loss.invalid*100 + 0.5);
lost_total = -1;//(int)(result.lost_lost + result.lost_rate + result.lost_delta + 0.5); lost_total = (int)((netinfo->loss.dropped + netinfo->loss.choked + netinfo->loss.invalid)*100 + 0.5);
clamp(lost_lost, 0, 100); clamp(lost_lost, 0, 100);
clamp(lost_rate, 0, 100); clamp(lost_rate, 0, 100);
@ -966,9 +970,9 @@ static void SCR_NetStats(int x, int y, float period, vmnetinfo_t *netinfo)
clamp(lost_total, 0, 100); clamp(lost_total, 0, 100);
//per packet sizes //per packet sizes
// size_in = (int)(netinfo->clrate.size_in + 0.5); size_in = (int)(netinfo->clrate.in_bps/netinfo->clrate.in_pps + 0.5);
// size_out = (int)(netinfo->size_out + 0.5); size_out = (int)(netinfo->clrate.out_bps/netinfo->clrate.out_pps + 0.5);
// size_all = (int)(netinfo->size_in + result.size_out + 0.5); size_all = (int)(netinfo->clrate.in_bps/netinfo->clrate.in_pps + netinfo->clrate.out_bps/netinfo->clrate.out_pps + 0.5);
//overall rate //overall rate
bandwidth_in = (int)(netinfo->clrate.in_bps + 0.5); bandwidth_in = (int)(netinfo->clrate.in_bps + 0.5);
@ -982,25 +986,25 @@ static void SCR_NetStats(int x, int y, float period, vmnetinfo_t *netinfo)
clamp(bandwidth_out, 0, 99999); clamp(bandwidth_out, 0, 99999);
clamp(bandwidth_all, 0, 99999); clamp(bandwidth_all, 0, 99999);
// with_delta = result.delta; with_delta = !pCvar_GetFloat("cl_nodelta");
} }
Draw_Alt_String(x+36, y, "latency"); Draw_Alt_String(x+36, y, "latency");
y+=12; y+=12;
snprintf (line, sizeof (line), "min %4.1f %3d ms", f_min, ping_min); snprintf (line, sizeof (line), "min %4f %3d ms", f_min, ping_min);
Draw_String(x, y, line); Draw_String(x, y, line);
y+=8; y+=8;
snprintf(line, sizeof (line), "avg %4.1f %3d ms", f_avg, ping_avg); snprintf(line, sizeof (line), "avg %4f %3d ms", f_avg, ping_avg);
Draw_String(x, y, line); Draw_String(x, y, line);
y+=8; y+=8;
snprintf(line, sizeof (line), "max %4.1f %3d ms", f_max, ping_max); snprintf(line, sizeof (line), "max %4f %3d ms", f_max, ping_max);
Draw_String(x, y, line); Draw_String(x, y, line);
y+=8; y+=8;
snprintf(line, sizeof (line), "dev %5.2f ms", ping_dev); snprintf(line, sizeof (line), "dev %f ms", ping_dev);
Draw_String(x, y, line); Draw_String(x, y, line);
y+=12; y+=12;
@ -1060,9 +1064,11 @@ static void SCR_HUD_DrawNetStats(hud_t *hud)
width = 16*8 ; width = 16*8 ;
height = 12 + 8 + 8 + 8 + 8 + 16 + 8 + 8 + 8 + 8 + 16 + 8 + 8 + 8; height = 12 + 8 + 8 + 8 + 8 + 16 + 8 + 8 + 8 + 8 + 16 + 8 + 8 + 8;
if (HUD_PrepareDraw(hud, width, height, &x, &y)) if (!netinfo || netinfo->capturing==2)
HUD_PrepareDraw(hud, 0, 0, &x, &y);
else if (HUD_PrepareDraw(hud, width, height, &x, &y))
{ {
// SCR_NetStats(x, y, hud_net_period->value); SCR_NetStats(x, y, hud_net_period->value, netinfo);
} }
} }
@ -2401,7 +2407,7 @@ static void SCR_HUD_NetProblem (hud_t *hud) {
if(scale == NULL) if(scale == NULL)
scale = HUD_FindVar(hud, "scale"); scale = HUD_FindVar(hud, "scale");
if (netinfo->ping.loss < 1) if (netinfo->loss.dropped < 1)
{ {
if (hud_editor) if (hud_editor)
HUD_PrepareDraw(hud, picwidth, picheight, &x, &y); HUD_PrepareDraw(hud, picwidth, picheight, &x, &y);
@ -2440,7 +2446,12 @@ void SCR_HUD_DrawGroup(hud_t *hud, int width, int height, mpic_t *pic, int pic_s
float picwidth = 64; float picwidth = 64;
float picheight = 64; float picheight = 64;
pDraw_ImageSize((intptr_t)pic, &picwidth, &picheight); if (pic && pDraw_ImageSize((intptr_t)pic, &picwidth, &picheight) <= 0)
{
pic = NULL;
picwidth = 64;
picheight = 64;
}
clamp(width, 1, 99999); clamp(width, 1, 99999);
clamp(height, 1, 99999); clamp(height, 1, 99999);
@ -7862,7 +7873,7 @@ void CommonDraw_Init(void)
HUD_Register("tracking", NULL, "Shows the name of tracked player.", HUD_Register("tracking", NULL, "Shows the name of tracked player.",
HUD_PLUSMINUS, ca_active, 9, SCR_HUD_DrawTracking, HUD_PLUSMINUS, ca_active, 9, SCR_HUD_DrawTracking,
"1", "face", "center", "before", "0", "0", "0", "0 0 0", NULL, "1", "face", "center", "before", "0", "0", "0", "0 0 0", NULL,
"format", "^mTracking:^m %t %n, ^mJUMP^m for next", //"Tracking: team name, JUMP for next", "Tracking:" and "JUMP" are brown. default: "Tracking %t %n, [JUMP] for next" "format", "^mTracking:^m %t %n"/*, ^mJUMP^m for next"*/, //"Tracking: team name, JUMP for next", "Tracking:" and "JUMP" are brown. default: "Tracking %t %n, [JUMP] for next"
"scale", "1", "scale", "1",
NULL); NULL);

View file

@ -87,14 +87,14 @@ BUILTIN(void, Con_SetConsoleString, (const char *conname, const char *attribname
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,message #define ARGNAMES ,message
BUILTIN(void, Sys_Error, (char *message)); //abort the entire engine. BUILTIN(void, Sys_Error, (const char *message)); //abort the entire engine.
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES #define ARGNAMES
BUILTINR(unsigned int, Sys_Milliseconds, (void)); //get the time the engine has been running. BUILTINR(unsigned int, Sys_Milliseconds, (void)); //get the time the engine has been running.
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,buffer #define ARGNAMES ,buffer
BUILTINR(int, Cmd_AddCommand, (char *buffer)); //register a command. BUILTINR(int, Cmd_AddCommand, (const char *buffer)); //register a command.
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,buffer,bufsize #define ARGNAMES ,buffer,bufsize
BUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //retrieve some arguments. BUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //retrieve some arguments.
@ -110,23 +110,23 @@ BUILTIN(void, Cmd_TokenizeString, (char *msg)); //tokenize a string.
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,text,insert #define ARGNAMES ,text,insert
BUILTIN(void, Cmd_AddText, (char *text, qboolean insert)); //add stuff to the console input. BUILTIN(void, Cmd_AddText, (const char *text, qboolean insert)); //add stuff to the console input.
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,name,value #define ARGNAMES ,name,value
BUILTIN(void, Cvar_SetString, (char *name, char *value)); //set a cvar string BUILTIN(void, Cvar_SetString, (const char *name, char *value)); //set a cvar string
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,name,PASSFLOAT(value) #define ARGNAMES ,name,PASSFLOAT(value)
BUILTIN(void, Cvar_SetFloat, (char *name, float value)); //set a cvar float BUILTIN(void, Cvar_SetFloat, (const char *name, float value)); //set a cvar float
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,name,retstring,sizeofretstring #define ARGNAMES ,name,retstring,sizeofretstring
BUILTINR(qboolean, Cvar_GetString, (char *name, char *retstring, int sizeofretstring)); //retrieve a cvar string BUILTINR(qboolean, Cvar_GetString, (const char *name, char *retstring, int sizeofretstring)); //retrieve a cvar string
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,name #define ARGNAMES ,name
BUILTINR(float, Cvar_GetFloat, (char *name)); //get a cvar's value BUILTINR(float, Cvar_GetFloat, (const char *name)); //get a cvar's value
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,name,defaultval,flags,grouphint #define ARGNAMES ,name,defaultval,flags,grouphint
BUILTINR(qhandle_t, Cvar_Register, (char *name, char *defaultval, int flags, char *grouphint)); //register a new cvar BUILTINR(qhandle_t, Cvar_Register, (const char *name, const char *defaultval, int flags, const char *grouphint)); //register a new cvar
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,handle,modificationcount,stringv,floatv #define ARGNAMES ,handle,modificationcount,stringv,floatv
BUILTINR(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. BUILTINR(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged.
@ -148,15 +148,15 @@ BUILTINR(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernu
BUILTIN(void, GetServerInfo, (char *info, int infolen)); BUILTIN(void, GetServerInfo, (char *info, int infolen));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,key,value #define ARGNAMES ,key,value
BUILTIN(void, SetUserInfo, (char *key, char *value)); BUILTIN(void, SetUserInfo, (const char *key, const char *value));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,pos,buffer,bufferlen #define ARGNAMES ,pos,buffer,bufferlen
BUILTIN(void, GetLocationName, (float *pos, char *buffer, int bufferlen)); BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,soundname #define ARGNAMES ,soundname
BUILTIN(void, LocalSound, (char *soundname)); BUILTIN(void, LocalSound, (const char *soundname));
#undef ARGNAMES #undef ARGNAMES
#define ARGNAMES ,plugnum, buffer, bufsize #define ARGNAMES ,plugnum, buffer, bufsize

View file

@ -206,45 +206,53 @@ EBUILTIN(void, Con_SetConsoleFloat, (const char *conname, const char *attribname
EBUILTIN(int, Con_GetConsoleString, (const char *conname, const char *attribname, const char *value, unsigned int valuesize)); EBUILTIN(int, Con_GetConsoleString, (const char *conname, const char *attribname, const char *value, unsigned int valuesize));
EBUILTIN(void, Con_SetConsoleString, (const char *conname, const char *attribname, const char *newvalue)); EBUILTIN(void, Con_SetConsoleString, (const char *conname, const char *attribname, const char *newvalue));
EBUILTIN(void, Sys_Error, (char *message)); //abort the entire engine. EBUILTIN(void, Sys_Error, (const char *message)); //abort the entire engine.
EBUILTIN(unsigned int, Sys_Milliseconds, ()); EBUILTIN(unsigned int, Sys_Milliseconds, ());
EBUILTIN(int, Cmd_AddCommand, (char *buffer)); //abort the entire engine. EBUILTIN(int, Cmd_AddCommand, (const char *buffer)); //abort the entire engine.
EBUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //abort the entire engine. EBUILTIN(void, Cmd_Args, (char *buffer, int bufsize)); //abort the entire engine.
EBUILTIN(void, Cmd_Argv, (int argnum, char *buffer, int bufsize)); //abort the entire engine. EBUILTIN(void, Cmd_Argv, (int argnum, char *buffer, int bufsize)); //abort the entire engine.
EBUILTIN(int, Cmd_Argc, (void)); //abort the entire engine. EBUILTIN(int, Cmd_Argc, (void)); //abort the entire engine.
EBUILTIN(void, Cmd_AddText, (char *text, qboolean insert)); EBUILTIN(void, Cmd_AddText, (const char *text, qboolean insert));
EBUILTIN(void, Cmd_Tokenize, (char *msg)); //abort the entire engine. EBUILTIN(void, Cmd_Tokenize, (const char *msg)); //abort the entire engine.
EBUILTIN(void, Cvar_SetString, (char *name, char *value)); EBUILTIN(void, Cvar_SetString, (const char *name, char *value));
EBUILTIN(void, Cvar_SetFloat, (char *name, float value)); EBUILTIN(void, Cvar_SetFloat, (const char *name, float value));
EBUILTIN(qboolean, Cvar_GetString, (char *name, char *retstring, int sizeofretstring)); EBUILTIN(qboolean, Cvar_GetString, (const char *name, char *retstring, int sizeofretstring));
EBUILTIN(float, Cvar_GetFloat, (char *name)); EBUILTIN(float, Cvar_GetFloat, (const char *name));
EBUILTIN(qhandle_t, Cvar_Register, (char *name, char *defaultval, int flags, char *grouphint)); EBUILTIN(qhandle_t, Cvar_Register, (const char *name, const char *defaultval, int flags, const char *grouphint));
EBUILTIN(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. EBUILTIN(int, Cvar_Update, (qhandle_t handle, int *modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged.
EBUILTIN(void, GetPluginName, (int plugnum, char *buffer, int bufsize)); EBUILTIN(void, GetPluginName, (int plugnum, char *buffer, int bufsize));
EBUILTIN(void, LocalSound, (char *soundname)); EBUILTIN(void, LocalSound, (const char *soundname));
EBUILTIN(int, CL_GetStats, (int pnum, unsigned int *stats, int maxstats)); EBUILTIN(int, CL_GetStats, (int pnum, unsigned int *stats, int maxstats));
EBUILTIN(int, GetPlayerInfo, (int pnum, plugclientinfo_t *info)); EBUILTIN(int, GetPlayerInfo, (int pnum, plugclientinfo_t *info));
EBUILTIN(int, LocalPlayerNumber, (void)); //deprecated EBUILTIN(int, LocalPlayerNumber, (void)); //deprecated
EBUILTIN(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernums, int *spectracks)); EBUILTIN(int, GetLocalPlayerNumbers, (int firstseat, int numseats, int *playernums, int *spectracks));
EBUILTIN(void, GetServerInfo, (char *info, int infolen)); EBUILTIN(void, GetServerInfo, (char *info, int infolen));
EBUILTIN(void, SetUserInfo, (char *key, char *value)); EBUILTIN(void, SetUserInfo, (const char *key, const char *value));
EBUILTIN(void, GetLocationName, (float *pos, char *buffer, int bufferlen)); EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
EBUILTIN(void, GetLocationName, (float *pos, char *buffer, int bufferlen)); EBUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
typedef struct { typedef struct {
int seats; int seats;
struct struct
{ {
float avg; float s_avg;
float mn; float s_mn;
float mx; float s_mx;
float stddev; float ms_stddev; //calculated in milliseconds for more sane numbers
float loss; float fr_avg;
int fr_mn;
int fr_mx;
} ping; } ping;
struct
{ //decimals
float dropped;
float choked;
float invalid;
} loss;
float mlatency; float mlatency;
float mrate; float mrate;
float vlatency; float vlatency;
@ -265,6 +273,7 @@ typedef struct {
float out_pps; float out_pps;
float out_bps; float out_bps;
} svrate; } svrate;
int capturing; //avi capturing
} vmnetinfo_t; } vmnetinfo_t;
EBUILTIN(int, GetNetworkInfo, (vmnetinfo_t *ni, unsigned int sizeofni)); EBUILTIN(int, GetNetworkInfo, (vmnetinfo_t *ni, unsigned int sizeofni));