autotrack is now over-complicated.

demo_jump with no args tells the current time (separate from map time or anything)
implement batching for text+csqcpolys to reduce draw calls.
qclib supports pointer(inc casts) evaluation.
fteqccgui now has a lame variables window thing. probably I'll get harassed about it.
add brush_calcfacepoints builtin for csaddon to use to preview brush edits.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4952 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-07-30 16:26:15 +00:00
parent 450bbcb50f
commit 6adb05d916
21 changed files with 859 additions and 202 deletions

View file

@ -67,7 +67,12 @@ void Cam_AutoTrack_Update(const char *mode)
autotrack_statsrule = NULL;
if (!*mode || !Q_strcasecmp(mode, "auto"))
{
if (cl_hightrack.ival)
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
autotrackmode = TM_STATS;
autotrack_statsrule = Z_StrDup(""); //default
}
else if (cl_hightrack.ival)
autotrackmode = TM_HIGHTRACK;
else
autotrackmode = TM_MODHINTS;
@ -80,6 +85,11 @@ void Cam_AutoTrack_Update(const char *mode)
autotrackmode = TM_MODHINTS;
else if (!Q_strcasecmp(mode, "user") || !Q_strcasecmp(mode, "off"))
autotrackmode = TM_USER;
else if (!Q_strcasecmp(mode, "stats"))
{
autotrackmode = TM_STATS;
autotrack_statsrule = NULL;
}
else
{
autotrackmode = TM_STATS;
@ -94,47 +104,131 @@ static void Cam_AutoTrack_f(void)
Cam_AutoTrack_Update(NULL);
}
static float CL_TrackScore(player_info_t *pl, char *rule)
static float CL_TrackScoreProp(player_info_t *pl, char rule, float *weights)
{
float score = 0;
float val;
int r;
while (*rule)
float r;
switch(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;
case 'a': //armour value
return pl->statsf[STAT_ARMOR];
case 'h':
return pl->statsf[STAT_HEALTH];
case 'A': //armour type
if (pl->stats[STAT_ITEMS] & IT_ARMOR3) r = weights[10];
else if (pl->stats[STAT_ITEMS] & IT_ARMOR2) r = weights[9];
else if (pl->stats[STAT_ITEMS] & IT_ARMOR1) r = weights[8];
else r = 0;
return r;
case 'W': //best weapon
r = 0;
if (r < weights[0] && (pl->stats[STAT_ITEMS] & IT_AXE)) r = weights[0];
if (r < weights[1] && (pl->stats[STAT_ITEMS] & IT_SHOTGUN)) r = weights[1];
if (r < weights[2] && (pl->stats[STAT_ITEMS] & IT_SUPER_SHOTGUN)) r = weights[2];
if (r < weights[3] && (pl->stats[STAT_ITEMS] & IT_NAILGUN)) r = weights[3];
if (r < weights[4] && (pl->stats[STAT_ITEMS] & IT_SUPER_NAILGUN)) r = weights[4];
if (r < weights[5] && (pl->stats[STAT_ITEMS] & IT_GRENADE_LAUNCHER)) r = weights[5];
if (r < weights[6] && (pl->stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER)) r = weights[6];
if (r < weights[7] && (pl->stats[STAT_ITEMS] & IT_LIGHTNING)) r = weights[7];
return r;
case 'p': //powerups held
r = 0;
r += (pl->stats[STAT_ITEMS] & IT_INVISIBILITY)?weights[11]:0;
r += (pl->stats[STAT_ITEMS] & IT_QUAD)?weights[12]:0;
r += (pl->stats[STAT_ITEMS] & IT_INVULNERABILITY)?weights[13]:0;
return r;
case 'f': //frags
return pl->frags;
// case 'F': //team frags
// return 0;
case 'g': //deaths
return Stats_GetDeaths(pl - cl.players);
case 'u': //userid
return pl - cl.players;
default:
return 0;
}
return score;
}
#define PRI_TOP 2
#define PRI_ADD 2
#define PRI_MUL 1
#define PRI_VAL 0
static float CL_TrackScore(player_info_t *pl, char **rule, float *weights, int pri)
{
float l, r;
char *s = *rule;
while (*s == ' ' || *s == '\t')
s++;
if (!pri)
{
if (*s == '(')
{
l = CL_TrackScore(pl, &s, weights, PRI_TOP);
while (*s == ' ' || *s == '\t')
s++;
if (*s == ')')
s++;
}
else if (*s == '%')
{
l = CL_TrackScoreProp(pl, *++s, weights);
s++;
}
else if (*s == '#')
{
int i = strtoul(s+1, &s, 0);
if (i >= 0 && i < MAX_CL_STATS)
l = pl->statsf[i];
else
l = 0;
}
else
l = strtod(s, &s);
while (*s == ' ' || *s == '\t')
s++;
}
else
l = CL_TrackScore(pl, &s, weights, pri-1);
for (;;)
{
if (pri == PRI_MUL)
{
if (*s == '*')
{
s++;
r = CL_TrackScore(pl, &s, weights, pri-1);
l *= r;
continue;
}
else if (*s == '/')
{
s++;
r = CL_TrackScore(pl, &s, weights, pri-1);
l /= r;
continue;
}
}
else if (pri == PRI_ADD)
{
if (*s == '+')
{
s++;
r = CL_TrackScore(pl, &s, weights, pri-1);
l += r;
continue;
}
else if (*s == '-')
{
s++;
r = CL_TrackScore(pl, &s, weights, pri-1);
l -= r;
continue;
}
}
break;
}
*rule = s;
return l;
}
static qboolean CL_MayTrack(int seat, int player)
{
@ -154,14 +248,60 @@ static qboolean CL_MayTrack(int seat, int player)
static int CL_FindHighTrack(int seat, char *rule)
{
int j = -1;
int i, k;
int i;
float max, score;
player_info_t *s;
float weights[14];
char *p;
if (rule && *rule == '[')
{
rule++;
weights[0] = strtod(rule, &rule); //axe
weights[1] = strtod(rule, &rule); //shot
weights[2] = strtod(rule, &rule); //sshot
weights[3] = strtod(rule, &rule); //nail
weights[4] = strtod(rule, &rule); //snail
weights[5] = strtod(rule, &rule); //gren
weights[6] = strtod(rule, &rule); //rock
weights[7] = strtod(rule, &rule); //lg
weights[8] = strtod(rule, &rule); //ga
weights[9] = strtod(rule, &rule); //ya
weights[10] = strtod(rule, &rule); //ra
weights[11] = strtod(rule, &rule); //ring
weights[12] = strtod(rule, &rule); //quad
weights[13] = strtod(rule, &rule); //pent
if (*rule == ']')
rule++;
}
else
{
weights[0] = 1; //axe
weights[1] = 2; //shot
weights[2] = 3; //sshot
weights[3] = 2; //nail
weights[4] = 3; //snail
weights[5] = 3; //gren
weights[6] = 8; //rock
weights[7] = 8; //lg
weights[8] = 1; //ga
weights[9] = 2; //ya
weights[10] = 3; //ra
weights[11] = 500; //ring
weights[12] = 900; //quad
weights[13] = 1000; //pent
}
if (!rule || !*rule)
rule = "%a * %A + 50 * %W + %p + %f";
//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 (CL_MayTrack(seat, j))
max = CL_TrackScore(&cl.players[j], rule);
{
p = rule;
max = CL_TrackScore(&cl.players[j], &p, weights, PRI_TOP);
}
else
{
max = -9999;
@ -171,17 +311,39 @@ static int CL_FindHighTrack(int seat, char *rule)
for (i = 0; i < cl.allocated_client_slots; i++)
{
s = &cl.players[i];
score = CL_TrackScore(s, rule);
if (j == i) //this was our default.
continue;
if (!CL_MayTrack(seat, i))
continue;
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
p = rule;
score = CL_TrackScore(s, &p, weights, PRI_TOP);
if (score > max)
{
max = score;
j = i;
}
}
if (j == -1 && cl.teamplay && seat)
{
//do it again, but with the teamplay check inverted
for (i = 0; i < cl.allocated_client_slots; i++)
{
s = &cl.players[i];
if (j == i) //this was our default.
continue;
if (!CL_MayTrack(seat, i))
continue;
if (cl.teamplay && seat && cl.playerview[0].cam_spec_track >= 0 && strcmp(cl.players[cl.playerview[0].cam_spec_track].team, s->team))
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
max = CL_TrackScore(s, rule);
j = i;
p = rule;
score = CL_TrackScore(s, &p, weights, PRI_TOP);
if (score > max)
{
max = score;
j = i;
}
}
}
return j;
@ -194,10 +356,10 @@ static int CL_AutoTrack_Choose(int seat)
best = cl.autotrack_killer;
if (autotrackmode == TM_MODHINTS && seat == 0 && cl.autotrack_hint >= 0)
best = cl.autotrack_hint;
if (autotrackmode == TM_STATS && cls.demoplayback == DPB_MVD)
if (autotrackmode == TM_STATS && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV))
best = CL_FindHighTrack(seat, autotrack_statsrule);
if (autotrackmode == TM_HIGHTRACK || best == -1)
best = CL_FindHighTrack(seat, "f");
best = CL_FindHighTrack(seat, "%f");
//TM_USER should generally avoid autotracking
cl.autotrack_killer = best; //killer should continue to track whatever is currently tracked until its changed by frag message parsing
return best;

View file

@ -390,6 +390,12 @@ void CL_DemoJump_f(void)
return;
}
if (Cmd_Argc() < 2)
{
Con_Printf("current time %.1f.\n", demtime);
return;
}
if (*s == '+' || *s == '-')
{
if (colon)

View file

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "winquake.h"
#include "gl_draw.h"
#include <sys/types.h>
#include "netinc.h"
#include "cl_master.h"
@ -4968,6 +4969,9 @@ double Host_Frame (double time)
scr_chatmode = 0;
SCR_UpdateScreen ();
if (R2D_Flush)
R2D_Flush();
}
if (host_speeds.ival)

View file

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// cl_screen.c -- master for refresh, status bar, console, chat, notify, etc
#include "quakedef.h"
#include "gl_draw.h"
#ifdef GLQUAKE
#include "glquake.h"//would prefer not to have this
#endif
@ -2594,5 +2595,8 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
SCR_DrawCursor();
SCR_DrawSimMTouchCursor();
if (R2D_Flush)
R2D_Flush();
RSpeedEnd(RSPEED_2D);
}

View file

@ -4732,7 +4732,7 @@ void Image_Shutdown(void)
i++;
}
if (i)
Con_Printf("Destroyed %i/%i images\n", j, i);
Con_DPrintf("Destroyed %i/%i images\n", j, i);
}
//load the named file, without failing.

View file

@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "gl_draw.h"
/*
@ -111,6 +112,7 @@ extern sfx_t *cl_sfx_r_exp3;
globalfunction(parse_damage, "CSQC_Parse_Damage"); \
globalfunction(input_event, "CSQC_InputEvent"); \
globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \
globalfunction(rendererrestarted, "CSQC_RendererRestarted"); \
globalfunction(console_command, "CSQC_ConsoleCommand"); \
globalfunction(console_link, "CSQC_ConsoleLink"); \
globalfunction(gamecommand, "GameCommand"); /*DP extension*/\
@ -1170,37 +1172,105 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva
//vbuff_delete(vboidx), vboidx=0
static shader_t *csqc_poly_shader;
static int csqc_poly_origvert;
static int csqc_poly_origidx;
static int csqc_poly_startvert;
static int csqc_poly_startidx;
static int csqc_poly_flags;
static int csqc_poly_2d;
static void CSQC_PolyFlush(void)
{
mesh_t mesh;
R2D_Flush = NULL;
//make sure there's actually something there...
if (cl_numstrisvert == csqc_poly_origvert)
return;
if (!csqc_poly_2d)
{
scenetris_t *t;
/*regular 3d polys are inserted into a 'scene trisoup' that the backend can then source from (multiple times, depending on how its drawn)*/
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = csqc_poly_shader;
t->flags = csqc_poly_flags;
t->firstidx = csqc_poly_origidx;
t->firstvert = csqc_poly_origvert;
t->numidx = cl_numstrisidx - t->firstidx;
t->numvert = cl_numstrisvert-csqc_poly_origvert;
}
else
{
/*2d polys need to be flushed now*/
memset(&mesh, 0, sizeof(mesh));
mesh.istrifan = (csqc_poly_origvert == csqc_poly_startvert);
mesh.xyz_array = cl_strisvertv + csqc_poly_origvert;
mesh.st_array = cl_strisvertt + csqc_poly_origvert;
mesh.colors4f_array[0] = cl_strisvertc + csqc_poly_origvert;
mesh.indexes = cl_strisidx + csqc_poly_origidx;
mesh.numindexes = cl_numstrisidx - csqc_poly_origidx;
mesh.numvertexes = cl_numstrisvert-csqc_poly_origvert;
/*undo the positions so we don't draw the same verts more than once*/
cl_numstrisvert = csqc_poly_origvert;
cl_numstrisidx = csqc_poly_origvert;
BE_DrawMesh_Single(csqc_poly_shader, &mesh, NULL, csqc_poly_flags);
}
//must call begin before the next poly
csqc_poly_shader = NULL;
}
// #306 void(string texturename) R_BeginPolygon (EXT_CSQC_???)
void QCBUILTIN PF_R_PolygonBegin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqc_poly_flags = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0;
shader_t *shader;
int flags = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0;
qboolean twod;
if (prinst->callargc > 2)
csqc_poly_2d = G_FLOAT(OFS_PARM2);
twod = G_FLOAT(OFS_PARM2);
else if (csqc_isdarkplaces)
{
csqc_poly_2d = !csqc_dp_lastwas3d;
twod = !csqc_dp_lastwas3d;
csqc_deprecated("guessing 2d mode based upon random builtin calls");
}
else
csqc_poly_2d = csqc_poly_flags & 4;
twod = flags & 4;
if ((csqc_poly_flags & 3) == 1)
csqc_poly_flags = BEF_FORCEADDITIVE;
if ((flags & 3) == 1)
flags = BEF_FORCEADDITIVE;
else
csqc_poly_flags = BEF_NOSHADOWS;
if (csqc_isdarkplaces)
csqc_poly_flags |= BEF_FORCETWOSIDED;
flags = BEF_NOSHADOWS;
if (csqc_isdarkplaces || (flags & 0x400))
flags |= BEF_FORCETWOSIDED;
if (csqc_poly_2d)
csqc_poly_shader = R_RegisterPic(PR_GetStringOfs(prinst, OFS_PARM0));
shader = R_RegisterPic(PR_GetStringOfs(prinst, OFS_PARM0));
else
csqc_poly_shader = R_RegisterSkin(PR_GetStringOfs(prinst, OFS_PARM0), NULL);
shader = R_RegisterSkin(PR_GetStringOfs(prinst, OFS_PARM0), NULL);
if (R2D_Flush && (R2D_Flush != CSQC_PolyFlush || csqc_poly_shader != shader || csqc_poly_flags != flags || csqc_poly_2d != twod))
R2D_Flush();
if (!R2D_Flush)
{ //this is where our current (2d) batch starts
csqc_poly_origvert = cl_numstrisvert;
csqc_poly_origidx = cl_numstrisidx;
}
R2D_Flush = CSQC_PolyFlush;
csqc_poly_shader = shader;
csqc_poly_flags = flags;
csqc_poly_2d = twod;
//this is where our current poly starts
csqc_poly_startvert = cl_numstrisvert;
csqc_poly_startidx = cl_numstrisidx;
}
@ -1226,10 +1296,10 @@ void QCBUILTIN PF_R_PolygonVertex(pubprogfuncs_t *prinst, struct globalvars_s *p
// #308 void() R_EndPolygon (EXT_CSQC_???)
void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
scenetris_t *t;
int i;
int nv;
int flags = csqc_poly_flags;
int first;
if (!csqc_poly_shader)
return;
@ -1237,24 +1307,26 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
nv = cl_numstrisvert-csqc_poly_startvert;
if (nv == 2)
flags |= BEF_LINES;
/*if the shader didn't change, continue with the old poly*/
if (cl_numstris && cl_stris[cl_numstris-1].shader == csqc_poly_shader && cl_stris[cl_numstris-1].flags == flags)
t = &cl_stris[cl_numstris-1];
else
flags &= ~BEF_LINES;
if (flags != csqc_poly_flags)
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = csqc_poly_shader;
t->flags = flags;
t->firstidx = cl_numstrisidx;
t->firstvert = csqc_poly_startvert;
t->numvert = 0;
t->numidx = 0;
int sv = cl_numstrisvert - nv;
cl_numstrisvert -= nv;
CSQC_PolyFlush();
csqc_poly_origvert = cl_numstrisvert;
csqc_poly_origidx = cl_numstrisidx;
R2D_Flush = CSQC_PolyFlush;
csqc_poly_flags = flags;
csqc_poly_startvert = cl_numstrisvert;
csqc_poly_startidx = cl_numstrisidx;
memcpy(cl_strisvertv+cl_numstrisvert, cl_strisvertv + sv, sizeof(*cl_strisvertv) * nv);
memcpy(cl_strisvertt+cl_numstrisvert, cl_strisvertt + sv, sizeof(*cl_strisvertt) * nv);
memcpy(cl_strisvertc+cl_numstrisvert, cl_strisvertc + sv, sizeof(*cl_strisvertc) * nv);
cl_numstrisvert += nv;
}
if (flags & BEF_LINES)
@ -1266,11 +1338,12 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
first = csqc_poly_startvert - csqc_poly_origvert;
/*build the line list fan out of triangles*/
for (i = 1; i < nv; i++)
{
cl_strisidx[cl_numstrisidx++] = t->numvert + i-1;
cl_strisidx[cl_numstrisidx++] = t->numvert + i;
cl_strisidx[cl_numstrisidx++] = first + i-1;
cl_strisidx[cl_numstrisidx++] = first + i;
}
}
else
@ -1282,42 +1355,19 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
first = csqc_poly_startvert - csqc_poly_origvert;
/*build the triangle fan out of triangles*/
for (i = 2; i < nv; i++)
{
cl_strisidx[cl_numstrisidx++] = t->numvert + 0;
cl_strisidx[cl_numstrisidx++] = t->numvert + i-1;
cl_strisidx[cl_numstrisidx++] = t->numvert + i;
cl_strisidx[cl_numstrisidx++] = first + 0;
cl_strisidx[cl_numstrisidx++] = first + i-1;
cl_strisidx[cl_numstrisidx++] = first + i;
}
}
if (csqc_poly_2d)
{
mesh_t mesh;
memset(&mesh, 0, sizeof(mesh));
mesh.istrifan = true;
mesh.xyz_array = cl_strisvertv + csqc_poly_startvert;
mesh.st_array = cl_strisvertt + csqc_poly_startvert;
mesh.colors4f_array[0] = cl_strisvertc + csqc_poly_startvert;
mesh.indexes = cl_strisidx + csqc_poly_startidx;
mesh.numindexes = cl_numstrisidx - csqc_poly_startidx;
mesh.numvertexes = cl_numstrisvert-csqc_poly_startvert;
/*undo the positions so we don't draw the same verts more than once*/
cl_numstrisvert = csqc_poly_startvert;
cl_numstrisidx = csqc_poly_startidx;
BE_DrawMesh_Single(csqc_poly_shader, &mesh, NULL, csqc_poly_flags);
}
else
{
t->numidx = cl_numstrisidx - t->firstidx;
t->numvert += cl_numstrisvert-csqc_poly_startvert;
/*set up ready for the next poly*/
csqc_poly_startvert = cl_numstrisvert;
csqc_poly_startidx = cl_numstrisidx;
}
/*set up ready for the next poly*/
csqc_poly_startvert = cl_numstrisvert;
csqc_poly_startidx = cl_numstrisidx;
}
@ -1420,6 +1470,9 @@ static void QCBUILTIN PF_cs_unproject (pubprogfuncs_t *prinst, struct globalvars
//clear scene, and set up the default stuff.
static void QCBUILTIN PF_R_ClearScene (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (R2D_Flush)
R2D_Flush();
if (prinst->callargc > 0)
CSQC_ChangeLocalPlayer(G_FLOAT(OFS_PARM0));
@ -1596,6 +1649,9 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
return;
}
if (R2D_Flush)
R2D_Flush();
csqc_rebuildmatricies = true;
G_FLOAT(OFS_RETURN) = 1;
@ -1792,6 +1848,8 @@ void R2D_PolyBlend (void);
void R_DrawNameTags(void);
static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (R2D_Flush)
R2D_Flush();
csqc_poly_shader = NULL;
if (csqc_worldchanged)
@ -5128,6 +5186,7 @@ static struct {
{"brush_delete", PF_brush_delete, 0},
{"brush_selected", PF_brush_selected, 0},
{"brush_getfacepoints", PF_brush_getfacepoints, 0},
{"brush_calcfacepoints", PF_brush_calcfacepoints,0},
{"brush_findinvolume", PF_brush_findinvolume, 0},
{"touchtriggers", PF_touchtriggers, 279},//void() touchtriggers = #279;
@ -5693,7 +5752,7 @@ void CSQC_Event_Think(world_t *w, wedict_t *s)
PR_ExecuteProgram (w->progs, s->v->think);
}
void CSQC_Event_Sound (float *origin, wedict_t *wentity, int channel, const char *sample, int volume, float attenuation, int pitchadj, float timeoffset)
void CSQC_Event_Sound (float *origin, wedict_t *wentity, int channel, const char *sample, int volume, float attenuation, int pitchadj, float timeoffset, unsigned int flags)
{
int i;
vec3_t originbuf;
@ -5709,7 +5768,7 @@ void CSQC_Event_Sound (float *origin, wedict_t *wentity, int channel, const char
origin = wentity->v->origin;
}
S_StartSound(NUM_FOR_EDICT(csqcprogs, (edict_t*)wentity), channel, S_PrecacheSound(sample), origin, volume, attenuation, timeoffset, pitchadj, 0);
S_StartSound(NUM_FOR_EDICT(csqcprogs, (edict_t*)wentity), channel, S_PrecacheSound(sample), origin, volume, attenuation, timeoffset, pitchadj, flags);
}
qboolean CSQC_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype)
@ -6199,6 +6258,10 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
csqcmapentitydataloaded = false;
csqc_world.physicstime = 0.1;
if (cls.state == ca_disconnected)
CSQC_WorldLoaded();
}
return true; //success!
@ -6218,6 +6281,18 @@ void CSQC_RendererRestarted(void)
}
//FIXME: registered shaders
//let the csqc know that its rendertargets got purged
if (csqcg.rendererrestarted)
PR_ExecuteProgram(csqcprogs, csqcg.rendererrestarted);
//in case it drew to any render targets.
if (R2D_Flush)
R2D_Flush();
if (*r_refdef.rt_destcolour[0].texname)
{
Q_strncpyz(r_refdef.rt_destcolour[0].texname, "", sizeof(r_refdef.rt_destcolour[0].texname));
BE_RenderToTextureUpdate2d(true);
}
}
void CSQC_WorldLoaded(void)
@ -6233,14 +6308,14 @@ void CSQC_WorldLoaded(void)
CSQC_FindGlobals(false);
csqcmapentitydataloaded = true;
csqcmapentitydata = cl.worldmodel->entities;
csqcmapentitydata = cl.worldmodel?cl.worldmodel->entities:NULL;
csqc_world.worldmodel = cl.worldmodel;
World_RBE_Start(&csqc_world);
worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0);
worldent->v->solid = SOLID_BSP;
csqc_setmodel(csqcprogs, worldent, 1);
csqc_setmodel(csqcprogs, worldent, cl.worldmodel?1:0);
worldent->readonly = false; //just in case
@ -6595,8 +6670,8 @@ qboolean CSQC_DrawView(void)
if (cl.paused)
*csqcg.frametime = 0; //apparently people can't cope with microstutter when they're using this as a test to see if the game is paused.
else
*csqcg.frametime = bound(0, cl.time - oldtime, 0.1);
oldtime = cl.time;
*csqcg.frametime = bound(0, cl.servertime - oldtime, 0.1);
oldtime = cl.servertime;
}
else
*csqcg.frametime = host_frametime;
@ -6671,6 +6746,8 @@ qboolean CSQC_DrawView(void)
else
PR_ExecuteProgram(csqcprogs, csqcg.f_updateview);
if (R2D_Flush)
R2D_Flush();
if (*r_refdef.rt_destcolour[0].texname)
{
Q_strncpyz(r_refdef.rt_destcolour[0].texname, "", sizeof(r_refdef.rt_destcolour[0].texname));

View file

@ -58,6 +58,7 @@ static void QDECL R2D_Crosshair_Callback(struct cvar_s *var, char *oldvalue);
static void QDECL R2D_CrosshairImage_Callback(struct cvar_s *var, char *oldvalue);
static void QDECL R2D_CrosshairColor_Callback(struct cvar_s *var, char *oldvalue);
void (*R2D_Flush)(void);
//We need this for minor things though, so we'll just use the slow accurate method.
//this is unlikly to be called too often.
@ -410,6 +411,9 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2,
return;
}
if (R2D_Flush)
R2D_Flush();
draw_mesh_xyz[0][0] = x;
draw_mesh_xyz[0][1] = y;
draw_mesh_st[0][0] = s1;
@ -447,6 +451,9 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic)
return;
}
if (R2D_Flush)
R2D_Flush();
for (i = 0; i < 4; i++)
{
Vector2Copy(points[i], draw_mesh_xyz[i]);
@ -459,6 +466,9 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic)
/*draws a block of the current colour on the screen*/
void R2D_FillBlock(float x, float y, float w, float h)
{
if (R2D_Flush)
R2D_Flush();
draw_mesh_xyz[0][0] = x;
draw_mesh_xyz[0][1] = y;
@ -479,6 +489,9 @@ void R2D_FillBlock(float x, float y, float w, float h)
void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader)
{
if (R2D_Flush)
R2D_Flush();
VectorSet(draw_mesh_xyz[0], x1, y1, 0);
Vector2Set(draw_mesh_st[0], 0, 0);
@ -632,6 +645,9 @@ void R2D_TileClear (float x, float y, float w, float h)
R2D_ImageColours(1,1,1,1);
if (R2D_Flush)
R2D_Flush();
draw_mesh_xyz[0][0] = x;
draw_mesh_xyz[0][1] = y;
draw_mesh_st[0][0] = newsl;

View file

@ -1078,7 +1078,8 @@ qboolean R_ApplyRenderer (rendererstate_t *newr)
return false;
time = Sys_DoubleTime();
M_Shutdown(false);
M_RemoveAllMenus(true);
Media_CaptureDemoEnd();
R_ShutdownRenderer(true);
Con_DPrintf("video shutdown took %f seconds\n", Sys_DoubleTime() - time);
@ -1691,7 +1692,7 @@ void R_RestartRenderer (rendererstate_t *newr)
SCR_EndLoadingPlaque();
TRACE(("dbg: R_RestartRenderer_f success\n"));
M_Reinit();
// M_Reinit();
}
void R_RestartRenderer_f (void)

View file

@ -3112,21 +3112,21 @@ ping time frags name
if (p < 0 || p > 999) p = 999; \
sprintf(num, "%4i", p); \
Draw_FunStringWidth(x, y, num, 4*8, false, false); \
})
},)
#define COLUMN_PL COLUMN(pl, 2*8, \
{ \
int p = s->pl; \
sprintf(num, "%2i", p); \
Draw_FunStringWidth(x, y, num, 2*8, false, false); \
})
},)
#define COLUMN_TIME COLUMN(time, 4*8, \
{ \
total = realtime - s->realentertime; \
minutes = (int)total/60; \
sprintf (num, "%4i", minutes); \
Draw_FunStringWidth(x, y, num, 4*8, false, false); \
})
},)
#define COLUMN_FRAGS COLUMN(frags, 5*8, \
{ \
int cx; int cy; \
@ -3136,12 +3136,6 @@ ping time frags name
} \
else \
{ \
if (largegame) \
Sbar_FillPC(x, y+1, 40, 3, top); \
else \
Sbar_FillPC(x, y, 40, 4, top); \
Sbar_FillPC(x, y+4, 40, 4, bottom); \
\
f = s->frags; \
sprintf(num, "%3i",f); \
\
@ -3162,6 +3156,15 @@ ping time frags name
} \
Font_EndString(font_default); \
} \
},{ \
if (!s->spectator) \
{ \
if (largegame) \
Sbar_FillPC(x, y+1, 40, 3, top); \
else \
Sbar_FillPC(x, y, 40, 4, top); \
Sbar_FillPC(x, y+4, 40, 4, bottom); \
} \
})
#define COLUMN_TEAMNAME COLUMN(team, 4*8, \
{ \
@ -3169,13 +3172,13 @@ ping time frags name
{ \
Draw_FunStringWidth(x, y, s->team, 4*8, false, false); \
} \
})
#define COLUMN_NAME COLUMN(name, (cl.teamplay ? 12*8 : 16*8), {Draw_FunStringWidth(x, y, s->name, (cl.teamplay ? 12*8 : 16*8), false, false);})
#define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetKills(k)), 4*8, false, false);})
#define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTKills(k)), 4*8, false, false);})
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetDeaths(k)), 4*8, false, false);})
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTouches(k)), 4*8, false, false);})
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetCaptures(k)), 4*8, false, false);})
},)
#define COLUMN_NAME COLUMN(name, (cl.teamplay ? 12*8 : 16*8), {Draw_FunStringWidth(x, y, s->name, (cl.teamplay ? 12*8 : 16*8), false, false);},)
#define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetKills(k)), 4*8, false, false);},)
#define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTKills(k)), 4*8, false, false);},)
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetDeaths(k)), 4*8, false, false);},)
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTouches(k)), 4*8, false, false);},)
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetCaptures(k)), 4*8, false, false);},)
@ -3184,7 +3187,7 @@ ping time frags name
enum
{
#define COLUMN(title, width, code) COLUMN##title,
#define COLUMN(title, width, code, fill) COLUMN##title,
ALLCOLUMNS
#undef COLUMN
COLUMN_MAX
@ -3270,7 +3273,7 @@ void Sbar_DeathmatchOverlay (int start)
rank_width = 0;
#define COLUMN(title, cwidth, code) if (rank_width+(cwidth)+8 <= gr.width) {showcolumns |= (1<<COLUMN##title); rank_width += cwidth+8;}
#define COLUMN(title, cwidth, code, fill) if (rank_width+(cwidth)+8 <= gr.width) {showcolumns |= (1<<COLUMN##title); rank_width += cwidth+8;}
//columns are listed here in priority order (if the screen is too narrow, later ones will be hidden)
COLUMN_NAME
COLUMN_PING
@ -3318,7 +3321,7 @@ void Sbar_DeathmatchOverlay (int start)
}
x = startx;
#define COLUMN(title, width, code) if (showcolumns & (1<<COLUMN##title)) {Draw_FunString(x, y, #title); x += width+8;}
#define COLUMN(title, width, code, fill) if (showcolumns & (1<<COLUMN##title)) {Draw_FunString(x, y, #title); x += width+8;}
ALLCOLUMNS
#undef COLUMN
@ -3328,7 +3331,7 @@ void Sbar_DeathmatchOverlay (int start)
if (scr_scoreboard_titleseperator.ival && !scr_scoreboard_newstyle.ival)
{
x = startx;
#define COLUMN(title, width, code) \
#define COLUMN(title, width, code, fill) \
if (showcolumns & (1<<COLUMN##title)) \
{ \
Draw_FunString(x, y, "^Ue01d"); \
@ -3357,6 +3360,7 @@ if (showcolumns & (1<<COLUMN##title)) \
y -= skip;
//drawfills (these are split out to aid batching)
for (i = 0; i < scoreboardlines; i++)
{
char team[5];
@ -3411,7 +3415,38 @@ if (showcolumns & (1<<COLUMN##title)) \
}
x = startx;
#define COLUMN(title, width, code) \
#define COLUMN(title, width, code, fills) \
if (showcolumns & (1<<COLUMN##title)) \
{ \
fills \
x += width+8; \
}
ALLCOLUMNS
#undef COLUMN
}
if (scr_scoreboard_newstyle.ival)
{
R2D_ImagePaletteColour (0, scr_scoreboard_fillalpha.value);
R2D_FillBlock (startx - 3, y + skip, rank_width - 1, 1); // Electro - Border - Bottom
}
R2D_ImageColours(1.0, 1.0, 1.0, 1.0);
y -= i * skip;
//text parts
for (i = 0; i < scoreboardlines; i++)
{
// TODO: Sort players so that the leading teams are drawn first
k = fragsort[i];
s = &cl.players[k];
if (!s->name[0])
continue;
y += skip;
if (y > vid.height-10)
break;
x = startx;
#define COLUMN(title, width, code, fills) \
if (showcolumns & (1<<COLUMN##title)) \
{ \
code \
@ -3421,16 +3456,8 @@ if (showcolumns & (1<<COLUMN##title)) \
#undef COLUMN
}
if (scr_scoreboard_newstyle.ival)
{
R2D_ImagePaletteColour (0, scr_scoreboard_fillalpha.value);
R2D_FillBlock (startx - 3, y + skip, rank_width - 1, 1); // Electro - Border - Bottom
}
if (y >= vid.height-10) // we ran over the screen size, squish
largegame = true;
R2D_ImageColours(1.0, 1.0, 1.0, 1.0);
}
void Sbar_ChatModeOverlay(playerview_t *pv)
@ -3578,6 +3605,20 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
x = sbar_rect.x + 320 + 4;
for (f = i, py = y; f < scoreboardlines && py < sbar_rect.y + sbar_rect.height - 8 + 1; f++)
{
k = fragsort[f];
s = &cl.players[k];
if (!s->name[0])
continue;
// draw ping
top = Sbar_TopColour(s);
bottom = Sbar_BottomColour(s);
Sbar_FillPC ( x, py+1, 40, 3, top);
Sbar_FillPC ( x, py+4, 40, 4, bottom);
py += 8;
}
for (/* */ ; i < scoreboardlines && y < sbar_rect.y + sbar_rect.height - 8 + 1; i++)
{
k = fragsort[i];
@ -3585,13 +3626,6 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
if (!s->name[0])
continue;
// draw ping
top = Sbar_TopColour(s);
bottom = Sbar_BottomColour(s);
Sbar_FillPC ( x, y+1, 40, 3, top);
Sbar_FillPC ( x, y+4, 40, 4, bottom);
// draw number
f = s->frags;
sprintf (num, "%3i",f);

View file

@ -95,10 +95,6 @@ qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
buffer->decodedbytecount = 0;
buffer->s = s;
s->decoder.buf = buffer;
s->decoder.decodedata = OV_DecodeSome;
s->decoder.querydata = OV_Query;
s->decoder.purge = OV_CancelDecoder;
s->decoder.ended = OV_CancelDecoder;
if (!OV_StartDecode(data, datalen, buffer))
{
@ -115,6 +111,10 @@ qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
s->loadstate = SLS_FAILED; //failed!
return false;
}
s->decoder.decodedata = OV_DecodeSome;
s->decoder.querydata = OV_Query;
s->decoder.purge = OV_CancelDecoder;
s->decoder.ended = OV_CancelDecoder;
s->decoder.decodedata(s, NULL, 0, 100);

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h"
#include "glquake.h"
#include "gl_draw.h"
#include <ctype.h> // for isdigit();
@ -1466,12 +1467,12 @@ entity_t *CL_EntityNum(int num)
#endif
float CalcFov (float fov_x, float width, float height);
void SCR_VRectForPlayer(vrect_t *vrect, int pnum)
static void SCR_VRectForPlayer(vrect_t *vrect, int pnum, unsigned maxseats)
{
#if MAX_SPLITS > 4
#pragma warning "Please change this function to cope with the new MAX_SPLITS value"
#endif
switch(cl.splitclients)
switch(maxseats)
{
case 1:
vrect->width = vid.fbvwidth;
@ -1828,7 +1829,7 @@ void R_DrawNameTags(void)
if ((!cl.spectator && !cls.demoplayback || !scr_autoid.ival) && (!cl.teamplay || !scr_autoid_team.ival))
return;
if (cls.state != ca_active || !cl.validsequence)
if (cls.state != ca_active || !cl.validsequence || cl.intermission)
return;
if (r_refdef.playerview->cam_state != CAM_FREECAM && r_refdef.playerview->cam_spec_track >= 0)
@ -2048,16 +2049,20 @@ void V_RenderPlayerViews(playerview_t *pv)
void V_RenderView (void)
{
int viewnum;
int maxviews = cl.splitclients;
Surf_LessenStains();
if (cls.state != ca_active)
return;
if (cl.intermission)
maxviews = 1;
R_PushDlights ();
r_secondaryview = 0;
for (viewnum = 0; viewnum < cl.splitclients; viewnum++)
for (viewnum = 0; viewnum < maxviews; viewnum++)
{
V_ClearRefdef(&cl.playerview[viewnum]);
if (viewnum)
@ -2085,7 +2090,9 @@ void V_RenderView (void)
RSpeedEnd(RSPEED_LINKENTITIES);
}
}
SCR_VRectForPlayer(&r_refdef.grect, viewnum);
if (R2D_Flush)
R2D_Flush();
SCR_VRectForPlayer(&r_refdef.grect, viewnum, maxviews);
V_RenderPlayerViews(r_refdef.playerview);
#ifdef PLUGINS

View file

@ -277,6 +277,7 @@ void QCBUILTIN PF_brush_create(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
void QCBUILTIN PF_brush_delete(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_selected(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_getfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_calcfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_brush_findinvolume(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_touchtriggers(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View file

@ -1026,6 +1026,8 @@ static void (D3D9_SCR_UpdateScreen) (void)
}
}
if (R2D_Flush)
R2D_Flush();
D3D9_Set2D();
R2D_BrightenScreen();
@ -1051,6 +1053,8 @@ static void (D3D9_SCR_UpdateScreen) (void)
RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow();
if (R2D_Flush)
R2D_Flush();
d3d9error(IDirect3DDevice9_EndScene(pD3DDev9));
d3d9error(IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL));

View file

@ -40,6 +40,8 @@ void R2D_FadeScreen (void);
void R2D_Init(void);
void R2D_Shutdown(void);
extern void (*R2D_Flush)(void); //if set, something is queued and must be flushed at some point. if its set to what you will set it to, then you can build onto your batch yourself.
void R2D_PolyBlend (void);
void R2D_BrightenScreen (void);

View file

@ -2,6 +2,7 @@
#ifndef SERVERONLY
#include "shader.h"
#include "gl_draw.h"
#ifdef _WIN32
#include <windows.h>
@ -392,6 +393,7 @@ void Font_Init(void)
//flush the font buffer, by drawing it to the screen
static void Font_Flush(void)
{
R2D_Flush = NULL;
if (!font_foremesh.numindexes)
return;
if (fontplanes.planechanged)
@ -419,7 +421,7 @@ static int Font_BeginChar(texid_t tex)
{
int fvert;
if (font_foremesh.numindexes == FONT_CHAR_BUFFER*6 || font_texture != tex)
if (font_foremesh.numindexes >= FONT_CHAR_BUFFER*6 || font_texture != tex)
{
Font_Flush();
TEXASSIGNF(font_texture, tex);
@ -1521,7 +1523,9 @@ void Font_Free(struct font_s *f)
//maps a given virtual screen coord to a pixel coord, which matches the font's height/width values
void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py)
{
Font_Flush();
if (R2D_Flush && curfont != font)
R2D_Flush();
R2D_Flush = Font_Flush;
curfont = font;
*px = (vx*(int)vid.rotpixelwidth) / (float)vid.width;
@ -1530,8 +1534,6 @@ void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py)
curfont_scale[0] = curfont->charheight;
curfont_scale[1] = curfont->charheight;
curfont_scaled = false;
font_colourmask = ~0u; //force the colour to be recalculated.
}
void Font_Transform(float vx, float vy, int *px, int *py)
{
@ -1542,7 +1544,9 @@ void Font_Transform(float vx, float vy, int *px, int *py)
}
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py)
{
Font_Flush();
if (R2D_Flush && curfont != font)
R2D_Flush();
R2D_Flush = Font_Flush;
curfont = font;
*px = (vx*(float)vid.rotpixelwidth) / (float)vid.width;
@ -1560,13 +1564,14 @@ void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx,
curfont_scale[0] = (szx * (float)vid.rotpixelheight) / (curfont->charheight * (float)vid.height);
curfont_scale[1] = (szy * (float)vid.rotpixelheight) / (curfont->charheight * (float)vid.height);
font_colourmask = ~0u; //force the colour to be recalculated.
}
void Font_EndString(struct font_s *font)
{
Font_Flush();
curfont = NULL;
// Font_Flush();
// curfont = NULL;
R2D_Flush = Font_Flush;
}
//obtains the font's row height (each row of chars should be drawn using this increment)
@ -1779,7 +1784,10 @@ void Font_ForceColour(float r, float g, float b, float a)
return;
if (font_colourmask & CON_NONCLEARBG)
{
Font_Flush();
R2D_Flush = Font_Flush;
}
font_colourmask = CON_WHITEMASK;
font_foretint[0] = r;
@ -1853,7 +1861,10 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint
{
vec4_t rgba;
if (font_colourmask & CON_NONCLEARBG)
{
Font_Flush();
R2D_Flush = Font_Flush;
}
font_colourmask = col;
rgba[0] = ((col>>CON_RICHRSHIFT)&0xf)*0x11;
@ -1899,7 +1910,10 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint
{
vec4_t rgba;
if ((col ^ font_colourmask) & CON_NONCLEARBG)
{
Font_Flush();
R2D_Flush = Font_Flush;
}
font_colourmask = col;
col = (charflags&CON_FGMASK)>>CON_FGSHIFT;
@ -2077,7 +2091,10 @@ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned in
{
vec4_t rgba;
if (font_backcolour[3])
{
Font_Flush();
R2D_Flush = Font_Flush;
}
font_colourmask = col;
rgba[0] = ((col>>CON_RICHRSHIFT)&0xf)*0x11;
@ -2119,7 +2136,10 @@ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned in
{
vec4_t rgba;
if (font_backcolour[3] != ((charflags & CON_NONCLEARBG)?127:0))
{
Font_Flush();
R2D_Flush = Font_Flush;
}
font_colourmask = col;
col = (charflags&CON_FGMASK)>>CON_FGSHIFT;

View file

@ -3274,9 +3274,11 @@ unsigned int Heightmap_PointContentsHM(heightmap_t *hm, float clipmipsz, vec3_t
return hm->exteriorcontents;
if (sx >= hm->maxsegx || sy >= hm->maxsegy)
return hm->exteriorcontents;
s = Terr_GetSection(hm, sx, sy, TGS_TRYLOAD);
if (!s)
s = Terr_GetSection(hm, sx, sy, TGS_TRYLOAD | TGS_ANYSTATE);
if (!s || s->loadstate != TSLS_LOADED)
{
if (s && s->loadstate == TSLS_FAILED)
return hm->exteriorcontents;
return FTECONTENTS_SOLID;
}
@ -3590,17 +3592,20 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
else if (sy < tr->hm->firstsegy || sy >= tr->hm->maxsegy)
return;//s = NULL;
else
s = Terr_GetSection(tr->hm, sx, sy, TGS_TRYLOAD|TGS_WAITLOAD);
s = Terr_GetSection(tr->hm, sx, sy, TGS_TRYLOAD|TGS_WAITLOAD|TGS_ANYSTATE);
if (!s)
if (!s || s->loadstate != TSLS_LOADED)
{
//you're not allowed to walk into sections that have not loaded.
//might as well check the entire section instead of just one tile
Vector4Set(n[0], 1, 0, 0, (tx/(SECTHEIGHTSIZE-1) + 1 - CHUNKBIAS)*tr->hm->sectionsize);
Vector4Set(n[1], -1, 0, 0, -(tx/(SECTHEIGHTSIZE-1) + 0 - CHUNKBIAS)*tr->hm->sectionsize);
Vector4Set(n[2], 0, 1, 0, (ty/(SECTHEIGHTSIZE-1) + 1 - CHUNKBIAS)*tr->hm->sectionsize);
Vector4Set(n[3], 0, -1, 0, -(ty/(SECTHEIGHTSIZE-1) + 0 - CHUNKBIAS)*tr->hm->sectionsize);
Heightmap_Trace_Brush(tr, n, 4);
if ((tr->contents & tr->hm->exteriorcontents) || s->loadstate != TSLS_FAILED)
{
//you're not allowed to walk into sections that have not loaded.
//might as well check the entire section instead of just one tile
Vector4Set(n[0], 1, 0, 0, (tx/(SECTHEIGHTSIZE-1) + 1 - CHUNKBIAS)*tr->hm->sectionsize);
Vector4Set(n[1], -1, 0, 0, -(tx/(SECTHEIGHTSIZE-1) + 0 - CHUNKBIAS)*tr->hm->sectionsize);
Vector4Set(n[2], 0, 1, 0, (ty/(SECTHEIGHTSIZE-1) + 1 - CHUNKBIAS)*tr->hm->sectionsize);
Vector4Set(n[3], 0, -1, 0, -(ty/(SECTHEIGHTSIZE-1) + 0 - CHUNKBIAS)*tr->hm->sectionsize);
Heightmap_Trace_Brush(tr, n, 4);
}
return;
}
@ -4576,14 +4581,20 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (!mod || !mod->terrain)
{
if (mod)
if (mod && mod->loadstate == MLS_LOADING)
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
if (mod && mod->loadstate == MLS_LOADED)
{
char basename[MAX_QPATH];
COM_FileBase(mod->name, basename, sizeof(basename));
mod->terrain = Mod_LoadTerrainInfo(mod, basename, true);
G_FLOAT(OFS_RETURN) = !!mod->terrain;
hm = mod->terrain;
if (!hm)
return;
Terr_FinishTerrain(mod);
}
return;
else
return;
}
hm = mod->terrain;
@ -5400,8 +5411,24 @@ static brushes_t *Terr_Brush_Insert(model_t *model, heightmap_t *hm, brushes_t *
brushes_t *out;
vec2_t mins, maxs;
vec2_t lm;
if (!hm)
return NULL;
{
if (model && model->loadstate == MLS_LOADING)
COM_WorkerPartialSync(model, &model->loadstate, MLS_LOADING);
if (model && model->loadstate == MLS_LOADED)
{
char basename[MAX_QPATH];
COM_FileBase(model->name, basename, sizeof(basename));
model->terrain = Mod_LoadTerrainInfo(model, basename, true);
hm = model->terrain;
if (!hm)
return NULL;
Terr_FinishTerrain(model);
}
else
return NULL;
}
hm->wbrushes = BZ_Realloc(hm->wbrushes, sizeof(*hm->wbrushes) * (hm->numbrushes+1));
out = &hm->wbrushes[hm->numbrushes];
@ -5815,7 +5842,22 @@ void QCBUILTIN PF_brush_create(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
G_INT(OFS_RETURN) = 0;
if (!hm)
return;
{
if (mod && mod->loadstate == MLS_LOADING)
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
if (mod && mod->loadstate == MLS_LOADED)
{
char basename[MAX_QPATH];
COM_FileBase(mod->name, basename, sizeof(basename));
mod->terrain = Mod_LoadTerrainInfo(mod, basename, true);
hm = mod->terrain;
if (!hm)
return;
Terr_FinishTerrain(mod);
}
else
return;
}
planes = alloca(sizeof(*planes) * numfaces);
faces = alloca(sizeof(*faces) * numfaces);
@ -5940,6 +5982,61 @@ void QCBUILTIN PF_brush_selected(pubprogfuncs_t *prinst, struct globalvars_s *pr
}
}
}
// {"brush_calcfacepoints",PF_brush_calcfacepoints,0,0, 0, 0, D("int(int faceid, brushface_t *in_faces, int numfaces, vector *points, int maxpoints)", "Determines the points of the specified face, if the specified brush were to actually be created.")},
void QCBUILTIN PF_brush_calcfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int faceid = G_INT(OFS_PARM0);
unsigned int numfaces = G_INT(OFS_PARM2);
qcbrushface_t *in_faces = validateqcpointer(prinst, G_INT(OFS_PARM1), sizeof(*in_faces), numfaces);
unsigned int maxpoints = G_INT(OFS_PARM4);
vec3_t *out_verts = validateqcpointer(prinst, G_INT(OFS_PARM3), sizeof(*out_verts), maxpoints);
vecV_t facepoints[256];
vec4_t planes[256];
unsigned int j, numpoints;
faceid--;
if (faceid < 0 || faceid >= numfaces)
{
G_INT(OFS_RETURN) = 0;
return;
}
//make sure this isn't a dupe face
for (j = 0; j < faceid; j++)
{
if (in_faces[j].planenormal[0] == in_faces[faceid].planenormal[0] &&
in_faces[j].planenormal[1] == in_faces[faceid].planenormal[1] &&
in_faces[j].planenormal[2] == in_faces[faceid].planenormal[2] &&
in_faces[j].planedist == in_faces[faceid].planedist)
{
G_INT(OFS_RETURN) = 0;
return;
}
}
//generate a list that Terr_GenerateBrushFace can actually use, silly, but lets hope this isn't needed to be nippy
for (j = 0; j < numfaces; j++)
{
VectorCopy(in_faces[j].planenormal, planes[j]);
planes[j][3] = in_faces[j].planedist;
}
//generate points now (so we know the correct mins+maxs for the brush, and whether the plane is relevent)
numpoints = Terr_GenerateBrushFace(facepoints, countof(facepoints), planes, numfaces, planes[faceid]);
G_INT(OFS_RETURN) = numpoints;
if (numpoints > maxpoints)
numpoints = maxpoints;
//... and copy them out without padding. yeah, silly.
for (j = 0; j < numpoints; j++)
{
VectorCopy(facepoints[j], out_verts[j]);
}
}
// {"brush_getfacepoints",PF_brush_getfacepoints,0,0, 0, 0, D("int(float modelid, int brushid, int faceid, vector *points, int maxpoints)", "Allows you to easily set transient visual properties of a brush. If brush/face is -1, applies to all. returns old value. selectedstate=-1 changes nothing (called for its return value).")},
void QCBUILTIN PF_brush_getfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -6057,7 +6154,8 @@ void Terr_WriteBrushInfo(vfsfile_t *file, brushes_t *br)
point[1] = br->faces[i].points[1];
point[2] = br->faces[i].points[2];
VFS_PRINTF(file, "\n( %g %g %g ) ( %g %g %g ) ( %g %g %g ) \"%s\" [ %g %g %g %g ] [ %g %g %g %g ] 0 1 1",
//%.9g is 'meant' to be lossless for a standard ieee single-precision float. (%.17g for a double)
VFS_PRINTF(file, "\n( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) \"%s\" [ %.9g %.9g %.9g %.9g ] [ %.9g %.9g %.9g %.9g ] 0 1 1",
point[0][0], point[0][1], point[0][2],
point[1][0], point[1][1], point[1][2],
point[2][0], point[2][1], point[2][2],

View file

@ -225,6 +225,8 @@ void GLSCR_UpdateScreen (void)
RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow();
if (R2D_Flush)
R2D_Flush();
RSpeedRemark();
GL_EndRendering ();

View file

@ -5465,7 +5465,7 @@ static qboolean Shader_ParseShader(char *parsename, shader_t *s)
}
void R_UnloadShader(shader_t *shader)
{
if (shader->uses-- == 1)
if (--shader->uses == 0)
Shader_Free(shader);
}
static shader_t *R_LoadShader (const char *name, unsigned int usageflags, shader_gen_t *defaultgen, const char *genargs)
@ -5493,6 +5493,8 @@ static shader_t *R_LoadShader (const char *name, unsigned int usageflags, shader
//q3 has a separate (internal) shader for every lightmap.
if (!((s->usageflags ^ usageflags) & SUF_LIGHTMAP))
{
if (!s->uses)
break;
s->uses++;
return s;
}

View file

@ -602,6 +602,7 @@ pbool LocateDebugTerm(progfuncs_t *progfuncs, char *key, eval_t **result, etype_
char *c, *c2;
etype_t type = ev_void;
struct edictrun_s *ed;
etype_t ptrtype = ev_void;
c = strchr(key, '.');
if (c) *c = '\0';
@ -722,6 +723,43 @@ pbool PDECL PR_SetWatchPoint(pubprogfuncs_t *ppf, char *key)
return true;
}
static char *PR_ParseCast(char *key, etype_t *t, pbool *isptr)
{
extern char *basictypenames[];
int type;
*t = ev_void;
*isptr = false;
while(*key == ' ')
key++;
if (*key == '(')
{
key++;
for (type = 0; type < 10; type++)
{
if (!strncmp(key, basictypenames[type], strlen(basictypenames[type])))
{
key += strlen(basictypenames[type]);
while(*key == ' ')
key++;
if (*key == '*')
{
*isptr = true;
key++;
}
*t = type;
break;
}
}
if (type == 10)
return NULL;
while(*key == ' ')
key++;
if (*key++ != ')')
return NULL;
}
return key;
}
char *PDECL PR_EvaluateDebugString(pubprogfuncs_t *ppf, char *key)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
@ -731,12 +769,44 @@ char *PDECL PR_EvaluateDebugString(pubprogfuncs_t *ppf, char *key)
char *assignment;
etype_t type;
eval_t fakeval;
extern char *basictypenames[];
if (*key == '*')
{
int ptr;
eval_t v;
etype_t cast;
pbool isptr;
type = ev_void;
key = PR_ParseCast(key+1, &cast, &isptr);
if (!key || !isptr)
return "(unable to evaluate)";
if (*key == '&')
{
if (!LocateDebugTerm(progfuncs, key+1, &val, &type, &fakeval) && val != &fakeval)
return "(unable to evaluate)";
v._int = (char*)val - progfuncs->funcs.stringtable;
val = &v;
type = ev_pointer;
}
else
{
if (!LocateDebugTerm(progfuncs, key, &val, &type, &fakeval) && val != &fakeval)
return "(unable to evaluate)";
}
if (type == ev_integer || type == ev_string || type == ev_pointer)
ptr = val->_int;
else if (type == ev_float)
ptr = val->_float;
else
return "(unable to evaluate)";
return PR_ValueString(progfuncs, cast, (eval_t*)(progfuncs->funcs.stringtable + ptr), true);
}
if (*key == '&')
{
if (!LocateDebugTerm(progfuncs, key+1, &val, &type, &fakeval) && val != &fakeval)
return "(unable to evaluate)";
QC_snprintfz(buf, sizeof(buf), "%#x", (char*)val - progfuncs->funcs.stringtable);
QC_snprintfz(buf, sizeof(buf), "(%s*)%#x", ((type>=10)?"???":basictypenames[type]), (char*)val - progfuncs->funcs.stringtable);
return buf;
}

View file

@ -568,6 +568,7 @@ pbool resetprogssrc; //progs.src was changed, reload project info.
HWND mainwindow;
HWND gamewindow;
HWND mdibox;
HWND watches;
HWND optionsmenu;
HWND outputwindow;
HWND outputbox;
@ -2762,13 +2763,27 @@ static LRESULT CALLBACK EngineWndProc(HWND hWnd,UINT message,
free(ctx);
}
if (hWnd == gamewindow)
{
gamewindow = NULL;
PostMessage(mainwindow, WM_SIZE, 0, 0);
}
break;
case WM_USER:
//engine broke. show code.
if (lParam)
SetForegroundWindow(mainwindow);
EditFile((char*)lParam, wParam-1, true);
if (watches)
{
char text[MAX_PATH];
int i, lim = ListView_GetItemCount(watches);
for (i = 0; i < lim; i++)
{
ListView_GetItemText(watches, i, 0, text, sizeof(text));
EngineCommandWndf(hWnd, "qcinspect \"%s\" \"%s\"\n", text, ""); //term, scope
}
}
break;
case WM_USER+1:
//engine loaded a progs, reset breakpoints.
@ -2809,6 +2824,17 @@ static LRESULT CALLBACK EngineWndProc(HWND hWnd,UINT message,
SendMessage(tooltip_editor->editpane, SCI_CALLTIPSHOW, (WPARAM)tooltip_position, (LPARAM)tip);
}
if (watches)
{
char text[MAX_PATH];
int i, lim = ListView_GetItemCount(watches);
for (i = 0; i < lim; i++)
{
ListView_GetItemText(watches, i, 0, text, sizeof(text));
if (!strcmp(text, varname))
ListView_SetItemText(watches, i, 1, varvalue);
}
}
free((char*)lParam);
}
break;
@ -3038,6 +3064,7 @@ void RunEngine(void)
enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA);
}
// SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)gamewindow, 0);
PostMessage(mainwindow, WM_SIZE, 0, 0);
}
@ -3692,6 +3719,37 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
0, 0, 320, 200, hWnd, (HMENU) 0xCAC, ghInstance, (LPSTR) &ccs);
ShowWindow(mdibox, SW_SHOW);
watches = CreateWindow(WC_LISTVIEW, (LPCTSTR) NULL,
WS_CHILD | WS_VSCROLL | WS_HSCROLL | LVS_REPORT | LVS_EDITLABELS,
0, 0, 320, 200, hWnd, (HMENU) 0xCAD, ghInstance, NULL);
ShowWindow(watches, SW_SHOW);
if (watches)
{
LVCOLUMN col;
LVITEM newi;
// ListView_SetUnicodeFormat(watches, TRUE);
ListView_SetExtendedListViewStyle(watches, LVS_EX_GRIDLINES);
memset(&col, 0, sizeof(col));
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
col.cx = 320;
col.pszText = "Variable";
ListView_InsertColumn(watches, 0, &col);
col.pszText = "Value";
ListView_InsertColumn(watches, 1, &col);
memset(&newi, 0, sizeof(newi));
newi.pszText = "<click to add>";
newi.mask = LVIF_TEXT | LVIF_PARAM;
newi.lParam = ~0;
newi.iSubItem = 0;
ListView_InsertItem(watches, &newi);
}
projecttree = CreateWindow(WC_TREEVIEW, (LPCTSTR) NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL
| TVS_HASBUTTONS |TVS_LINESATROOT|TVS_HASLINES,
@ -3732,12 +3790,23 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
GetClientRect(mainwindow, &rect);
if (projecttree)
{
int mdiheight, watchheight;
SetWindowPos(projecttree, NULL, 0, 0, 192, rect.bottom-rect.top - 34 - 48, 0);
SetWindowPos(search_name, NULL, 0, rect.bottom-rect.top - 33 - 48, 192, 24, 0);
SetWindowPos(search_gotodef, NULL, 0, rect.bottom-rect.top - 33 - 24, 192/2, 24, 0);
SetWindowPos(search_grep, NULL, 192/2, rect.bottom-rect.top - 33 - 24, 192/2, 24, 0);
SetWindowPos(mdibox?mdibox:outputbox, NULL, 192, 0, rect.right-rect.left-192, rect.bottom-rect.top - 32, 0);
if (gamewindow)
watchheight = (ListView_GetItemCount(watches) + 2) * 16;
else
watchheight = 0;
mdiheight = (rect.bottom-rect.top) - 32;
if (watchheight > mdiheight/2)
watchheight = mdiheight/2;
mdiheight -= watchheight;
SetWindowPos(watches, NULL, 192, mdiheight, rect.right-rect.left-192, watchheight, 0);
SetWindowPos(mdibox?mdibox:outputbox, NULL, 192, 0, rect.right-rect.left-192, mdiheight, 0);
}
else
SetWindowPos(mdibox?mdibox:outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top - 32, 0);
@ -3796,9 +3865,9 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
GetWindowText(search_name, greptext, sizeof(greptext)-1);
return true;
}
if (i>0 && i <= NUMBUTTONS)
if (i>=20 && i < 20+NUMBUTTONS)
{
buttons[i-1].washit = 1;
buttons[i-20].washit = 1;
break;
}
if (i < IDM_FIRSTCHILD)
@ -3831,7 +3900,84 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
int oldlen;
int newlen;
nm = (NMHDR*)lParam;
if (nm->hwndFrom == projecttree)
if (nm->hwndFrom == watches)
{
NMLISTVIEW *lnm = (NMLISTVIEW*)nm;
switch(nm->code)
{
case LVN_BEGINLABELEDITA:
return FALSE; //false to allow...
case LVN_BEGINLABELEDITW:
// OutputDebugString("Begin EditW\n");
return FALSE; //false to allow...
case LVN_ENDLABELEDITA:
if (((NMLVDISPINFOA*)nm)->item.iItem == ListView_GetItemCount(watches)-1)
{
LVITEM newi;
memset(&newi, 0, sizeof(newi));
newi.iItem = ListView_GetItemCount(watches);
newi.pszText = "<click to add>";
newi.mask = LVIF_TEXT | LVIF_PARAM;
newi.lParam = ~0;
newi.iSubItem = 0;
ListView_InsertItem(watches, &newi);
}
EngineCommandf("qcinspect \"%s\" \"%s\"\n", ((NMLVDISPINFOA*)nm)->item.pszText, ""); //term, scope
PostMessage(mainwindow, WM_SIZE, 0, 0);
return TRUE; //true to allow...
/* case LVN_ENDLABELEDITW:
// OutputDebugString("End EditW\n");
if (((NMLVDISPINFOW*)nm)->item.iItem == ListView_GetItemCount(watches)-1)
{
LVITEM newi;
memset(&newi, 0, sizeof(newi));
newi.iItem = ListView_GetItemCount(watches);
newi.pszText = "<click to add>";
newi.mask = LVIF_TEXT | LVIF_PARAM;
newi.lParam = ~0;
newi.iSubItem = 0;
ListView_InsertItem(watches, &newi);
}
EngineCommandf("qcinspect \"%s\" \"%s\"\n", ((NMLVDISPINFOW*)nm)->item.pszText, ""); //term, scope
return TRUE; //true to allow...
*/
case LVN_ITEMCHANGING:
// OutputDebugString("Changing\n");
return FALSE; //false to allow...
case LVN_ITEMCHANGED:
// OutputDebugString("Changed\n");
return FALSE;
case LVN_GETDISPINFOA:
// OutputDebugString("LVN_GETDISPINFOA\n");
return FALSE;
// case LVN_GETDISPINFOW:
// OutputDebugString("LVN_GETDISPINFOW\n");
// return FALSE;
case NM_DBLCLK:
// OutputDebugString("NM_DBLCLK\n");
{
NMITEMACTIVATE *ia = (NMITEMACTIVATE*)nm;
LVHITTESTINFO ht;
memset(&ht, 0, sizeof(ht));
ht.pt = ia->ptAction;
ListView_SubItemHitTest(watches, &ht);
ListView_EditLabel(watches, ht.iItem);
}
return TRUE;
case LVN_ITEMACTIVATE:
// OutputDebugString("LVN_ITEMACTIVATE\n");
return FALSE; //must return false
case LVN_COLUMNCLICK:
// OutputDebugString("LVN_COLUMNCLICK\n");
break;
default:
// sprintf(filename, "%i\n", nm->code);
// OutputDebugString(filename);
break;
}
return FALSE;
}
else if (nm->hwndFrom == projecttree)
{
switch(nm->code)
{
@ -4856,7 +5002,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
WS_CHILD | WS_VISIBLE,
0, 0, 5, 5,
mainwindow,
(HMENU)(LONG_PTR)(i+1),
(HMENU)(LONG_PTR)(i+20),
ghInstance,
NULL);
}

View file

@ -681,11 +681,11 @@ void PR_LoadGlabalStruct(qboolean muted)
int i;
int *v;
globalptrs_t *pr_globals = pr_global_ptrs;
#define globalfloat(need,name) (pr_globals)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static float fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_Printf("Could not find \""#name"\" export in progs\n");}
#define globalint(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static int fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_Printf("Could not find \""#name"\" export in progs\n");}
#define globalstring(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static string_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_Printf("Could not find \""#name"\" export in progs\n");}
#define globalvec(need,name) (pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static vec3_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_Printf("Could not find \""#name"\" export in progs\n");}
#define globalfunc(need,name) (pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!(pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) (pr_globals)->name = &stripped##name; else if (need && !muted) Con_Printf("Could not find function \""#name"\" in progs\n"); }
#define globalfloat(need,name) (pr_globals)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static float fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");}
#define globalint(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static int fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");}
#define globalstring(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static string_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");}
#define globalvec(need,name) (pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static vec3_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");}
#define globalfunc(need,name) (pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!(pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) (pr_globals)->name = &stripped##name; else if (need && !muted) Con_DPrintf("Could not find function \""#name"\" in progs\n"); }
// globalint(pad);
globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.
globalint (true, other);
@ -773,7 +773,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static vec3_t fallback_trace_plane_normal;
(pr_globals)->trace_plane_normal = &fallback_trace_plane_normal;
if (!muted)
Con_Printf("Could not find export trace_plane_normal in progs\n");
Con_DPrintf("Could not find trace_plane_normal export in progs\n");
}
}
if (!(pr_globals)->trace_endpos)
@ -784,7 +784,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static vec3_t fallback_trace_endpos;
(pr_globals)->trace_endpos = &fallback_trace_endpos;
if (!muted)
Con_Printf("Could not find export trace_endpos in progs\n");
Con_DPrintf("Could not find trace_endpos export in progs\n");
}
}
if (!(pr_globals)->trace_fraction)
@ -795,7 +795,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static float fallback_trace_fraction;
(pr_globals)->trace_fraction = &fallback_trace_fraction;
if (!muted)
Con_Printf("Could not find export trace_fraction in progs\n");
Con_DPrintf("Could not find trace_fraction export in progs\n");
}
}
ensureglobal(serverflags, zero_default);
@ -9622,7 +9622,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"brush_delete", PF_brush_delete, 0, 0, 0, 0, D("void(float modelidx, int brushid)", "Destroys the specified brush.")},
{"brush_selected", PF_brush_selected, 0, 0, 0, 0, D("float(float modelid, int brushid, int faceid, float selectedstate)", "Allows you to easily set transient visual properties of a brush. returns old value. selectedstate=-1 changes nothing (called for its return value).")},
{"brush_getfacepoints",PF_brush_getfacepoints,0,0, 0, 0, D("int(float modelid, int brushid, int faceid, vector *points, int maxpoints)", "Returns the list of verticies surrounding the given face. If face is 0, returns the center of the brush (if space for 1 point) or the mins+maxs (if space for 2 points).")},
// {"brush_calcfacepoints",PF_brush_calcfacepoints,0,0, 0, 0, D("int(brushface_t *in_faces, int numfaces, int faceid, vector *points, int maxpoints)", "Returns the list of verticies surrounding the given face. If face is 0, returns the center of the brush (if space for 1 point) or the mins+maxs (if space for 2 points). Returns 0 if a face is degenerate.")},
{"brush_calcfacepoints",PF_brush_calcfacepoints,0,0, 0, 0, D("int(int faceid, brushface_t *in_faces, int numfaces, vector *points, int maxpoints)", "Determines the points of the specified face, if the specified brush were to actually be created.")},
{"brush_findinvolume",PF_brush_findinvolume,0, 0, 0, 0, D("int(float modelid, vector *planes, float *dists, int numplanes, int *out_brushes, int *out_faces, int maxresults)", "Allows you to easily obtain a list of brushes+faces within the given bounding region. If out_faces is not null, the same brush might be listed twice.")},
// {"brush_editplane", PF_brush_editplane, 0, 0, 0, 0, D("float(float modelid, int brushid, int faceid, in brushface *face)", "Changes a surface's texture info.")},
// {"brush_transformselected",PF_brush_transformselected,0,0,0, 0, D("int(float modelid, int brushid, float *matrix)", "Transforms selected brushes by the given transform")},
@ -10711,6 +10711,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_Parse_Event", "void()", CS, "Called when the client receives an SVC_CGAMEPACKET. The csqc should read the data or call the error builtin if it does not recognise the message."},
{"CSQC_InputEvent", "float(float evtype, float scanx, float chary, float devid)", CS, "Called whenever a key is pressed, the mouse is moved, etc. evtype will be one of the IE_* constants. The other arguments vary depending on the evtype. Key presses are not guarenteed to have both scan and unichar values set at the same time."},
{"CSQC_Input_Frame", "__used void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."},
{"CSQC_RendererRestarted", "void(void)", CS, "Called by the engine after the video was restarted. This serves to notify the CSQC that any render targets that it may have cached were purged, and will need to be regenerated."},
{"CSQC_ConsoleCommand", "float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."},
{"CSQC_ConsoleLink", "float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself."},
{"CSQC_Ent_Update", "void(float isnew)", CS},