heightmap semi-functional again, but still useless.

A few bugs fixed.
Slightly better compatibility with DP.
Added breakpoint_csqc command to set breakpoints in csqc to better debug csprogs.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3793 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2011-05-20 04:10:46 +00:00
parent 9c0a84e3aa
commit d5ab16befc
62 changed files with 1811 additions and 818 deletions

View file

@ -2713,15 +2713,6 @@ guess_pm_type:
state->pm_type = PM_NORMAL;
}
/* if (cl.lerpplayers[num].frame != state->frame)
{
cl.lerpplayers[num].oldframechange = cl.lerpplayers[num].framechange;
cl.lerpplayers[num].framechange = cl.time;
cl.lerpplayers[num].frame = state->frame;
//don't care about position interpolation.
}
*/
TP_ParsePlayerInfo(oldstate, state, info);
}
@ -2881,6 +2872,8 @@ void CL_LinkPlayers (void)
continue; // not present this frame
}
CL_UpdateNetFrameLerpState(false, state->frame, &cl.lerpplayers[j]);
#ifdef CSQC_DAT
if (CSQC_DeltaPlayer(j, state))
continue;
@ -2983,7 +2976,6 @@ void CL_LinkPlayers (void)
ent->skinnum = state->skinnum;
CL_UpdateNetFrameLerpState(false, state->frame, &cl.lerpplayers[j]);
CL_LerpNetFrameState(FS_REG, &ent->framestate, &cl.lerpplayers[j]);
// if (state->modelindex == cl_playerindex)

View file

@ -2665,11 +2665,17 @@ void CL_ReadPackets (void)
//
if (cls.state >= ca_connected
&& realtime - cls.netchan.last_received > cl_timeout.value)
{
#ifndef CLIENTONLY
/*don't timeout when we're the actual server*/
if (!sv.state)
#endif
{
Con_TPrintf (TLC_SERVERTIMEOUT);
CL_Disconnect ();
return;
}
}
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
MVD_Interpolate();

View file

@ -4658,6 +4658,13 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
{
Cam_SetAutoTrack(atoi(stufftext+5));
}
else if (!strncmp(stufftext, "//kickfile ", 11))
{
flocation_t loc;
Cmd_TokenizeString(stufftext+2, false, false);
if (FS_FLocateFile(Cmd_Argv(1), FSLFRT_IFFOUND, &loc))
Con_Printf("You have been kicked due to a modified file located at %s.\n", Cmd_Argv(0));
}
#ifdef PLUGINS
else if (!strncmp(stufftext, "//tinfo ", 8))
{
@ -5270,11 +5277,11 @@ void CL_ParseServerMessage (void)
case svcfte_cgamepacket:
#ifdef HLCLIENT
if (CLHL_ParseGamePacket());
if (CLHL_ParseGamePacket())
break;
#endif
#ifdef CSQC_DAT
if (CSQC_ParseGamePacket());
if (CSQC_ParseGamePacket())
break;
#endif
Con_Printf("Unable to parse gamecode packet\n");

View file

@ -1052,6 +1052,8 @@ qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state);
void CSQC_DeltaStart(float time);
qboolean CSQC_DeltaUpdate(entity_state_t *src);
void CSQC_DeltaEnd(void);
void CSQC_CvarChanged(cvar_t *var);
#endif
//
@ -1211,6 +1213,8 @@ extern qboolean editoractive;
extern qboolean editormodal;
void Editor_Draw(void);
void Editor_Init(void);
struct progfuncs_s;
void Editor_ProgsKilled(struct progfuncs_s *dead);
#endif
void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale);

View file

@ -1178,7 +1178,7 @@ badjpeg:
#endif
goto badjpeg;
}
if (cinfo.output_components!=3)
if (cinfo.output_components!=3 && cinfo.output_components != 1)
{
#ifdef _DEBUG
Con_Printf("Bad number of components in JPEG: '%d', should be '3'.\n",cinfo.output_components);
@ -1192,6 +1192,29 @@ badjpeg:
out=mem=BZ_Malloc(cinfo.output_height*cinfo.output_width*4);
memset(out, 0, cinfo.output_height*cinfo.output_width*4);
if (cinfo.output_components == 1)
{
while (cinfo.output_scanline < cinfo.output_height)
{
#ifdef DYNAMIC_LIBJPEG
(void) qjpeg_read_scanlines(&cinfo, buffer, 1);
#else
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
#endif
in = buffer[0];
for (i = 0; i < cinfo.output_width; i++)
{//rgb to rgba
*out++ = *in;
*out++ = *in;
*out++ = *in;
*out++ = 255;
in++;
}
}
}
else
{
while (cinfo.output_scanline < cinfo.output_height)
{
#ifdef DYNAMIC_LIBJPEG
@ -1209,6 +1232,7 @@ badjpeg:
*out++ = 255;
}
}
}
#ifdef DYNAMIC_LIBJPEG
(void) qjpeg_finish_decompress(&cinfo);
@ -2241,7 +2265,8 @@ int image_width, image_height;
texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
{
qboolean alphaed;
char *buf, *data;
char *buf;
unsigned char *data;
texid_t tex;
// int h;
char fname[MAX_QPATH], nicename[MAX_QPATH];
@ -2332,6 +2357,35 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
extern cvar_t vid_hardwaregamma;
if (!(flags&IF_NOGAMMA) && !vid_hardwaregamma.value)
BoostGamma(data, image_width, image_height);
if (!(flags & IF_NOALPHA))
{
unsigned int alpha_width, alpha_height, p;
char aname[MAX_QPATH];
unsigned char *alphadata;
char *alph;
if (tex_path[i].args >= 3)
snprintf(aname, sizeof(aname)-1, tex_path[i].path, subpath, nicename, va("_alpha%s", tex_extensions[e].name));
else
snprintf(aname, sizeof(aname)-1, tex_path[i].path, nicename, va("_alpha%s", tex_extensions[e].name));
if ((alph = COM_LoadFile (aname, 5)))
{
if ((alphadata = Read32BitImageFile(alph, com_filesize, &alpha_width, &alpha_height, aname)))
{
if (alpha_width == image_width && alpha_height == image_height)
{
for (p = 0; p < alpha_width*alpha_height; p++)
{
data[(p<<2) + 3] = (alphadata[(p<<2) + 0] + alphadata[(p<<2) + 1] + alphadata[(p<<2) + 2])/3;
}
}
BZ_Free(alphadata);
}
BZ_Free(alph);
}
}
TRACE(("dbg: Mod_LoadHiResTexture: %s loaded\n", name));
if (tex_path[i].args >= 3)
{ //if it came from a special subpath (eg: map specific), upload it using the subpath prefix

View file

@ -1340,6 +1340,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
#endif
#ifdef PEXT_CSQC
if (mx || my)
if (CSQC_MouseMove(mx, my))
{
mx = 0;

View file

@ -1312,7 +1312,7 @@ qboolean Key_MouseShouldBeFree(void)
if (m_state == m_complex || m_state == m_plugin /*|| m_state == m_menu_dat*/)
return true;
}
if (key_dest == key_console)
if (key_dest == key_console || key_dest == key_editor)
return true;
#ifdef VM_UI
@ -1605,7 +1605,6 @@ void Key_Event (int pnum, int key, unsigned int unicode, qboolean down)
//
// during demo playback, most keys bring up the main menu
//
if (cls.demoplayback && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV && down && consolekeys[key] && key != K_TAB && key_dest == key_game)
{
M_ToggleMenu_f ();

View file

@ -1740,6 +1740,9 @@ void M_Menu_Singleplayer_Cheats_f (void)
extern cvar_t sv_gravity, sv_cheats, sv_maxspeed, skill;
extern cvar_t host_mapname;
#endif
#ifdef TEXTEDITOR
extern cvar_t debugger;
#endif
int y;
menu_t *menu = M_Options_Title(&y, sizeof(*info));
info = menu->data;
@ -1765,6 +1768,9 @@ void M_Menu_Singleplayer_Cheats_f (void)
info->mapcombo = MC_AddCombo(menu,16, y, " Map", mapoptions_q1, currentmap); y+=8;
MC_AddCheckBox(menu, 16, y, " Cheats", &sv_cheats,0); y+=8;
#endif
#ifdef TEXTEDITOR
MC_AddCheckBox(menu, 16, y, " Debugger", &debugger, 0); y+=8;
#endif
MC_AddConsoleCommand(menu, 16, y, " Toggle Godmode", "god\n"); y+=8;
MC_AddConsoleCommand(menu, 16, y, " Toggle Flymode", "fly\n"); y+=8;
MC_AddConsoleCommand(menu, 16, y, " Toggle Noclip", "noclip\n"); y+=8;

View file

@ -385,6 +385,7 @@ void M_DrawScalePic (int x, int y, int w, int h, mpic_t *pic);
void M_FindKeysForCommand (int pnum, char *command, int *twokeys);
void M_UnbindCommand (char *command);
void MP_CvarChanged(cvar_t *var);
qboolean MP_Init (void);
void MP_Shutdown (void);
qboolean MP_Toggle(void);

View file

@ -1915,6 +1915,12 @@ static void P_LoadParticleSet(char *name, qboolean first)
}
}
if (!strcmp(name, "effectinfo"))
{
P_ImportEffectInfo_f();
return;
}
FS_LoadFile(va("particles/%s.cfg", name), (void**)&file);
if (!file)

View file

@ -25,7 +25,7 @@
#include "pr_common.h"
#ifdef CLIENTONLY
#ifndef TEXTEDITOR
//client only builds don't have a qc debugger
#define QCEditor NULL
#endif
@ -59,6 +59,8 @@ cvar_t pr_csmaxedicts = CVAR("pr_csmaxedicts", "3072"); //not tied to protocol n
cvar_t cl_csqcdebug = CVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...)
cvar_t cl_nocsqc = CVAR("cl_nocsqc", "0");
cvar_t pr_csqc_coreonerror = CVAR("pr_csqc_coreonerror", "1");
extern cvar_t dpcompat_stats;
cvar_t dpcompat_corruptglobals = CVAR("dpcompat_corruptglobals", "0");
#define MASK_DELTA 1
@ -140,6 +142,7 @@ typedef enum
globalfunction(input_event, "CSQC_InputEvent"); \
globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \
globalfunction(console_command, "CSQC_ConsoleCommand"); \
globalfunction(gamecommand, "GameCommand"); /*DP extension*/\
\
globalfunction(ent_update, "CSQC_Ent_Update"); \
globalfunction(ent_remove, "CSQC_Ent_Remove"); \
@ -232,15 +235,29 @@ static void CSQC_ChangeLocalPlayer(int lplayernum)
csqcg.view_angles[1] = cl.viewangles[csqc_lplayernum][1];
csqcg.view_angles[2] = cl.viewangles[csqc_lplayernum][2];
}
if (dpcompat_corruptglobals.ival)
{
if (csqcg.pmove_org)
{
csqcg.pmove_org[0] = cl.simorg[csqc_lplayernum][0];
csqcg.pmove_org[1] = cl.simorg[csqc_lplayernum][1];
csqcg.pmove_org[2] = cl.simorg[csqc_lplayernum][2];
}
if (csqcg.input_angles)
{
csqcg.input_angles[0] = cl.viewangles[csqc_lplayernum][0];
csqcg.input_angles[1] = cl.viewangles[csqc_lplayernum][1];
csqcg.input_angles[2] = cl.viewangles[csqc_lplayernum][2];
}
}
}
static void CSQC_FindGlobals(void)
{
#define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0);
#define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0);
#define globalentity(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0);
#define globalstring(name,qcname) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, qcname, 0);
#define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalentity(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalstring(name,qcname) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalfunction(name,qcname) csqcg.name = PR_FindFunction(csqcprogs,qcname,PR_ANY);
csqcglobals
@ -262,6 +279,16 @@ static void CSQC_FindGlobals(void)
*csqcg.maxclients = cl.allocated_client_slots;
}
static void QCBUILTIN PF_cs_gettime (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int timer = G_FLOAT(OFS_PARM0);
switch(timer)
{
default:
G_FLOAT(OFS_RETURN) = cl.time;
break;
}
}
//this is the list for all the csqc fields.
@ -1078,126 +1105,6 @@ static void QCBUILTIN PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s
csqc_drawsbar = false;
}
static void QCBUILTIN PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
viewflags parametertype = G_FLOAT(OFS_PARM0);
float *p = G_VECTOR(OFS_PARM1);
csqc_rebuildmatricies = true;
G_FLOAT(OFS_RETURN) = 1;
switch(parametertype)
{
case VF_FOV:
r_refdef.fov_x = p[0];
r_refdef.fov_y = p[1];
break;
case VF_FOVX:
r_refdef.fov_x = *p;
break;
case VF_FOVY:
r_refdef.fov_y = *p;
break;
case VF_AFOV:
{
float frustumx, frustumy;
frustumy = tan(p[0] * (M_PI/360)) * 0.75;
if (*prinst->callargc > 2)
frustumy *= G_FLOAT(OFS_PARM2);
frustumx = frustumy * vid.width / vid.height /* / vid.pixelheight*/;
r_refdef.fov_x = atan2(frustumx, 1) * (360/M_PI);
r_refdef.fov_y = atan2(frustumy, 1) * (360/M_PI);
}
break;
case VF_ORIGIN:
VectorCopy(p, r_refdef.vieworg);
cl.crouch[csqc_lplayernum] = 0;
break;
case VF_ORIGIN_Z:
cl.crouch[csqc_lplayernum] = 0;
case VF_ORIGIN_X:
case VF_ORIGIN_Y:
r_refdef.vieworg[parametertype-VF_ORIGIN_X] = *p;
break;
case VF_ANGLES:
VectorCopy(p, r_refdef.viewangles);
break;
case VF_ANGLES_X:
case VF_ANGLES_Y:
case VF_ANGLES_Z:
r_refdef.viewangles[parametertype-VF_ANGLES_X] = *p;
break;
case VF_CL_VIEWANGLES_V:
VectorCopy(p, cl.viewangles[csqc_lplayernum]);
break;
case VF_CL_VIEWANGLES_X:
case VF_CL_VIEWANGLES_Y:
case VF_CL_VIEWANGLES_Z:
cl.viewangles[csqc_lplayernum][parametertype-VF_CL_VIEWANGLES_X] = *p;
break;
case VF_CARTESIAN_ANGLES:
Con_Printf(CON_WARNING "WARNING: CARTESIAN ANGLES ARE NOT YET SUPPORTED!\n");
break;
case VF_VIEWPORT:
r_refdef.vrect.x = p[0];
r_refdef.vrect.y = p[1];
p+=3;
r_refdef.vrect.width = p[0];
r_refdef.vrect.height = p[1];
break;
case VF_SIZE_X:
r_refdef.vrect.width = *p;
break;
case VF_SIZE_Y:
r_refdef.vrect.height = *p;
break;
case VF_SIZE:
r_refdef.vrect.width = p[0];
r_refdef.vrect.height = p[1];
break;
case VF_MIN_X:
r_refdef.vrect.x = *p;
break;
case VF_MIN_Y:
r_refdef.vrect.y = *p;
break;
case VF_MIN:
r_refdef.vrect.x = p[0];
r_refdef.vrect.y = p[1];
break;
case VF_DRAWWORLD:
r_refdef.flags = (r_refdef.flags&~Q2RDF_NOWORLDMODEL) | (*p?0:Q2RDF_NOWORLDMODEL);
break;
case VF_ENGINESBAR:
csqc_drawsbar = *p;
break;
case VF_DRAWCROSSHAIR:
csqc_addcrosshair = *p;
break;
case VF_PERSPECTIVE:
r_refdef.useperspective = *p;
break;
default:
Con_DPrintf("SetViewFlag: %i not recognised\n", parametertype);
G_FLOAT(OFS_RETURN) = 0;
break;
}
}
static void QCBUILTIN PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
viewflags parametertype = G_FLOAT(OFS_PARM0);
@ -1316,6 +1223,133 @@ static void QCBUILTIN PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s
}
}
static void QCBUILTIN PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
viewflags parametertype = G_FLOAT(OFS_PARM0);
float *p = G_VECTOR(OFS_PARM1);
if (*prinst->callargc < 2)
{
csqc_deprecated("PF_R_SetViewFlag called with wrong argument count\n");
PF_R_GetViewFlag(prinst, pr_globals);
return;
}
csqc_rebuildmatricies = true;
G_FLOAT(OFS_RETURN) = 1;
switch(parametertype)
{
case VF_FOV:
r_refdef.fov_x = p[0];
r_refdef.fov_y = p[1];
break;
case VF_FOVX:
r_refdef.fov_x = *p;
break;
case VF_FOVY:
r_refdef.fov_y = *p;
break;
case VF_AFOV:
{
float frustumx, frustumy;
frustumy = tan(p[0] * (M_PI/360)) * 0.75;
if (*prinst->callargc > 2)
frustumy *= G_FLOAT(OFS_PARM2);
frustumx = frustumy * vid.width / vid.height /* / vid.pixelheight*/;
r_refdef.fov_x = atan2(frustumx, 1) * (360/M_PI);
r_refdef.fov_y = atan2(frustumy, 1) * (360/M_PI);
}
break;
case VF_ORIGIN:
VectorCopy(p, r_refdef.vieworg);
cl.crouch[csqc_lplayernum] = 0;
break;
case VF_ORIGIN_Z:
cl.crouch[csqc_lplayernum] = 0;
case VF_ORIGIN_X:
case VF_ORIGIN_Y:
r_refdef.vieworg[parametertype-VF_ORIGIN_X] = *p;
break;
case VF_ANGLES:
VectorCopy(p, r_refdef.viewangles);
break;
case VF_ANGLES_X:
case VF_ANGLES_Y:
case VF_ANGLES_Z:
r_refdef.viewangles[parametertype-VF_ANGLES_X] = *p;
break;
case VF_CL_VIEWANGLES_V:
VectorCopy(p, cl.viewangles[csqc_lplayernum]);
break;
case VF_CL_VIEWANGLES_X:
case VF_CL_VIEWANGLES_Y:
case VF_CL_VIEWANGLES_Z:
cl.viewangles[csqc_lplayernum][parametertype-VF_CL_VIEWANGLES_X] = *p;
break;
case VF_CARTESIAN_ANGLES:
Con_Printf(CON_WARNING "WARNING: CARTESIAN ANGLES ARE NOT YET SUPPORTED!\n");
break;
case VF_VIEWPORT:
r_refdef.vrect.x = p[0];
r_refdef.vrect.y = p[1];
p+=3;
r_refdef.vrect.width = p[0];
r_refdef.vrect.height = p[1];
break;
case VF_SIZE_X:
r_refdef.vrect.width = *p;
break;
case VF_SIZE_Y:
r_refdef.vrect.height = *p;
break;
case VF_SIZE:
r_refdef.vrect.width = p[0];
r_refdef.vrect.height = p[1];
break;
case VF_MIN_X:
r_refdef.vrect.x = *p;
break;
case VF_MIN_Y:
r_refdef.vrect.y = *p;
break;
case VF_MIN:
r_refdef.vrect.x = p[0];
r_refdef.vrect.y = p[1];
break;
case VF_DRAWWORLD:
r_refdef.flags = (r_refdef.flags&~Q2RDF_NOWORLDMODEL) | (*p?0:Q2RDF_NOWORLDMODEL);
break;
case VF_ENGINESBAR:
csqc_drawsbar = *p;
break;
case VF_DRAWCROSSHAIR:
csqc_addcrosshair = *p;
break;
case VF_PERSPECTIVE:
r_refdef.useperspective = *p;
break;
default:
Con_DPrintf("SetViewFlag: %i not recognised\n", parametertype);
G_FLOAT(OFS_RETURN) = 0;
break;
}
}
static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (cl.worldmodel)
@ -1354,11 +1388,10 @@ static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s
R2D_DrawCrosshair();
}
static void QCBUILTIN PF_cs_getstatf(progfuncs_t *prinst, struct globalvars_s *pr_globals)
static void QCBUILTIN PF_cs_getstati(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int stnum = G_FLOAT(OFS_PARM0);
float val = cl.statsf[csqc_lplayernum][stnum]; //copy float into the stat
G_FLOAT(OFS_RETURN) = val;
G_INT(OFS_RETURN) = cl.stats[csqc_lplayernum][stnum];
}
static void QCBUILTIN PF_cs_getstatbits(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //convert an int stat into a qc float.
@ -1376,7 +1409,7 @@ static void QCBUILTIN PF_cs_getstatbits(progfuncs_t *prinst, struct globalvars_s
G_FLOAT(OFS_RETURN) = (((unsigned int)val)&(((1<<count)-1)<<first))>>first;
}
else
G_FLOAT(OFS_RETURN) = val;
G_FLOAT(OFS_RETURN) = cl.statsf[csqc_lplayernum][stnum];
}
static void QCBUILTIN PF_cs_getstats(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -1865,8 +1898,10 @@ static void QCBUILTIN PF_cs_trailparticles (progfuncs_t *prinst, struct globalva
if (csqc_isdarkplaces)
{
efnum = G_FLOAT(OFS_PARM1)-1;
efnum = G_FLOAT(OFS_PARM1);
ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
efnum = pe->FindParticleType(COM_Effectinfo_ForNumber(efnum));
}
else
{
@ -1884,11 +1919,16 @@ static void QCBUILTIN PF_cs_particleeffectnum (progfuncs_t *prinst, struct globa
{
char *effectname = PR_GetStringOfs(prinst, OFS_PARM0);
if (csqc_isdarkplaces)
{
//keep the effectinfo synced between server and client.
COM_Effectinfo_ForName(effectname);
G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(effectname);
}
else
{
G_FLOAT(OFS_RETURN) = pe->FindParticleType(effectname)+1;
}
}
static void QCBUILTIN PF_cs_sendevent (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2234,6 +2274,11 @@ static void QCBUILTIN PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars
if (pnum < 0 || pnum >= cl.allocated_client_slots)
ret = "";
else if (!strcmp(keyname, "viewentity")) //compat with DP. Yes, I know this is in the wrong place.
{
ret = buffer;
sprintf(ret, "%i", pnum+1);
}
else if (!*cl.players[pnum].userinfo)
ret = ""; //player isn't on the server.
else if (!strcmp(keyname, "ping"))
@ -2260,11 +2305,6 @@ static void QCBUILTIN PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars
ret = buffer;
sprintf(ret, "%i", (int)cl.players[pnum].entertime);
}
else if (!strcmp(keyname, "viewentity")) //compat with DP
{
ret = buffer;
sprintf(ret, "%i", pnum+1);
}
#ifdef VOICECHAT
else if (!strcmp(keyname, "voipspeaking"))
{
@ -2998,10 +3038,16 @@ void CSQC_RunThreads(void)
static void QCBUILTIN PF_cs_addprogs (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s = PR_GetStringOfs(prinst, OFS_PARM0);
int newp;
if (!s || !*s)
G_FLOAT(OFS_RETURN) = -1;
newp = -1;
else
G_FLOAT(OFS_RETURN) = PR_LoadProgs(prinst, s, 0, NULL, 0);
{
newp = PR_LoadProgs(prinst, s, 0, NULL, 0);
if (newp >= 0)
PR_AutoCvarSetup(csqcprogs);
}
G_FLOAT(OFS_RETURN) = newp;
}
static void QCBUILTIN PF_cs_OpenPortal (progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -4057,6 +4103,8 @@ void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent)
ent->v->skin = srcp->skinnum;
CSQC_LerpStateToCSQC(&cl.lerpplayers[pnum], ent, true);
ent->xv->lerpfrac = 1-(ent->xv->frame1time) / cl.lerpplayers[pnum].framelerpdeltatime;
ent->xv->lerpfrac = bound(0, ent->xv->lerpfrac, 1);
VectorCopy(srcp->origin, ent->v->origin);
@ -4065,7 +4113,7 @@ void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent)
VectorCopy(srcp->velocity, ent->v->velocity);
ent->v->angles[0] *= -0.333;
ent->v->colormap = pnum+1;
ent->xv->scale = srcp->scale/16.0f;
ent->xv->scale = srcp->scale;
//ent->v->fatness = srcp->fatness;
ent->xv->alpha = srcp->alpha/255.0f;
@ -4122,6 +4170,7 @@ qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state)
ent = (csqcedict_t *)ED_Alloc(csqcprogs);
CSQC_PlayerStateToCSQC(playernum, state, ent);
ent->xv->drawmask = MASK_DELTA;
*csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent);
@ -4443,6 +4492,19 @@ static void QCBUILTIN PF_ReadServerEntityState(progfuncs_t *prinst, struct globa
}
#endif
static void QCBUILTIN PF_cs_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int action = G_FLOAT(OFS_PARM0);
float *pos = G_VECTOR(OFS_PARM1);
float radius = G_FLOAT(OFS_PARM2);
float quant = G_FLOAT(OFS_PARM3);
#if defined(TERRAIN)
G_FLOAT(OFS_RETURN) = Heightmap_Edit(csqc_world.worldmodel, action, pos, radius, quant);
#else
G_FLOAT(OFS_RETURN) = false;
#endif
}
#define PF_FixTen PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme
//prefixes:
@ -4636,6 +4698,24 @@ static struct {
{"shaderforname", PF_shaderforname, 238}, // #238
{"te_bloodqw", PF_cl_te_bloodqw, 239}, // #239 void te_bloodqw(vector org[, float count]) (FTE_TE_STANDARDEFFECTBUILTINS)
// {"checkpvs", PF_checkpvs, 240},
// {"matchclientname", PF_matchclient, 241},
{"sendpacket", PF_NoCSQC, 242}, //void(string dest, string content) sendpacket = #242; (FTE_QC_SENDPACKET)
// {"bulleten", PF_bulleten, 243}, (removed builtin)
#ifdef SQL
{"sqlconnect", PF_NoCSQC, 250}, // #250 float([string host], [string user], [string pass], [string defaultdb], [string driver]) sqlconnect (FTE_SQL)
{"sqldisconnect", PF_NoCSQC, 251}, // #251 void(float serveridx) sqldisconnect (FTE_SQL)
{"sqlopenquery", PF_NoCSQC, 252}, // #252 float(float serveridx, void(float serveridx, float queryidx, float rows, float columns, float eof) callback, float querytype, string query) sqlopenquery (FTE_SQL)
{"sqlclosequery", PF_NoCSQC, 253}, // #253 void(float serveridx, float queryidx) sqlclosequery (FTE_SQL)
{"sqlreadfield", PF_NoCSQC, 254}, // #254 string(float serveridx, float queryidx, float row, float column) sqlreadfield (FTE_SQL)
{"sqlerror", PF_NoCSQC, 255}, // #255 string(float serveridx, [float queryidx]) sqlerror (FTE_SQL)
{"sqlescape", PF_NoCSQC, 256}, // #256 string(float serveridx, string data) sqlescape (FTE_SQL)
{"sqlversion", PF_NoCSQC, 257}, // #257 string(float serveridx) sqlversion (FTE_SQL)
{"sqlreadfloat", PF_NoCSQC, 258}, // #258 float(float serveridx, float queryidx, float row, float column) sqlreadfloat (FTE_SQL)
#endif
{"stoi", PF_stoi, 259},
{"itos", PF_itos, 260},
{"stoh", PF_stoh, 261},
@ -4657,6 +4737,7 @@ static struct {
{"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS)
{"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS)
{"terrain_edit", PF_cs_terrain_edit, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??)
//300
{"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC)
{"addentities", PF_R_AddEntityMask, 301}, // #301 void(float mask) addentities (EXT_CSQC)
@ -4701,7 +4782,7 @@ static struct {
// {"?", PF_Fixme, 329}, // #329 EXT_CSQC_'DARKPLACES'
//330
{"getstatf", PF_cs_getstatf, 330}, // #330 float(float stnum) getstatf (EXT_CSQC)
{"getstati", PF_cs_getstati, 330}, // #330 float(float stnum) getstati (EXT_CSQC)
{"getstatbits", PF_cs_getstatbits, 331}, // #331 float(float stnum) getstatbits (EXT_CSQC)
{"getstats", PF_cs_getstats, 332}, // #332 string(float firststnum) getstats (EXT_CSQC)
{"setmodelindex", PF_cs_SetModelIndex, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
@ -4720,7 +4801,7 @@ static struct {
{"getkeybind", PF_cl_getkeybind, 342}, // #342 string(float keynum) getkeybind (EXT_CSQC)
// {"?", PF_Fixme, 343}, // #343
// {"?", PF_Fixme, 344}, // #344
{"getmousepos", PF_cl_getmousepos, 344}, // #344 This is a DP extension
{"getinputstate", PF_cs_getinputstate, 345}, // #345 float(float framenum) getinputstate (EXT_CSQC)
{"setsensitivityscaler", PF_cs_setsensativityscaler, 346}, // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
@ -4942,13 +5023,17 @@ static struct {
{"buf_cvarlist", PF_buf_cvarlist, 517},
{"cvar_description", PF_cvar_description, 518},
{"gettime", PF_cs_gettime, 519},
{"keynumtostring", PF_cl_keynumtostring, 520},
{"findkeysforcommand", PF_cl_findkeysforcommand, 521},
{"sprintf", PF_sprintf, 627},
{NULL}
};
static builtin_t pr_builtin[550];
static builtin_t csqc_builtin[800];
@ -5048,6 +5133,9 @@ void CSQC_Shutdown(void)
CSQC_ForgetThreads();
CloseProgs(csqcprogs);
}
#ifdef TEXTEDITOR
Editor_ProgsKilled(csqcprogs);
#endif
csqcprogs = NULL;
#ifdef USEODE
@ -5202,12 +5290,12 @@ qboolean CSQC_Init (unsigned int checksum)
if (cl_nocsqc.value)
return false;
for (i = 0; i < sizeof(pr_builtin)/sizeof(pr_builtin[0]); i++)
pr_builtin[i] = PF_Fixme;
for (i = 0; i < sizeof(csqc_builtin)/sizeof(csqc_builtin[0]); i++)
csqc_builtin[i] = PF_Fixme;
for (i = 0; BuiltinList[i].bifunc; i++)
{
if (BuiltinList[i].ebfsnum)
pr_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc;
csqc_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc;
}
csqc_deprecated_warned = false;
@ -5239,8 +5327,8 @@ qboolean CSQC_Init (unsigned int checksum)
csqcprogparms.memfree = PR_CB_Free;//void (*memfree) (void * mem);
csqcprogparms.globalbuiltins = pr_builtin;//builtin_t *globalbuiltins; //these are available to all progs
csqcprogparms.numglobalbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
csqcprogparms.globalbuiltins = csqc_builtin;//builtin_t *globalbuiltins; //these are available to all progs
csqcprogparms.numglobalbuiltins = sizeof(csqc_builtin)/sizeof(csqc_builtin[0]);
csqcprogparms.autocompile = PR_COMPILEIGNORE;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile;
@ -5289,6 +5377,7 @@ qboolean CSQC_Init (unsigned int checksum)
return false;
}
PR_AutoCvarSetup(csqcprogs);
PF_InitTempStrings(csqcprogs);
@ -5307,11 +5396,12 @@ qboolean CSQC_Init (unsigned int checksum)
worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0);
worldent->isfree = false;
/*DP compat*/
str = (string_t*)csqcprogs->GetEdictFieldValue(csqcprogs, (edict_t*)worldent, "message", NULL);
if (str)
*str = PR_SetString(csqcprogs, cl.levelname);
str = (string_t*)PR_FindGlobal(csqcprogs, "mapname", 0);
str = (string_t*)PR_FindGlobal(csqcprogs, "mapname", 0, NULL);
if (str)
{
char *s = Info_ValueForKey(cl.serverinfo, "map");
@ -5400,14 +5490,14 @@ void PR_CSExtensionList_f(void)
showflags = SHOW_ACTIVEEXT|SHOW_NOTACTIVEEXT;
//make sure the info is valid
if (!pr_builtin[0])
if (!csqc_builtin[0])
{
for (i = 0; i < sizeof(pr_builtin)/sizeof(pr_builtin[0]); i++)
pr_builtin[i] = PF_Fixme;
for (i = 0; i < sizeof(csqc_builtin)/sizeof(csqc_builtin[0]); i++)
csqc_builtin[i] = PF_Fixme;
for (i = 0; BuiltinList[i].bifunc; i++)
{
if (BuiltinList[i].ebfsnum)
pr_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc;
csqc_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc;
}
}
@ -5419,7 +5509,7 @@ void PR_CSExtensionList_f(void)
continue; //a reserved builtin.
if (BuiltinList[i].bifunc == PF_Fixme)
Con_Printf("^1%s:%i needs to be added\n", BuiltinList[i].name, BuiltinList[i].ebfsnum);
else if (pr_builtin[BuiltinList[i].ebfsnum] == BuiltinList[i].bifunc)
else if (csqc_builtin[BuiltinList[i].ebfsnum] == BuiltinList[i].bifunc)
{
if (showflags & SHOW_ACTIVEBI)
Con_Printf("%s is active on %i\n", BuiltinList[i].name, BuiltinList[i].ebfsnum);
@ -5464,9 +5554,9 @@ void PR_CSExtensionList_f(void)
Con_Printf("^4%s is not supported\n", extlist[i].name);
break;
}
if (pr_builtin[BuiltinList[bi].ebfsnum] != BuiltinList[bi].bifunc)
if (csqc_builtin[BuiltinList[bi].ebfsnum] != BuiltinList[bi].bifunc)
{
if (pr_builtin[BuiltinList[bi].ebfsnum] == PF_Fixme)
if (csqc_builtin[BuiltinList[bi].ebfsnum] == PF_Fixme)
{
if (showflags & SHOW_NOTACTIVEEXT)
Con_Printf("^4%s is not currently active (builtin: %s#%i)\n", extlist[i].name, BuiltinList[bi].name, BuiltinList[bi].ebfsnum);
@ -5493,18 +5583,53 @@ void PR_CSExtensionList_f(void)
}
}
void CSQC_Breakpoint_f(void)
{
int wasset;
int isset;
char *filename = Cmd_Argv(1);
int line = atoi(Cmd_Argv(2));
if (!csqcprogs)
{
Con_Printf("CSQC not running\n");
return;
}
wasset = svprogfuncs->ToggleBreak(csqcprogs, filename, line, 3);
isset = svprogfuncs->ToggleBreak(csqcprogs, filename, line, 2);
if (wasset == isset)
Con_Printf("Breakpoint was not valid\n");
else if (isset)
Con_Printf("Breakpoint has been set\n");
else
Con_Printf("Breakpoint has been cleared\n");
}
static void CSQC_GameCommand_f(void);
void CSQC_RegisterCvarsAndThings(void)
{
PF_Common_RegisterCvars();
Cmd_AddCommand("coredump_csqc", CSQC_CoreDump);
Cmd_AddCommand ("extensionlist_csqc", PR_CSExtensionList_f);
Cmd_AddCommand("cl_cmd", CSQC_GameCommand_f);
Cmd_AddCommand("breakpoint_csqc", CSQC_Breakpoint_f);
Cvar_Register(&pr_csmaxedicts, CSQCPROGSGROUP);
Cvar_Register(&cl_csqcdebug, CSQCPROGSGROUP);
Cvar_Register(&cl_nocsqc, CSQCPROGSGROUP);
Cvar_Register(&pr_csqc_coreonerror, CSQCPROGSGROUP);
Cvar_Register(&dpcompat_corruptglobals, CSQCPROGSGROUP);
}
void CSQC_CvarChanged(cvar_t *var)
{
if (csqcprogs)
{
PR_AutoCvar(csqcprogs, var);
}
}
qboolean CSQC_DrawView(void)
@ -5626,6 +5751,17 @@ qboolean CSQC_ConsoleCommand(char *cmd)
PR_ExecuteProgram (csqcprogs, csqcg.console_command);
return G_FLOAT(OFS_RETURN);
}
static void CSQC_GameCommand_f(void)
{
void *pr_globals;
if (!csqcprogs || !csqcg.gamecommand)
return;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, Cmd_Args()));
PR_ExecuteProgram (csqcprogs, csqcg.gamecommand);
}
#pragma message("do we really need the firstbyte parameter here?")
qboolean CSQC_ParseTempEntity(unsigned char firstbyte)
@ -5643,9 +5779,27 @@ qboolean CSQC_ParseTempEntity(unsigned char firstbyte)
qboolean CSQC_ParseGamePacket(void)
{
int len = (unsigned short)MSG_ReadShort();
int start = msg_readcount;
void *pr_globals;
if (!csqcprogs || !csqcg.parse_tempentity)
{
MSG_ReadSkip(len);
return false;
}
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
PR_ExecuteProgram (csqcprogs, csqcg.parse_tempentity);
if (msg_readcount != start + len)
{
Con_Printf("Gamecode misread a gamecode packet (%i bytes too much)\n", msg_readcount - (start+len));
msg_readcount = start + len;
}
return true;
}
qboolean CSQC_LoadResource(char *resname, char *restype)
{
void *pr_globals;

View file

@ -9,6 +9,13 @@
#if defined(MENU_DAT) || defined(CSQC_DAT)
struct
{
float *drawfont;
float *drawfontscale;
} mp_globs;
int MP_TranslateFTEtoDPCodes(int code)
{
switch(code)
@ -343,12 +350,30 @@ void QCBUILTIN PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_
float *pos = G_VECTOR(OFS_PARM0);
char *text = PR_GetStringOfs(prinst, OFS_PARM1);
float *size = G_VECTOR(OFS_PARM2);
float alpha = G_FLOAT(OFS_PARM3);
// float flag = G_FLOAT(OFS_PARM4);
float alpha = 0;
float flag = 0;
float r, g, b;
conchar_t buffer[2048], *str;
float px, py;
if (*prinst->callargc >= 6)
{
r = G_FLOAT(OFS_PARM3 + 0);
g = G_FLOAT(OFS_PARM3 + 1);
b = G_FLOAT(OFS_PARM3 + 2);
alpha = G_FLOAT(OFS_PARM4);
flag = G_FLOAT(OFS_PARM5);
}
else
{
r = 1;
g = 1;
b = 1;
alpha = G_FLOAT(OFS_PARM3);
flag = G_FLOAT(OFS_PARM4);
}
if (!text)
{
G_FLOAT(OFS_RETURN) = -1; //was null..
@ -359,7 +384,7 @@ void QCBUILTIN PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_
str = buffer;
Font_BeginScaledString(font_conchar, pos[0], pos[1], &px, &py);
Font_ForceColour(1, 1, 1, alpha);
Font_ForceColour(r, g, b, alpha);
while(*str)
{
px = Font_DrawScaleChar(px, py, size[0], size[1], *str++);
@ -377,9 +402,26 @@ void QCBUILTIN PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_gl
fontsize = G_FLOAT(OFS_PARM2);
else
fontsize = 1;
if (mp_globs.drawfontscale)
fontsize *= mp_globs.drawfontscale[1];
if (usecolours)
{
G_FLOAT(OFS_RETURN) = COM_FunStringLength(text)*fontsize;
conchar_t buffer[2048], *str;
float px, py;
COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), false);
str = buffer;
Font_BeginScaledString(font_conchar, 0, 0, &px, &py);
while(*str)
{
px += Font_CharWidth(*str++);
}
Font_EndString(font_conchar);
if (mp_globs.drawfontscale)
px *= mp_globs.drawfontscale[1];
G_FLOAT(OFS_RETURN) = px;
}
else
{
@ -534,7 +576,7 @@ void QCBUILTIN PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr
Font_BeginScaledString(font_conchar, pos[0], pos[1], &x, &y);
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK | 0xe000|(chara&0xff));
Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK | /*0xe000|*/(chara&0xff));
Font_InvalidateColour();
Font_EndString(font_conchar);
@ -561,9 +603,15 @@ void QCBUILTIN PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr
x = pos[0];
y = pos[1];
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
if (mp_globs.drawfontscale)
{
size[0] *= mp_globs.drawfontscale[0];
size[1] *= mp_globs.drawfontscale[1];
}
while(*text)
{
x = Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK|0xe000|(*text++&0xff));
x = Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK|/*0xe000|*/(*text++&0xff));
}
Font_InvalidateColour();
Font_EndString(font_conchar);
@ -602,9 +650,6 @@ void QCBUILTIN PF_CL_drawgetimagesize (progfuncs_t *prinst, struct globalvars_s
float *ret = G_VECTOR(OFS_RETURN);
if (!p)
p = R2D_SafeCachePic(va("%s.tga", picname));
if (p)
{
ret[0] = p->width;
@ -743,7 +788,15 @@ void QCBUILTIN PF_parseentitydata(progfuncs_t *prinst, struct globalvars_s *pr_g
void QCBUILTIN PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
G_FLOAT(OFS_RETURN) = (float)(((int)G_FLOAT(OFS_PARM0))%((int)G_FLOAT(OFS_PARM1)));
int a = G_FLOAT(OFS_PARM0);
int b = G_FLOAT(OFS_PARM1);
if (b == 0)
{
Con_Printf("mod by zero\n");
G_FLOAT(OFS_RETURN) = 0;
}
else
G_FLOAT(OFS_RETURN) = a % b;
}
char *RemapCvarNameFromDPToFTE(char *name)
@ -836,7 +889,7 @@ void QCBUILTIN PF_nonfatalobjerror (progfuncs_t *prinst, struct globalvars_s *pr
PR_StackTrace(prinst);
selfp = PR_FindGlobal(prinst, "self", PR_CURRENT);
selfp = PR_FindGlobal(prinst, "self", PR_CURRENT, NULL);
if (selfp && selfp->_int)
{
ed = PROG_TO_EDICT(prinst, selfp->_int);
@ -970,7 +1023,7 @@ void QCBUILTIN PF_cl_getmousetarget (progfuncs_t *prinst, struct globalvars_s *p
}
//vector getmousepos(void) = #66;
void QCBUILTIN QCBUILTIN PF_cl_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_cl_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *ret = G_VECTOR(OFS_RETURN);
extern int mousemove_x, mousemove_y;
@ -1608,7 +1661,7 @@ builtin_t menu_builtins[] = {
PF_cin_getstate, // #464
PF_cin_restart, // #465
PF_drawline, // #466
PF_drawcolorcodedstring, // #467
PF_CL_drawcolouredstring, // #467
PF_CL_stringwidth, // #468
PF_CL_drawsubpic, // #469
@ -1705,7 +1758,21 @@ builtin_t menu_builtins[] = {
PF_M_gethostcacheindexforkey,
PF_M_addwantedhostcachekey,
PF_M_getextresponse, // #624
PF_netaddress_resolve
PF_netaddress_resolve,
skip1 /*get gamedir info*/
PF_sprintf, /*sprintf*/
skip1 /*not listed in dp*/
skip1 /*not listed in dp*/
skip1 /*setkeybind*/
skip1 /*getbindmaps*/
skip1 /*setbindmaps*/
skip1 /*crypto*/
skip1 /*crypto*/
skip1 /*crypto*/
skip1 /*crypto*/
skip1 /*crypto #637*/
};
int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]);
@ -1757,6 +1824,9 @@ void MP_Shutdown (void)
search_close_progs(menuprogs, true);
CloseProgs(menuprogs);
#ifdef TEXTEDITOR
Editor_ProgsKilled(menuprogs);
#endif
menuprogs = NULL;
key_dest = key_game;
@ -1800,6 +1870,14 @@ void VARGS Menu_Abort (char *format, ...)
MP_Shutdown();
}
void MP_CvarChanged(cvar_t *var)
{
if (svprogfuncs)
{
PR_AutoCvar(svprogfuncs, var);
}
}
double menutime;
qboolean MP_Init (void)
{
@ -1875,10 +1953,14 @@ qboolean MP_Init (void)
PF_InitTempStrings(menuprogs);
mp_time = (float*)PR_FindGlobal(menuprogs, "time", 0);
mp_time = (float*)PR_FindGlobal(menuprogs, "time", 0, NULL);
if (mp_time)
*mp_time = Sys_DoubleTime();
#pragma message("disabled until csqc gets forked or some such")
//mp_globs.drawfont = (float*)PR_FindGlobal(menuprogs, "drawfont", 0, NULL);
//mp_globs.drawfontscale = (float*)PR_FindGlobal(menuprogs, "drawfontscale", 0, NULL);
menuentsize = PR_InitEnts(menuprogs, 8192);
@ -1923,7 +2005,7 @@ void MP_CoreDump_f(void)
void MP_Reload_f(void)
{
MP_Shutdown();
M_Init();
MP_Init();
}
void MP_RegisterCvarsAndCmds(void)

View file

@ -111,9 +111,10 @@ void R2D_Init(void)
draw_backtile = R_RegisterShader("gfx/backtile.lmp",
"{\n"
#ifdef USE_EGL
"if $nofixed\n"
"[\n"
"program default2d\n"
#endif
"]\n"
"nomipmaps\n"
"{\n"
"map $diffuse\n"
@ -219,9 +220,10 @@ void R2D_Init(void)
);
shader_crosshair = R_RegisterShader("crosshairshader",
"{\n"
#ifdef USE_EGL
"if $nofixed\n"
"[\n"
"program default2d\n"
#endif
"]\n"
"nomipmaps\n"
"{\n"
"map $diffuse\n"
@ -257,9 +259,9 @@ mpic_t *R2D_SafeCachePic (char *path)
if (!qrenderer)
return NULL;
s = R_RegisterPic(path);
if (s->width)
return s;
if (s->flags & SHADER_NOIMAGE)
return NULL;
return s;
}
@ -270,7 +272,7 @@ mpic_t *R2D_SafePicFromWad (char *name)
shader_t *s;
snprintf(newname, sizeof(newname), "gfx/%s.lmp", name);
s = R_RegisterPic(newname);
if (s->width)
if (!(s->flags & SHADER_NOIMAGE))
return s;
failedpic = name;
return NULL;
@ -400,9 +402,10 @@ void R2D_TransPicTranslate (int x, int y, int width, int height, qbyte *pic, qby
{
translate_texture = R_AllocNewTexture(64, 64);
translate_shader = R_RegisterShader("translatedpic", "{\n"
#ifdef USE_EGL
"if $nofixed\n"
"[\n"
"program default2d\n"
#endif
"]\n"
"nomipmaps\n"
"{\n"
"map $diffuse\n"

View file

@ -2045,11 +2045,6 @@ void Surf_DrawWorld (void)
if (currentmodel->fromgame = fg_doom)
GLR_DoomWorld();
else
#endif
#ifdef TERRAIN
if (currentmodel->type == mod_heightmap)
GL_DrawHeightmapModel(currententity);
else
#endif
{
RSpeedRemark();
@ -2093,6 +2088,13 @@ void Surf_DrawWorld (void)
vis = D3_CalcVis(cl.worldmodel, r_refdef.vieworg);
}
else
#endif
#ifdef TERRAIN
if (currentmodel->type == mod_heightmap)
{
vis = NULL;
}
else
#endif
{
//extern cvar_t temp1;
@ -2179,6 +2181,9 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader)
}
}
if (lightmap[texnum]->external)
lightmap_textures[texnum] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT);
/*not required, but using one lightmap per texture can result in better texture unit switching*/
if (lightmap[texnum]->shader != shader)
continue;
@ -2277,6 +2282,9 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y)
memset(lightmap[i]->lightmaps, 255, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3);
COM_StripExtension(cl.worldmodel->name, basename, sizeof(basename));
if (!lightmap[i]->external)
R_DestroyTexture(lightmap_textures[i]);
lightmap[i]->external = true;
lightmap_textures[i] = R_LoadHiResTexture(va("%s/lm_%04i", basename, i), NULL, IF_NOALPHA|IF_NOGAMMA);
lightmap[i]->modified = false;
}
@ -2445,6 +2453,14 @@ void Surf_DeInit(void)
{
int i;
if (lightmap_textures)
{
for (i = 0; i < numlightmaps; i++)
if (!lightmap[i] || lightmap[i]->external)
R_DestroyTexture(lightmap_textures[i]);
BZ_Free(lightmap_textures);
}
for (i = 0; i < numlightmaps; i++)
{
if (!lightmap[i])
@ -2453,12 +2469,6 @@ void Surf_DeInit(void)
lightmap[i] = NULL;
}
if (lightmap_textures)
{
for (i = 0; i < numlightmaps; i++)
R_DestroyTexture(lightmap_textures[i]);
BZ_Free(lightmap_textures);
}
if (lightmap)
BZ_Free(lightmap);

View file

@ -211,6 +211,7 @@ typedef struct {
struct mesh_s *meshchain;
qboolean modified;
qboolean deluxmodified;
qboolean external;
glRect_t rectchange;
glRect_t deluxrectchange;
int allocated[LMBLOCK_WIDTH];

View file

@ -16,14 +16,15 @@ F11 will step through.
#include "quakedef.h"
#ifdef TEXTEDITOR
cvar_t alloweditor = SCVAR("alloweditor", "1"); //disallow loading editor for stepbystep debugging.
cvar_t editstripcr = SCVAR("edit_stripcr", "1"); //remove \r from eols (on load).
cvar_t editaddcr = SCVAR("edit_addcr", "1"); //make sure that each line ends with a \r (on save).
cvar_t edittabspacing = SCVAR("edit_tabsize", "4");
static cvar_t alloweditor = SCVAR("alloweditor", "1"); //disallow loading editor for stepbystep debugging.
static cvar_t editstripcr = SCVAR("edit_stripcr", "1"); //remove \r from eols (on load).
static cvar_t editaddcr = SCVAR("edit_addcr", "1"); //make sure that each line ends with a \r (on save).
static cvar_t edittabspacing = SCVAR("edit_tabsize", "4");
cvar_t debugger = SCVAR("debugger", "1");
#undef pr_trace
progfuncs_t *editprogfuncs;
static progfuncs_t *editprogfuncs;
typedef struct fileblock_s {
struct fileblock_s *next;
@ -37,7 +38,7 @@ typedef struct fileblock_s {
static fileblock_t *cursorblock, *firstblock, *executionblock, *viewportystartblock;
void *E_Malloc(int size)
static void *E_Malloc(int size)
{
char *mem;
mem = Z_Malloc(size);
@ -45,7 +46,7 @@ void *E_Malloc(int size)
Sys_Error("Failed to allocate enough mem for editor\n");
return mem;
}
void E_Free(void *mem)
static void E_Free(void *mem)
{
Z_Free(mem);
}
@ -53,23 +54,23 @@ void E_Free(void *mem)
#define GETBLOCK(s, ret) ret = (void *)E_Malloc(sizeof(fileblock_t) + s);ret->allocatedlength = s;ret->data = (char *)ret + sizeof(fileblock_t)
char OpenEditorFile[256];
static char OpenEditorFile[256];
qboolean editoractive; //(export)
qboolean editormodal; //doesn't return. (export)
qboolean editorblocking;
qboolean madechanges;
qboolean insertkeyhit=true;
qboolean useeval;
static qboolean editorblocking;
static qboolean madechanges;
static qboolean insertkeyhit=true;
static qboolean useeval;
char evalstring[256];
static char evalstring[256];
int executionlinenum; //step by step debugger
int cursorlinenum, cursorx;
static int executionlinenum; //step by step debugger
static int cursorlinenum, cursorx;
int viewportx;
int viewporty;
static int viewportx;
static int viewporty;
static int VFS_GETC(vfsfile_t *fp)
@ -80,7 +81,7 @@ static int VFS_GETC(vfsfile_t *fp)
}
//newsize = number of chars, EXCLUDING terminator.
void MakeNewSize(fileblock_t *block, int newsize) //this is used to resize a block. It allocates a new one, copys the data frees the old one and links it into the right place
static void MakeNewSize(fileblock_t *block, int newsize) //this is used to resize a block. It allocates a new one, copys the data frees the old one and links it into the right place
//it is called when the user is typing
{
fileblock_t *newblock;
@ -111,8 +112,8 @@ void MakeNewSize(fileblock_t *block, int newsize) //this is used to resize a blo
cursorblock = newblock;
}
int positionacross;
void GetCursorpos(void)
static int positionacross;
static void GetCursorpos(void)
{
int a;
char *s;
@ -131,7 +132,7 @@ void GetCursorpos(void)
}
// positionacross = cursorofs;
}
void SetCursorpos(void)
static void SetCursorpos(void)
{
int a=0;
char *s;
@ -156,7 +157,7 @@ void SetCursorpos(void)
}
void CloseEditor(void)
static void CloseEditor(void)
{
fileblock_t *b;
@ -183,7 +184,7 @@ void CloseEditor(void)
executionlinenum = -1;
}
qboolean EditorSaveFile(char *s) //returns true if succesful
static qboolean EditorSaveFile(char *s) //returns true if succesful
{
// FILE *F;
@ -233,7 +234,7 @@ qboolean EditorSaveFile(char *s) //returns true if succesful
void EditorNewFile()
static void EditorNewFile(void)
{
GETBLOCK(64, firstblock);
GETBLOCK(64, firstblock->next);
@ -251,7 +252,7 @@ void EditorNewFile()
editoractive = true;
}
void EditorOpenFile(char *name)
static void EditorOpenFile(char *name)
{
int i;
char line[8192];
@ -445,10 +446,21 @@ void Editor_Key(int key, int unicode)
break;
case K_CTRL:
break;
case K_MWHEELUP:
case K_UPARROW:
case K_PGUP:
GetCursorpos();
{int a=(vid.height/8)/2;
while(a) {a--;
{
int a;
if (key == K_PGUP)
a =(vid.height/8)/2;
else if (key == K_MWHEELUP)
a = 5;
else
a = 1;
while(a)
{
a--;
if (cursorblock->prev)
{
cursorblock = cursorblock->prev;
@ -458,9 +470,18 @@ void Editor_Key(int key, int unicode)
}
SetCursorpos();
break;
case K_MWHEELDOWN:
case K_DOWNARROW:
case K_PGDN:
GetCursorpos();
{int a=(vid.height/8)/2;
{
int a;
if (key == K_PGDN)
a =(vid.height/8)/2;
else if (key == K_MWHEELDOWN)
a = 5;
else
a = 1;
while(a)
{
a--;
@ -528,7 +549,7 @@ void Editor_Key(int key, int unicode)
int f = 0;
if (editprogfuncs)
{
if (editprogfuncs->ToggleBreak(editprogfuncs, OpenEditorFile+4, cursorlinenum, 2))
if (editprogfuncs->ToggleBreak(editprogfuncs, OpenEditorFile, cursorlinenum, 2))
f |= 1;
else
f |= 2;
@ -536,7 +557,7 @@ void Editor_Key(int key, int unicode)
#ifndef CLIENTONLY
else if (svprogfuncs)
{
if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile+4, cursorlinenum, 2))
if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile, cursorlinenum, 2))
f |= 1;
else
f |= 2;
@ -582,30 +603,6 @@ void Editor_Key(int key, int unicode)
cursorx = cursorblock->datalength;
break;
case K_MWHEELUP:
case K_UPARROW:
GetCursorpos();
if (cursorblock->prev)
{
cursorblock = cursorblock->prev;
cursorlinenum--;
}
SetCursorpos();
break;
case K_MWHEELDOWN:
case K_DOWNARROW:
GetCursorpos();
if (cursorblock->next)
{
cursorblock = cursorblock->next;
cursorlinenum++;
}
SetCursorpos();
break;
case K_BACKSPACE:
cursorx--;
if (cursorx < 0)
@ -738,76 +735,24 @@ void Editor_Key(int key, int unicode)
}
}
void Draw_CursorLine(int ox, int y, fileblock_t *b)
static void Draw_Line(int x, int y, fileblock_t *b, int cursorx)
{
#pragma message("Fixme: ")
/*
int x=0;
qbyte *d = b->data;
int cx;
int a = 0, i;
int colour=COLOR_BLUE;
int ts = edittabspacing.value;
if (ts < 1)
ts = 4;
ts*=8;
if (b->flags & (FB_BREAK))
colour = COLOR_RED; //red
if (executionblock == b)
{
if (colour) //break point too
colour = COLOR_GREEN; //green
else
colour = COLOR_YELLOW; //yellow
}
if (cursorx <= strlen(d)+1 && (int)(Sys_DoubleTime()*4.0) & 1)
cx = -1;
else
cx = cursorx;
for (i = 0; i < b->datalength; i++)
{
if (*d == '\t')
{
if (a == cx)
Draw_ColouredCharacter (x+ox, y, 11|CON_WHITEMASK);
x+=ts;
x-=x%ts;
d++;
a++;
continue;
}
if (x+ox< vid.width)
{
if (a == cx)
Draw_ColouredCharacter (x+ox, y, 11|CON_WHITEMASK);
else
Draw_ColouredCharacter (x+ox, y, (int)*d | (colour<<CON_FGSHIFT));
}
d++;
x += 8;
a++;
}
if (a == cx)
Draw_ColouredCharacter (x+ox, y, 11|CON_WHITEMASK);
*/
}
void Draw_NonCursorLine(int x, int y, fileblock_t *b)
{
#pragma message("Fixme: ")
/*
int nx = 0;
int nx = 0, nnx;
qbyte *d = b->data;
qbyte *c;
int i;
int colour=COLOR_WHITE;
int ts = edittabspacing.value;
if (cursorx >= 0)
c = d + cursorx;
else
c = NULL;
Font_BeginString(font_conchar, x, y, &x, &y);
if (ts < 1)
ts = 4;
ts*=8;
@ -823,24 +768,38 @@ void Draw_NonCursorLine(int x, int y, fileblock_t *b)
colour = COLOR_YELLOW; //yellow
}
nx = x;
for (i = 0; i < b->datalength; i++)
{
if (*d == '\t')
{
if (d == c)
Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK));
nx+=ts;
nx-=nx%ts;
nx-=(nx - x)%ts;
d++;
continue;
}
if (x+nx < vid.width)
Draw_ColouredCharacter (x+nx, y, (int)*d | (colour<<CON_FGSHIFT));
if (nx < (int)vid.pixelwidth)
nnx = Font_DrawChar(nx, y, (int)*d | (colour<<CON_FGSHIFT));
else nnx = vid.pixelwidth;
if (d == c)
Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK));
nx = nnx;
d++;
nx += 8;
}
*/
}
fileblock_t *firstline(void)
/*we didn't do the cursor! stick it at the end*/
if (c && c >= d)
Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK));
Font_EndString(font_conchar);
}
static fileblock_t *firstline(void)
{
int lines;
fileblock_t *b;
@ -864,6 +823,7 @@ void Editor_Draw(void)
{
int x;
int y;
int c;
fileblock_t *b;
if (key_dest != key_console)
@ -948,10 +908,11 @@ void Editor_Draw(void)
b = firstline();
for (; b; b=b->next)
{
c = -1;
if (b == cursorblock)
Draw_CursorLine(x, y, b);
else
Draw_NonCursorLine(x, y, b);
if ((int)(Sys_DoubleTime()*4.0) & 1)
c = cursorx;
Draw_Line(x, y, b, c);
y+=8;
if (y > vid.height)
@ -983,7 +944,8 @@ void Editor_Draw(void)
int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **parms)
{
if (editormodal || !developer.ival)
char *f1, *f2;
if (editormodal || line < 0 || !debugger.ival)
return line; //whoops
if (qrenderer == QR_NONE)
@ -1015,9 +977,13 @@ int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **
editprogfuncs = prfncs;
if (!strncmp(OpenEditorFile, "src/", 4))
{
if (!editoractive || strcmp(OpenEditorFile+4, filename))
f1 = OpenEditorFile;
f2 = filename;
if (!strncmp(f1, "src/", 4))
f1 += 4;
if (!strncmp(f2, "src/", 4))
f2 += 4;
if (!editoractive || strcmp(f1, f2))
{
if (editoractive)
EditorSaveFile(OpenEditorFile);
@ -1025,18 +991,6 @@ int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **
EditorOpenFile(filename);
}
}
else
{
if (!editoractive || strcmp(OpenEditorFile, filename))
{
if (editoractive)
EditorSaveFile(OpenEditorFile);
EditorOpenFile(filename);
}
}
for (cursorlinenum = 1, cursorblock = firstblock; cursorlinenum < line && cursorblock->next; cursorlinenum++)
cursorblock=cursorblock->next;
@ -1063,7 +1017,16 @@ int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **
return line;
}
void Editor_f(void)
void Editor_ProgsKilled(progfuncs_t *dead)
{
if (editprogfuncs == dead)
{
editprogfuncs = NULL;
editormodal = false;
}
}
static void Editor_f(void)
{
if (Cmd_Argc() != 2)
{
@ -1088,5 +1051,6 @@ void Editor_Init(void)
Cvar_Register(&editstripcr, "Text editor");
Cvar_Register(&editaddcr, "Text editor");
Cvar_Register(&edittabspacing, "Text editor");
Cvar_Register(&debugger, "Text editor");
}
#endif

View file

@ -2919,6 +2919,8 @@ void Cmd_Init (void)
Cvar_Register(&com_fs_cache, "Filesystem");
Cvar_Register(&tp_disputablemacros, "Teamplay");
Cvar_Register(&dpcompat_set, "Darkplaces compatibility");
#ifndef SERVERONLY
rcon_level.ival = atof(rcon_level.string); //client is restricted to not be allowed to change restrictions.
#else

View file

@ -1848,6 +1848,8 @@ void Mod_LoadSkinFile(texnums_t *texnum, char *surfacename, int skinnumber, unsi
texnum->shader = R_RegisterSkin(shadername);
R_BuildDefaultTexnums(texnum, texnum->shader);
if (texnum->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name);
}
#endif
@ -2213,6 +2215,16 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
"depthwrite\n"
"}\n"
"}\n");
else if (skintranstype == 3)
texnums->shader = R_RegisterShader(skinname,
"{\n"
"{\n"
"map $diffuse\n"
"alphafunc ge128\n"
"rgbgen lightingDiffuse\n"
"depthwrite\n"
"}\n"
"}\n");
else if (skintranstype)
texnums->shader = R_RegisterShader(skinname,
"{\n"
@ -3639,6 +3651,9 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
{
texnum->shader = R_RegisterSkin(shadname);
R_BuildDefaultTexnums(texnum, texnum->shader);
if (texnum->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name);
}
inshader++;
@ -4594,6 +4609,8 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
Q_strncpyz(skin->name, matt[i].name, sizeof(skin->name));
gtexnums->shader = R_RegisterSkin(matt[i].name);
R_BuildDefaultTexnums(gtexnums, gtexnums->shader);
if (gtexnums->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", gtexnums->shader->name, loadmodel->name);
gmdl[i].ofsskins = (char*)skin - (char*)&gmdl[i];
gmdl[i].numskins = 1;
@ -5138,7 +5155,7 @@ galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, f
{
galisskeletaltransforms_t *t, *r;
unsigned int num_t = 0;
unsigned int 0;
unsigned int v, j;
for (v = 0; v < inverts*4; v++)
{
if (vweight[v])
@ -5149,12 +5166,12 @@ galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, f
{
for (j = 0; j < 4; j++)
{
if (vweight[v<<2+j])
if (vweight[(v<<2)+j])
{
t->boneindex = vbone[v<<2+j];
t->boneindex = vbone[(v<<2)+j];
t->vertexindex = v;
VectorScale(vpos, vweight[v<<2+j]/255.0, t->org);
VectorScale(vnorm, vweight[v<<2+j]/255.0, t->normal);
VectorScale(vpos, vweight[(v<<2)+j]/255.0, t->org);
VectorScale(vnorm, vweight[(v<<2)+j]/255.0, t->normal);
t++;
}
}
@ -5162,31 +5179,42 @@ galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, f
return r;
}
galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer)
galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
{
struct iqmheader *h = (struct iqmheader *)buffer;
struct iqmjoint *joint;
struct iqmmesh *mesh;
struct iqmvertexarray *varray;
struct iqmtriangle *tris;
unsigned int i, t, nt;
char *strings;
float *vpos = NULL, *tcoord = NULL, *vnorm = NULL, *vtang = NULL;
unsigned char *vbone = NULL, *vweight = NULL;
unsigned int type, fmt, size, offset;
galiasinfo_t *gai;
galiasskin_t *skin;
texnums_t *texnum;
index_t *idx;
if (memcmp(h->magic, IQM_MAGIC, sizeof(h->magic))
if (memcmp(h->magic, IQM_MAGIC, sizeof(h->magic)))
{
Con_Printf("%s: format not recognised\n", mod->name);
return false;
return NULL;
}
if (h->version != IQM_VERSION)
{
Con_Printf("%s: unsupported version\n", mod->name);
return false;
return NULL;
}
if (h->filesize != com_filesize)
{
Con_Printf("%s: size (%u != %u)\n", mod->name, h->filesize, com_filesize);
return false;
return NULL;
}
/*
struct iqmjoint
unsigned int name;
int parent;
@ -5196,11 +5224,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer)
unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
unsigned int num_triangles, ofs_triangles, ofs_adjacency;
unsigned int num_joints, ofs_joints;
float *vpos = NULL, *tcoord = NULL, *vnorm = NULL, *vtang = NULL;
unsigned char *vbone = NULL, *vweight = NULL;
unsigned int type, fmt, size, offset;
*/
varray = (struct iqmvertexarray*)(buffer + h->ofs_vertexarrays);
for (i = 0; i < h->num_vertexarrays; i++)
@ -5223,24 +5247,55 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer)
vweight = (unsigned char *)(buffer + offset);
}
gai = Hunk_Alloc(sizeof(*gai)*h->num_meshes);
if (!h->num_meshes)
return NULL;
strings = buffer + h->ofs_text;
mesh = buffer + h->ofs_meshes;
tris = buffer + h->ofs_triangles;
gai = Hunk_Alloc(sizeof(*gai)*h->num_meshes + sizeof(*skin)*h->num_meshes + sizeof(*texnum)*h->num_meshes);
skin = (galiasskin_t*)(gai + h->num_meshes);
texnum = (texnums_t*)(skin + h->num_meshes);
for (i = 0; i < h->num_meshes; i++)
{
gai[i].nextsurf = (i == (h->num_meshes-1))?0:sizeof(*gai);
gai[i].sharesverts = false; //used with models with two shaders using the same vertex - use last mesh's verts
gai[i].sharesbones = i != 0;
gai[i].numverts = LittleLong(mesh[i].num_vertexes);
gai[i].numskins = 1;
gai[i].ofsskins = (char*)&skin[i] - (char*)&gai[i];
Q_strncpyz(skin[i].name, strings+mesh[i].material, sizeof(skin[i].name));
skin[i].skinwidth = 1;
skin[i].skinheight = 1;
skin[i].ofstexels = NULL; /*doesn't support 8bit colourmapping*/
skin[i].skinspeed = 10; /*something to avoid div by 0*/
skin[i].texnums = 1;
skin[i].ofstexnums = (char*)&texnum[i] - (char*)&skin[i];
texnum[i].shader = R_RegisterSkin(skin[i].name);
offset = LittleLong(mesh[i].first_vertex);
/*generate transforms for each vertex*/
gai[i].ofstransforms = (char*)IQM_ImportTransforms(&gai[i].numtransforms, gai[i].numverts, vpos+offset*3, tcoord+offset*2, vnorm+offset*3, vtang+offset*4, vbone+offset*4, vweight+offset*4) - (char*)gai;
}
galiasinfo_t
unsigned int name;
unsigned int material;
unsigned int first_vertex, num_vertexes;
unsigned int first_triangle, num_triangles;
nt = 0;//LittleLong(mesh[i].num_triangles);
tris = buffer + LittleLong(h->ofs_triangles);
tris += LittleLong(mesh[i].first_triangle);
gai[i].numindexes = nt*3;
idx = Hunk_Alloc(sizeof(*idx)*gai[i].numindexes);
gai[i].ofs_indexes = (char*)idx - (char*)&gai[i];
for (t = 0; t < nt; t++)
{
*idx++ = LittleShort(tris[t].vertex[0]);
*idx++ = LittleShort(tris[t].vertex[1]);
*idx++ = LittleShort(tris[t].vertex[2]);
}
}
return gai;
}
qboolean Mod_ParseIQMAnim(char *buffer, galiasinfo_t *prototype, void**poseofs, galiasgroup_t *gat)
@ -5251,11 +5306,12 @@ qboolean Mod_ParseIQMAnim(char *buffer, galiasinfo_t *prototype, void**poseofs,
qboolean Mod_LoadInterQuakeModel(model_t *mod, void *buffer)
{
unsigned int hunkstart, hunkend, hunktotal;
galiasinfo_t *root;
struct iqmheader *h = (struct iqmheader *)buffer;
hunkstart = Hunk_LowMark();
root = Mod_ParseMD5MeshModel(buffer);
root = Mod_ParseIQMMeshModel(mod, buffer);
if (!root)
return false;
hunkend = Hunk_LowMark();
@ -5693,6 +5749,8 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer)
#ifndef SERVERONLY
texnum->shader = R_RegisterSkin(com_token);
R_BuildDefaultTexnums(texnum, texnum->shader);
if (texnum->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name);
#endif
}
else if (!strcmp(com_token, "numverts"))

View file

@ -144,6 +144,9 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer);
#ifdef PSKMODELS
qboolean Mod_LoadPSKModel(model_t *mod, void *buffer);
#endif
#ifdef INTERQUAKEMODELS
qboolean Mod_LoadInterQuakeModel(model_t *mod, void *buffer);
#endif
#ifdef MD5MODELS
qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer);
qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer);

View file

@ -89,6 +89,8 @@ static char *safeargvs[NUM_SAFE_ARGVS] =
cvar_t registered = CVARD("registered","0","Set if quake's pak1.pak is available");
cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version for server browsers");
cvar_t gameversion_min = CVARD("gameversion_min","", "gamecode version for server browsers");
cvar_t gameversion_max = CVARD("gameversion_max","", "gamecode version for server browsers");
cvar_t com_gamename = CVARD("com_gamename", "", "The game name used for dpmaster queries");
cvar_t com_modname = CVARD("com_modname", "", "dpmaster information");
cvar_t com_parseutf8 = CVARD("com_parseutf8", "0", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts."); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
@ -3313,6 +3315,8 @@ void COM_Init (void)
Cvar_Register (&registered, "Copy protection");
Cvar_Register (&gameversion, "Gamecode");
Cvar_Register (&gameversion_min, "Gamecode");
Cvar_Register (&gameversion_max, "Gamecode");
Cvar_Register (&com_parseutf8, "Internationalisation");
com_parseutf8.ival = 1;

View file

@ -719,6 +719,19 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
var->latched_string = NULL;
}
if (var->flags & CVAR_TELLGAMECODE)
{
#ifndef CLIENTONLY
SVQ1_CvarChanged(var);
#endif
#ifdef MENU_DAT
MP_CvarChanged(var);
#endif
#ifdef CSQC_DAT
CSQC_CvarChanged(var);
#endif
}
return var;
}

View file

@ -129,6 +129,7 @@ typedef struct cvar_group_s
#define CVAR_NOUNSAFEEXPAND (1<<14) // do not expand cvar value when command is from gamecode
#define CVAR_RULESETLATCH (1<<15) //latched by the ruleset
#define CVAR_SHADERSYSTEM (1<<16) //change flushes shaders.
#define CVAR_TELLGAMECODE (1<<17) //tells the gamecode when it has changed, does not prevent changing, added as an optimisation
#define CVAR_LASTFLAG CVAR_SHADERSYSTEM

View file

@ -1633,7 +1633,7 @@ void COM_Gamedir (const char *dir)
#endif
}
#define DPCOMPAT "set dpcompat_set 1\nset dpcompat_trailparticles 1\n"
#define DPCOMPAT "set _cl_playermodel \"\"\n set dpcompat_set 1\n set dpcompat_trailparticles 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
#define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\nset r_particlesdesc effectinfo\n"
#define DMFCFG "set com_parseutf8 1\npm_airstep 1\n"
#define HEX2CFG "set r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\n"
@ -1659,6 +1659,7 @@ const gamemode_info_t gamemode_info[] = {
{"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", {NULL}, NULL, {"id1", "qw", "hipnotic", "fte"}, "Quake: Scourge of Armagon"},
{"Darkplaces-Rogue", "rogue", "-rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"},
{"Nexuiz", "nexuiz", "-nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"},
{"Xonotic", "xonotic", "-xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"},
{"DMF", "dmf", "-dmf", {"base/src/progs.src"}, DMFCFG, {"base", }, "DMF"},
//supported commercial mods (some are currently only partially supported)

View file

@ -610,6 +610,9 @@ vfsfile_t *FSZIP_OpenVFS(void *handle, flocation_t *loc, const char *mode)
if (strcmp(mode, "rb"))
return NULL; //urm, unable to write/append
if (loc->len < 0)
return NULL;
vfsz = Z_Malloc(sizeof(vfszip_t));
vfsz->parent = zip;

View file

@ -15,6 +15,7 @@ static char *cvargroup_progs = "Progs variables";
cvar_t pr_brokenfloatconvert = SCVAR("pr_brokenfloatconvert", "0");
cvar_t pr_tempstringcount = SCVAR("pr_tempstringcount", "");//"16");
cvar_t pr_tempstringsize = SCVAR("pr_tempstringsize", "4096");
cvar_t dpcompat_stats = CVAR("dpcompat_stats", "0");
static char *strtoupper(char *s)
{
@ -54,6 +55,7 @@ void PF_Common_RegisterCvars(void)
Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs);
Cvar_Register (&pr_tempstringcount, cvargroup_progs);
Cvar_Register (&pr_tempstringsize, cvargroup_progs);
Cvar_Register (&dpcompat_stats, cvargroup_progs);
}
char *Translate(char *message);
@ -1951,6 +1953,15 @@ void QCBUILTIN PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_gl
RETURN_TSTRING(resultbuf);
}
// uri_get() gets content from an URL and calls a callback "uri_get_callback" with it set as string; an unique ID of the transfer is returned
// returns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string
void QCBUILTIN PF_uri_get (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
Con_Printf("PF_uri_get: stub\n");
G_FLOAT(OFS_RETURN) = 0;
}
////////////////////////////////////////////////////
//Console functions
@ -2444,7 +2455,7 @@ void QCBUILTIN PF_externset (progfuncs_t *prinst, struct globalvars_s *pr_global
char *varname = PF_VarString(prinst, 2, pr_globals);
eval_t *var;
var = prinst->FindGlobal(prinst, varname, n);
var = PR_FindGlobal(prinst, varname, n, NULL);
if (var)
var->_int = v;
@ -2456,7 +2467,7 @@ void QCBUILTIN PF_externvalue (progfuncs_t *prinst, struct globalvars_s *pr_glob
char *varname = PF_VarString(prinst, 1, pr_globals);
eval_t *var;
var = prinst->FindGlobal(prinst, varname, n);
var = prinst->FindGlobal(prinst, varname, n, NULL);
if (var)
{
@ -2610,11 +2621,105 @@ void QCBUILTIN PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals
Cbuf_AddText (str, RESTRICT_INSECURE);
}
void QCBUILTIN PF_sprintf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char result[1024];
char *fmt = PR_GetStringOfs(prinst, OFS_PARM0);
Con_Printf("PF_sprintf: stub\n");
Q_strncpyz(result, fmt, sizeof(result));
RETURN_TSTRING(result);
}
#define DEF_SAVEGLOBAL (1u<<15)
static void PR_AutoCvarApply(progfuncs_t *prinst, eval_t *val, etype_t type, cvar_t *var)
{
switch(type & ~DEF_SAVEGLOBAL)
{
case ev_float:
val->_float = var->value;
break;
case ev_integer:
val->_int = var->ival;
break;
case ev_string:
PR_RemoveProgsString(prinst, val->_int);
val->_int = PR_SetString(prinst, var->string);
break;
case ev_vector:
{
char res[128];
char *vs = var->string;
vs = COM_ParseOut(vs, res, sizeof(res));
val->_vector[0] = atof(com_token);
vs = COM_ParseOut(vs, res, sizeof(res));
val->_vector[1] = atof(com_token);
vs = COM_ParseOut(vs, res, sizeof(res));
val->_vector[2] = atof(com_token);
}
break;
}
}
/*called when a var has changed*/
void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var)
{
char *gname;
eval_t *val;
etype_t type;
int n, p;
for (n = 0; n < 2; n++)
{
gname = n?var->name2:var->name;
if (!gname)
continue;
gname = va("autocvar_%s", gname);
for (p = 0; p < prinst->numprogs; p++)
{
val = PR_FindGlobal(prinst, gname, p, &type);
if (val)
PR_AutoCvarApply(prinst, val, type, var);
}
}
}
void PR_FoundPrefixedGlobals(progfuncs_t *progfuncs, char *name, eval_t *val, etype_t type)
{
cvar_t *var;
char *vals;
name += 9; //autocvar_
switch(type & ~DEF_SAVEGLOBAL)
{
case ev_float:
vals = va("%f", val->_float);
break;
case ev_integer:
vals = va("%i", val->_int);
break;
case ev_vector:
vals = va("%f %f %f", val->_vector[0], val->_vector[1], val->_vector[2]);
break;
case ev_string:
vals = PR_GetString(progfuncs, val->string);
break;
default:
return;
}
var = Cvar_Get(name, vals, 0, "autocvars");
if (!var)
return;
var->flags |= CVAR_TELLGAMECODE;
PR_AutoCvarApply(progfuncs, val, type, var);
}
void PR_AutoCvarSetup(progfuncs_t *prinst)
{
prinst->FindPrefixGlobals (prinst, "autocvar_", PR_FoundPrefixedGlobals);
}
lh_extension_t QSG_Extensions[] = {

View file

@ -44,8 +44,6 @@ struct wedict_s
#define PF_cin_getstate PF_Fixme
#define PF_cin_restart PF_Fixme
#define PF_drawline PF_Fixme
#define PF_drawcolorcodedstring PF_Fixme
#define PF_uri_get PF_Fixme
#define PF_gecko_create PF_Fixme
#define PF_gecko_destroy PF_Fixme
#define PF_gecko_navigate PF_Fixme
@ -53,7 +51,6 @@ struct wedict_s
#define PF_gecko_movemouse PF_Fixme
#define PF_gecko_resize PF_Fixme
#define PF_gecko_get_texture_extent PF_Fixme
#define PF_uri_get PF_Fixme
#define PF_pointsound PF_Fixme
#define PF_getsurfacepointattribute PF_Fixme
@ -141,6 +138,7 @@ void QCBUILTIN PF_atan (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_atan2 (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_tan (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_sprintf (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -166,13 +164,15 @@ void QCBUILTIN PF_crc16 (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cvar_type (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_uri_escape (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_uri_get (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_itos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_stoi (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_stoh (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_htos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PR_fclose_progs (progfuncs_t *prinst);
char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
void PR_AutoCvarSetup(progfuncs_t *prinst);
void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var);
@ -245,6 +245,8 @@ void QCBUILTIN PF_CL_drawgetimagesize (progfuncs_t *prinst, struct globalvars_s
void QCBUILTIN PF_CL_stringwidth (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_CL_drawsubpic (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_keynumtostring (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_findkeysforcommand (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_stringtokeynum(progfuncs_t *prinst, struct globalvars_s *pr_globals);

View file

@ -712,7 +712,7 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
return e->light_known-1;
e->light_dir[0] = 0; e->light_dir[1] = 1; e->light_dir[2] = 0;
if (clmodel->engineflags & MDLF_FLAME)
if (clmodel->engineflags & MDLF_FLAME || r_fullbright.ival)
{
e->light_avg[0] = e->light_avg[1] = e->light_avg[2] = 1;
e->light_range[0] = e->light_range[1] = e->light_range[2] = 0;
@ -1890,6 +1890,11 @@ void BE_GenModelBatches(batch_t **batches)
if (!r_drawentities.ival)
return;
#if defined(TERRAIN)
if (cl.worldmodel && cl.worldmodel->type == mod_heightmap)
GL_DrawHeightmapModel(batches, &r_worldentity);
#endif
// draw sprites seperately, because of alpha blending
for (i=0 ; i<cl_numvisedicts ; i++)
{

View file

@ -36,25 +36,32 @@ uniform vec3 lightposition;\n\
uniform vec3 eyeposition;\n\
#endif\n\
\
uniform mat4 m_modelview, m_projection;\n\
attribute vec3 v_position;\n\
attribute vec2 v_texcoord;\n\
attribute vec3 v_normal;\n\
attribute vec3 v_svector;\n\
attribute vec3 v_tvector;\n\
\
void main (void)\n\
{\n\
gl_Position = ftransform();\n\
gl_Position = m_projection * m_modelview * vec4(v_position, 1);\n\
\
tcbase = gl_MultiTexCoord0.xy; //pass the texture coords straight through\n\
tcbase = v_texcoord; //pass the texture coords straight through\n\
\
vec3 lightminusvertex = lightposition - gl_Vertex.xyz;\n\
lightvector.x = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n\
lightvector.y = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n\
lightvector.z = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n\
vec3 lightminusvertex = lightposition - v_position.xyz;\n\
lightvector.x = dot(lightminusvertex, v_svector.xyz);\n\
lightvector.y = dot(lightminusvertex, v_tvector.xyz);\n\
lightvector.z = dot(lightminusvertex, v_normal.xyz);\n\
\
#if defined(SPECULAR)||defined(OFFSETMAPPING)\n\
vec3 eyeminusvertex = eyeposition - gl_Vertex.xyz;\n\
eyevector.x = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n\
eyevector.y = -dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n\
eyevector.z = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n\
vec3 eyeminusvertex = eyeposition - v_position.xyz;\n\
eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n\
eyevector.y = -dot(eyeminusvertex, v_tvector.xyz);\n\
eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n\
#endif\n\
#if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\
vshadowcoord = gl_TextureMatrix[7] * (entmatrix*gl_Vertex);\n\
vshadowcoord = gl_TextureMatrix[7] * (entmatrix*v_position);\n\
#endif\n\
}\n\
#endif\n\
@ -556,7 +563,7 @@ void GL_MTBind(int tmu, int target, texid_t texnum)
if (target)
bindTexFunc (target, texnum.num);
if (shaderstate.curtexturetype[tmu] != target)
if (shaderstate.curtexturetype[tmu] != target && !gl_config.nofixedfunc)
{
if (shaderstate.curtexturetype[tmu])
qglDisable(shaderstate.curtexturetype[tmu]);
@ -593,7 +600,7 @@ void GL_LazyBind(int tmu, int target, texid_t texnum, qboolean arrays)
if (target)
bindTexFunc (target, texnum.num);
if (shaderstate.curtexturetype[tmu] != target)
if (shaderstate.curtexturetype[tmu] != target && !gl_config.nofixedfunc)
{
if (shaderstate.curtexturetype[tmu])
qglDisable(shaderstate.curtexturetype[tmu]);
@ -1148,6 +1155,9 @@ static float *tcgen(unsigned int tcgen, int cnt, float *dst, const mesh_t *mesh)
case TC_GEN_BASE:
return (float*)mesh->st_array;
case TC_GEN_LIGHTMAP:
if (!mesh->lmst_array)
return (float*)mesh->st_array;
else
return (float*)mesh->lmst_array;
case TC_GEN_NORMAL:
return (float*)mesh->normals_array;
@ -1958,10 +1968,18 @@ static void BE_GeneratePassTC(const shaderpass_t *pass, int passno)
qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord);
}
else if (pass->tcgen == TC_GEN_LIGHTMAP)
{
if (!shaderstate.sourcevbo->lmcoord)
{
GL_SelectVBO(shaderstate.sourcevbo->vbotexcoord);
qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord);
}
else
{
GL_SelectVBO(shaderstate.sourcevbo->vbolmcoord);
qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->lmcoord);
}
}
else if (pass->tcgen == TC_GEN_NORMAL)
{
GL_SelectVBO(shaderstate.sourcevbo->vbonormals);
@ -3269,6 +3287,8 @@ void GLBE_DrawWorld (qbyte *vis)
shaderstate.curentity = &r_worldentity;
shaderstate.updatetime = cl.servertime;
BE_SelectEntity(&r_worldentity);
#if 0
{int i;
for (i = 0; i < SHADER_SORT_COUNT; i++)
@ -3309,18 +3329,18 @@ void GLBE_DrawWorld (qbyte *vis)
BE_SelectMode(BEM_DEPTHDARK);
else
BE_SelectMode(BEM_STANDARD);
checkglerror();
RSpeedRemark();
GLBE_SubmitMeshes(true, batches);
RSpeedEnd(RSPEED_WORLD);
checkglerror();
#ifdef RTLIGHTS
RSpeedRemark();
BE_SelectEntity(&r_worldentity);
Sh_DrawLights(vis);
RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif
checkglerror();
if (r_refdef.gfog_alpha)
{
BE_SelectMode(BEM_FOG);

View file

@ -254,9 +254,10 @@ void Font_Init(void)
fontplanes.shader = R_RegisterShader("ftefont",
"{\n"
#ifdef USE_EGL
"if $nofixed\n"
"[\n"
"program default2d\n"
#endif
"]\n"
"nomipmaps\n"
"{\n"
"map $diffuse\n"
@ -555,6 +556,21 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
}
}
}
/*make tab invisible*/
if (charidx == '\t' || charidx == '\n')
{
c = &f->chars[charidx];
c->left = 0;
c->advance = f->charheight;
c->top = 0;
c->texplane = 0;
c->bmx = 0;
c->bmy = 0;
c->bmw = 0;
c->bmh = 0;
return c;
}
#ifdef AVAIL_FREETYPE
if (f->face)
@ -949,14 +965,14 @@ void Font_Free(struct font_s *f)
void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py)
{
curfont = font;
*px = (vx*vid.rotpixelwidth) / (float)vid.width;
*py = (vy*vid.rotpixelheight) / (float)vid.height;
*px = (vx*(int)vid.rotpixelwidth) / (float)vid.width;
*py = (vy*(int)vid.rotpixelheight) / (float)vid.height;
}
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float *px, float *py)
{
curfont = font;
*px = (vx*vid.rotpixelwidth) / (float)vid.width;
*py = (vy*vid.rotpixelheight) / (float)vid.height;
*px = vx;
*py = vy;
}
void Font_EndString(struct font_s *font)
@ -1273,10 +1289,10 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch
if (c->texplane >= DEFAULTPLANE)
{
sx = ((px+c->left));//*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top));//*(int)vid.height) / (float)vid.rotpixelheight;
sw = ((curfont->charheight*cw));//*vid.width) / (float)vid.rotpixelwidth;
sh = ((curfont->charheight*ch));//*vid.height) / (float)vid.rotpixelheight;
sx = ((px+c->left));
sy = ((py+c->top));
sw = ((curfont->charheight*cw));
sh = ((curfont->charheight*ch));
if (c->texplane == DEFAULTPLANE)
v = Font_BeginChar(fontplanes.defaultfont);
@ -1285,10 +1301,10 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch
}
else
{
sx = ((px+c->left));//*(int)vid.width) / (float)vid.rotpixelwidth;
sy = ((py+c->top));//*(int)vid.height) / (float)vid.rotpixelheight;
sw = ((c->bmw*cw));//*vid.width) / (float)vid.rotpixelwidth;
sh = ((c->bmh*ch));//*vid.height) / (float)vid.rotpixelheight;
sx = ((px+c->left));
sy = ((py+c->top));
sw = ((c->bmw*cw));
sh = ((c->bmh*ch));
v = Font_BeginChar(fontplanes.texnum[c->texplane]);
}

View file

@ -20,6 +20,7 @@
typedef struct {
char path[MAX_QPATH];
char hmapname[MAX_QPATH];
unsigned short *heights;
int terrainsize;
float terrainscale;
@ -29,150 +30,159 @@ typedef struct {
texid_t textures[SECTIONS*SECTIONS];
int displaylist[SECTIONS*SECTIONS]; //display lists are famous for being stupidly fast with heightmaps.
unsigned short mins[SECTIONS*SECTIONS], maxs[SECTIONS*SECTIONS];
shader_t *skyshader;
shader_t *shader;
mesh_t mesh[SECTIONS*SECTIONS];
mesh_t *amesh[SECTIONS*SECTIONS];
mesh_t skymesh;
mesh_t *askymesh;
qboolean modified[SECTIONS*SECTIONS];
} heightmap_t;
#ifdef GLQUAKE
#define DISPLISTS
//#define MULTITEXTURE //ATI suck. I don't know about anyone else (this goes at 1/5th the speed).
void GL_DrawHeightmapModel (entity_t *e)
void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
{
//a 512*512 heightmap
//will draw 2 tris per square, drawn twice for detail
//so a million triangles per frame if the whole thing is visible.
//with 130 to 180fps, display lists rule!
int x, y, vx, vy;
int x, y, vx, vy, v;
float subsize;
int minx, miny;
vec3_t mins, maxs;
model_t *m = e->model;
heightmap_t *hm = m->terrain;
mesh_t *mesh;
batch_t *b;
vbo_t *vbo;
if (e->model == cl.worldmodel)
{
qglColor4f(1, 1, 1, 1);
R_DrawSkyChain(NULL);
b = BE_GetTempBatch();
if (b)
{
b->ent = e;
b->shader = hm->skyshader;
b->flags = 0;
b->mesh = &hm->askymesh;
b->mesh[0] = &hm->skymesh;
b->meshes = 1;
b->buildmeshes = NULL;
b->skin = &b->shader->defaulttextures;
b->texture = NULL;
// vbo = b->vbo = hm->vbo[x+y*SECTIONS];
b->vbo = NULL;
b->next = batches[b->shader->sort];
batches[b->shader->sort] = b;
}
}
else
qglColor4fv(e->shaderRGBAf);
GL_CullFace(SHADER_CULL_BACK);
for (x = 0; x < hm->numsegs; x++)
{
mins[0] = (x+0)*hm->terrainscale*hm->terrainsize/hm->numsegs;
maxs[0] = (x+1)*hm->terrainscale*hm->terrainsize/hm->numsegs;
for (y = 0; y < hm->numsegs; y++)
{
mins[1] = (y+0)*hm->terrainscale*hm->terrainsize/hm->numsegs;
maxs[1] = (y+1)*hm->terrainscale*hm->terrainsize/hm->numsegs;
mins[2] = 0;//hm->mins[x+y*SECTIONS];
mins[2] = 65535;//hm->maxs[x+y*SECTIONS];
// if (!BoundsIntersect(mins, maxs, r_refdef.vieworg, r_refdef.vieworg))
// if (R_CullBox(mins, maxs))
// continue;
#ifdef DISPLISTS
if (!hm->displaylist[x+y*SECTIONS])
{
hm->displaylist[x+y*SECTIONS] = qglGenLists(1);
qglNewList(hm->displaylist[x+y*SECTIONS], GL_COMPILE_AND_EXECUTE);
#endif
#ifdef MULTITEXTURE
if (qglActiveTextureARB)
{
GL_MBind(0, hm->textures[x+y*SECTIONS]);
GL_MBind(1, hm->detailtexture);
qglEnable(GL_TEXTURE_2D);
subsize = hm->terrainsize/SECTIONS;
for (x = 0; x < hm->numsegs; x++)
{
mins[0] = (x+0)*subsize*hm->terrainscale;
maxs[0] = (x+1)*subsize*hm->terrainscale;
for (y = 0; y < hm->numsegs; y++)
{
mins[1] = (y+0)*subsize*hm->terrainscale;
maxs[1] = (y+1)*subsize*hm->terrainscale;
mesh = &hm->mesh[x+y*SECTIONS];
if (hm->modified[x+y*SECTIONS])
{
minx = x*subsize;
miny = y*subsize;
hm->modified[x+y*SECTIONS] = false;
qglBegin(GL_QUADS);
hm->mins[x+y*SECTIONS] = 65536 * hm->heightscale;
hm->maxs[x+y*SECTIONS] = 0;
if (!mesh->xyz_array)
mesh->xyz_array = BZ_Malloc(sizeof(vecV_t) * (subsize+1)*(subsize+1));
if (!mesh->st_array)
mesh->st_array = BZ_Malloc(sizeof(vec2_t) * (subsize+1)*(subsize+1));
if (!mesh->lmst_array)
mesh->lmst_array = BZ_Malloc(sizeof(vec2_t) * (subsize+1)*(subsize+1));
mesh->numvertexes = 0;
/*64 quads across requires 65 verticies*/
for (vx = 0; vx <= subsize; vx++)
{
for (vy = 0; vy <= subsize; vy++)
{
v = mesh->numvertexes++;
mesh->xyz_array[v][0] = (vx+minx)*hm->terrainscale;
mesh->xyz_array[v][1] = (vy+miny)*hm->terrainscale;
mesh->xyz_array[v][2] = hm->heights[(vx+minx) + (vy+miny)*hm->terrainsize]*hm->heightscale;
if (hm->maxs[x+y*SECTIONS] < mesh->xyz_array[v][2])
hm->maxs[x+y*SECTIONS] = mesh->xyz_array[v][2];
if (hm->mins[x+y*SECTIONS] > mesh->xyz_array[v][2])
hm->mins[x+y*SECTIONS] = mesh->xyz_array[v][2];
mesh->st_array[v][0] = mesh->xyz_array[v][0] / 64;
mesh->st_array[v][1] = mesh->xyz_array[v][1] / 64;
mesh->lmst_array[v][0] = mesh->xyz_array[v][0] / 64;
mesh->lmst_array[v][1] = mesh->xyz_array[v][1] / 64;
}
}
if (!mesh->indexes)
mesh->indexes = BZ_Malloc(sizeof(index_t) * subsize*subsize*6);
mesh->numindexes = 0;
for (vx = 0; vx < subsize; vx++)
{
for (vy = 0; vy < subsize; vy++)
{
qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, vx/subsize, (vy+1)/subsize);
qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);
qglVertex3f((vx+minx)*hm->terrainscale, (vy+miny+1)*hm->terrainscale, hm->heights[vx + (vy+1)*hm->terrainsize]*hm->heightscale);
qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, (vx+1)/subsize, (vy+1)/subsize);
qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
qglVertex3f((vx+minx+1)*hm->terrainscale, (vy+miny+1)*hm->terrainscale, hm->heights[vx+1 + (vy+1)*hm->terrainsize]*hm->heightscale);
qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, (vx+1)/subsize, vy/subsize);
qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);
qglVertex3f((vx+minx+1)*hm->terrainscale, (vy+miny)*hm->terrainscale, hm->heights[vx+1 + vy*hm->terrainsize]*hm->heightscale);
qglMultiTexCoord2fARB(GL_TEXTURE0_ARB, vx/subsize, vy/subsize);
qglMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
qglVertex3f((vx+minx)*hm->terrainscale, (vy+miny)*hm->terrainscale, hm->heights[vx + vy*hm->terrainsize]*hm->heightscale);
v = vx + vy*(subsize+1);
mesh->indexes[mesh->numindexes++] = v+0;
mesh->indexes[mesh->numindexes++] = v+1;
mesh->indexes[mesh->numindexes++] = v+subsize+1;
mesh->indexes[mesh->numindexes++] = v+1;
mesh->indexes[mesh->numindexes++] = v+1+subsize+1;
mesh->indexes[mesh->numindexes++] = v+subsize+1;
}
}
qglEnd();
qglDisable(GL_TEXTURE_2D);
qglActiveTextureARB(GL_TEXTURE0_ARB);
}
else
#endif
{ //single texture
GL_MTBind(0, GL_TEXTURE_2D, hm->textures[x+y*SECTIONS]);
qglBegin(GL_QUADS);
subsize = hm->terrainsize/hm->numsegs;
minx = x*subsize;
miny = y*subsize;
for (vx = 0; vx < subsize; vx++)
{
for (vy = 0; vy < subsize; vy++)
{
qglTexCoord2f(vx/subsize, (vy+1)/subsize);
qglVertex3f((vx+minx)*hm->terrainscale, (vy+miny+1)*hm->terrainscale, hm->heights[vx+minx + (vy+miny+1)*hm->terrainsize]*hm->heightscale);
qglTexCoord2f((vx+1)/subsize, (vy+1)/subsize);
qglVertex3f((vx+minx+1)*hm->terrainscale, (vy+miny+1)*hm->terrainscale, hm->heights[vx+minx+1 + (vy+miny+1)*hm->terrainsize]*hm->heightscale);
qglTexCoord2f((vx+1)/subsize, vy/subsize);
qglVertex3f((vx+minx+1)*hm->terrainscale, (vy+miny)*hm->terrainscale, hm->heights[vx+minx+1 + (vy+miny)*hm->terrainsize]*hm->heightscale);
qglTexCoord2f(vx/subsize, vy/subsize);
qglVertex3f((vx+minx)*hm->terrainscale, (vy+miny)*hm->terrainscale, hm->heights[vx+minx + (vy+miny)*hm->terrainsize]*hm->heightscale);
}
}
qglEnd();
GL_MTBind(0, GL_TEXTURE_2D, hm->detailtexture);
qglEnable(GL_BLEND);
qglBlendFunc (GL_ZERO, GL_SRC_COLOR);
qglBegin(GL_QUADS);
for (vx = 0; vx < subsize; vx++)
{
for (vy = 0; vy < subsize; vy++)
{
qglTexCoord2f(0, 1);
qglVertex3f((vx+minx)*hm->terrainscale, (vy+miny+1)*hm->terrainscale, hm->heights[vx+minx + (vy+miny+1)*hm->terrainsize]*hm->heightscale);
qglTexCoord2f(1, 1);
qglVertex3f((vx+minx+1)*hm->terrainscale, (vy+miny+1)*hm->terrainscale, hm->heights[vx+minx+1 + (vy+miny+1)*hm->terrainsize]*hm->heightscale);
qglTexCoord2f(1, 0);
qglVertex3f((vx+minx+1)*hm->terrainscale, (vy+miny)*hm->terrainscale, hm->heights[vx+minx+1 + (vy+miny)*hm->terrainsize]*hm->heightscale);
qglTexCoord2f(0, 0);
qglVertex3f((vx+minx)*hm->terrainscale, (vy+miny)*hm->terrainscale, hm->heights[vx+minx + (vy+miny)*hm->terrainsize]*hm->heightscale);
//GL_BuildVBO();
}
}
qglEnd();
qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qglDisable(GL_BLEND);
}
#ifdef DISPLISTS
qglEndList();
}
else
{
qglCallList(hm->displaylist[x+y*SECTIONS]);
}
#endif
mins[2] = hm->mins[x+y*SECTIONS];
maxs[2] = hm->maxs[x+y*SECTIONS];
if (!BoundsIntersect(mins, maxs, r_refdef.vieworg, r_refdef.vieworg))
if (R_CullBox(mins, maxs))
continue;
b = BE_GetTempBatch();
if (!b)
continue;
b->ent = e;
b->shader = hm->shader;
b->flags = 0;
b->mesh = &hm->amesh[x+y*SECTIONS];
b->mesh[0] = mesh;
b->meshes = 1;
b->buildmeshes = NULL;
b->skin = &b->shader->defaulttextures;
b->texture = NULL;
// vbo = b->vbo = hm->vbo[x+y*SECTIONS];
b->vbo = NULL;
b->next = batches[b->shader->sort];
batches[b->shader->sort] = b;
}
}
}
#endif
unsigned int Heightmap_PointContentsHM(heightmap_t *hm, float clipmipsz, vec3_t org)
{
@ -286,6 +296,7 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
float x, y;
float z;
int sx, sy;
vec3_t d1, d2;
x = org[0]/hm->terrainscale;
y = org[1]/hm->terrainscale;
@ -299,23 +310,27 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
//0, 1
//1, 1
//1, 0
x = hm->heights[(sx+1)+(sy+1)*hm->terrainsize] - hm->heights[(sx+0)+(sy+1)*hm->terrainsize];
y = hm->heights[(sx+1)+(sy+1)*hm->terrainsize] - hm->heights[(sx+1)+(sy+0)*hm->terrainsize];
d1[0] = hm->terrainscale;
d1[1] = 0;
d1[2] = hm->heights[(sx+1)+(sy+1)*hm->terrainsize] - hm->heights[(sx+0)+(sy+1)*hm->terrainsize];
d2[0] = 0;
d2[1] = hm->terrainscale;
d2[2] = hm->heights[(sx+1)+(sy+1)*hm->terrainsize] - hm->heights[(sx+1)+(sy+0)*hm->terrainsize];
}
else
{
//0, 1
//1, 0
//0, 0
x = hm->heights[(sx+1)+(sy+0)*hm->terrainsize] - hm->heights[(sx+0)+(sy+0)*hm->terrainsize];
y = hm->heights[(sx+0)+(sy+1)*hm->terrainsize] - hm->heights[(sx+0)+(sy+0)*hm->terrainsize];
d1[0] = hm->terrainscale;
d1[1] = 0;
d1[2] = hm->heights[(sx+0)+(sy+1)*hm->terrainsize] - hm->heights[(sx+0)+(sy+0)*hm->terrainsize];
d2[0] = 0;
d2[1] = hm->terrainscale;
d2[2] = hm->heights[(sx+1)+(sy+0)*hm->terrainsize] - hm->heights[(sx+0)+(sy+0)*hm->terrainsize];
}
norm[0] = (-x*hm->heightscale)/hm->terrainscale;
norm[1] = (-y*hm->heightscale)/hm->terrainscale;
norm[2] = 1.0f/(float)sqrt(norm[0]*norm[0] + norm[1]*norm[1] + 1);
norm[0] *= norm[2];
norm[1] *= norm[2];
CrossProduct(d1, d2, norm);
VectorNormalize(norm);
}
@ -518,7 +533,7 @@ qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axi
{
vec3_t org;
vec3_t dir;
int distleft;
float distleft;
float dist;
heightmap_t *hm = model->terrain;
memset(trace, 0, sizeof(trace_t));
@ -534,14 +549,14 @@ qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axi
VectorCopy(start, org);
VectorSubtract(end, start, dir);
dist = VectorNormalize(dir);
/* if (dist < 10)
if (dist < 10 && dist)
{ //if less than 10 units, do at least 10 steps
VectorScale(dir, 10/dist, dir);
VectorScale(dir, 1/10.0f, dir);
dist = 10;
}*/
}
distleft = dist;
while(distleft>=0)
while(distleft>0)
{
VectorAdd(org, dir, org);
if (Heightmap_PointContentsHM(hm, mins[2], org) == FTECONTENTS_SOLID)
@ -554,7 +569,7 @@ qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axi
trace->contents = Heightmap_PointContentsHM(hm, mins[2], end);
if (distleft < 0 && trace->contents != FTECONTENTS_SOLID)
if (distleft <= 0 && trace->contents != FTECONTENTS_SOLID)
{ //all the way
trace->fraction = 1;
VectorCopy(end, trace->endpos);
@ -619,12 +634,139 @@ int Heightmap_LeafForPoint (model_t *model, vec3_t point)
//Heightmap_NativeBoxContents
enum
{
ter_reload,
ter_save,
ter_set,
ter_smooth,
ter_raise,
ter_lower
};
qboolean Heightmap_Edit(model_t *mod, int action, float *pos, float radius, float quant)
{
unsigned short *tmp;
heightmap_t *hm = mod->terrain;
int size;
int x, y, min[2], max[2];
float xd, yd, w;
vec2_t sc;
if (mod->type != mod_heightmap)
return false;
size = hm->terrainsize;
if (radius < 0.05)
radius = 0.05;
sc[0] = pos[0] / hm->terrainscale;
sc[1] = pos[1] / hm->terrainscale;
radius = radius / hm->terrainscale;
quant /= hm->heightscale;
min[0] = sc[0] - radius;
min[1] = sc[1] - radius;
max[0] = sc[0] + radius;
max[1] = sc[1] + radius;
if (min[0] < 0)
min[0] = 0;
if (min[1] < 0)
min[1] = 0;
if (max[0] > size)
max[0] = size;
if (max[1] < size)
max[1] = size;
switch(action)
{
case ter_reload:
tmp = (unsigned short*)COM_LoadTempFile(hm->hmapname);
if (tmp)
x = com_filesize/2;
else
x = 0;
if (x > size*size)
x = size*size;
while (x-- > 0)
{
hm->heights[x] = LittleShort(tmp[x]);
}
break;
case ter_save:
tmp = Hunk_TempAlloc(size*size*2);
for (x = 0; x < size*size; x++)
{
tmp[x] = LittleShort(hm->heights[x]);
}
COM_WriteFile(hm->hmapname, tmp, size*size*2);
break;
case ter_set:
for (x = min[0]; x < max[0]; x++)
{
for (y = min[1]; y < max[1]; y++)
{
xd = sc[0] - x;
yd = sc[1] - y;
if (sqrt(xd*xd+yd*yd) < radius)
{
hm->heights[x + y*size] = quant;
hm->modified[(int)(x/(hm->terrainscale)) + (int)(y/(hm->terrainscale))*SECTIONS] = true;
}
}
}
break;
case ter_smooth:
case ter_raise:
for (x = min[0]; x < max[0]; x++)
{
for (y = min[1]; y < max[1]; y++)
{
xd = sc[0] - x;
yd = sc[1] - y;
w = sqrt(radius*radius - (xd*xd+yd*yd));
if (w > 0)
{
w *= quant/radius;
hm->heights[x + y*size] += w;
hm->modified[(int)(x/(hm->terrainscale)) + (int)(y/(hm->terrainscale))*SECTIONS] = true;
}
}
}
break;
case ter_lower:
for (x = min[0]; x < max[0]; x++)
{
for (y = min[1]; y < max[1]; y++)
{
xd = sc[0] - x;
yd = sc[1] - y;
w = sqrt(radius*radius - (xd*xd+yd*yd));
if (w > 0)
{
w *= quant/radius;
/*don't drop below 0*/
if (hm->heights[x + y*size]-w < 0)
hm->heights[x + y*size] = 0;
else
hm->heights[x + y*size] -= w;
hm->modified[(int)(x/(hm->terrainscale)) + (int)(y/(hm->terrainscale))*SECTIONS] = true;
}
}
}
break;
}
return true;
}
qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer)
{
heightmap_t *hm;
unsigned short *heightmap;
int size;
int x;
int x, y;
float skyrotate;
vec3_t skyaxis;
@ -738,27 +880,51 @@ qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer)
mod->type = mod_heightmap;
heightmap = (unsigned short*)COM_LoadTempFile(heightmapname);
if (!heightmap)
{
size = 1024;
heightmap = Hunk_TempAlloc(size*size*2);
for (x = 0; x < size; x++)
for (y = 0; y < size; y++)
{
heightmap[x+y*size] = 0;
}
}
else
{
size = sqrt(com_filesize/2);
if (size % numsegs)
{
Con_Printf(CON_ERROR "%s, heightmap is not a multiple of %i\n", mod->name, numsegs);
return false;
}
}
hm = Hunk_Alloc(sizeof(*hm) + com_filesize);
hm = Hunk_Alloc(sizeof(*hm) + size*size*2);
memset(hm, 0, sizeof(*hm));
Q_strncpyz(hm->hmapname, heightmapname, sizeof(hm->hmapname));
hm->heights = (unsigned short*)(hm+1);
for (x = 0; x < size*size; x++)
{
hm->heights[x] = LittleShort(heightmap[x]);
}
memcpy(hm->heights, heightmap, com_filesize);
hm->terrainsize = size;
hm->terrainscale = worldsize;
hm->heightscale = heightsize;
hm->numsegs = numsegs;
hm->shader = R_RegisterShader(basetexname,
"{\n"
"{\n"
"map maps/test/ground.jpg\n"
"}\n"
"}\n"
);
hm->skyshader = R_RegisterCustom(va("skybox_%s", skyname), Shader_DefaultSkybox, NULL);
mod->entities = COM_LoadHunkFile(entfile);
if (qrenderer != QR_NONE)
@ -772,6 +938,7 @@ qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer)
for (y = 0; y < numsegs; y++)
{
hm->textures[x+y*SECTIONS] = R_LoadHiResTexture(va("%s%02ix%02i%s", basetexname, x, y, exttexname), "", IF_CLAMP|IF_NOGAMMA);
hm->modified[x+y*SECTIONS] = true;
}
}
}

View file

@ -659,6 +659,12 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
break;
#endif
#ifdef INTERQUAKEMODELS
case ('I'<<0)+('N'<<8)+('T'<<16)+('E'<<24):
if (!Mod_LoadInterQuakeModel (mod, buf))
continue;
break;
#endif
//Binary Sprites
#ifdef SP2MODELS
@ -3238,6 +3244,7 @@ void * RMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
"{\n"
"map $diffuse\n"
"alphafunc ge128\n"
"depthwrite\n"
"rgbgen entity\n"
"alphagen entity\n"
"}\n"

View file

@ -925,7 +925,7 @@ qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model);
qboolean Heightmap_Edit(model_t *mod, int action, float *pos, float radius, float quant);
#ifdef Q2BSPS

View file

@ -117,7 +117,7 @@ void GLSCR_UpdateScreen (void)
R2D_BrightenScreen();
if (key_dest == key_console)
Con_DrawConsole(vid_conheight.value/2, false);
Con_DrawConsole(vid.height/2, false);
GL_EndRendering ();
GL_DoSwap();
RSpeedEnd(RSPEED_TOTALREFRESH);

View file

@ -227,6 +227,22 @@ static qboolean Shader_EvaluateCondition(char **ptr)
else if (!Q_stricmp(token, "normalmap") )
conditiontrue = conditiontrue == !!gl_bump.value;
else if (!Q_stricmp(token, "gles") )
{
#ifdef GLQUAKE
conditiontrue = conditiontrue == ((qrenderer == QR_OPENGL) && !!gl_config.gles);
#else
conditiontrue = conditiontrue == false;
#endif
}
else if (!Q_stricmp(token, "nofixed") )
{
#ifdef GLQUAKE
conditiontrue = conditiontrue == ((qrenderer == QR_OPENGL) && !!gl_config.nofixedfunc);
#else
conditiontrue = conditiontrue == false;
#endif
}
else if (!Q_stricmp(token, "glsl") )
{
#ifdef GLQUAKE
@ -915,15 +931,15 @@ struct sbuiltin_s
"}\n"
"#endif\n"
},
{QR_OPENGL, 130, "defaultwall",
"#version 130\n"
{QR_OPENGL, 110, "defaultwall",
"!!cvarf gl_overbright\n"
"#version 110\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"in vec3 v_position;\n"
"in vec2 v_texcoord;\n"
"in vec2 v_lmcoord;\n"
"out vec2 tc, lm;\n"
"uniform mat4 m_modelview, m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n"
"varying vec2 tc, lm;\n"
"void main (void)\n"
"{\n"
@ -939,14 +955,16 @@ struct sbuiltin_s
//"uniform sampler2D s_t2;\n" /*tex_normalmap*/
//"uniform sampler2D s_t3;\n" /*tex_deluxmap*/
//"uniform sampler2D s_t4;\n" /*tex_fullbright*/
"in vec2 tc, lm;\n"
"varying vec2 tc, lm;\n"
"uniform float cvar_gl_overbright;\n"
"void main (void)\n"
"{\n"
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm);\n"
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(cvar_gl_overbright, cvar_gl_overbright, cvar_gl_overbright, 1);\n"
"}\n"
"#endif\n"
},
/*FIXME: this doesn't match the gl3 version*/
{QR_OPENGL/*ES*/, 100, "defaultwall",
"!!permu FULLBRIGHT\n"
//"#version 100\n"
@ -1004,7 +1022,7 @@ struct sbuiltin_s
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D watertexture;\n"
"uniform mediump float e_time;\n"
"uniform lowp float r_wateralpha;\n"
"uniform lowp float cvar_r_wateralpha;\n"
"void main (void)\n"
"{\n"
@ -1013,7 +1031,7 @@ struct sbuiltin_s
" ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
" lowp vec3 ts = vec3(texture2D(watertexture, ntc));\n"
" gl_FragColor = vec4(ts, r_wateralpha);\n"
" gl_FragColor = vec4(ts, cvar_r_wateralpha);\n"
"}\n"
"#endif\n"
},
@ -1022,17 +1040,21 @@ struct sbuiltin_s
"#version 110\n"
"varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"attribute vec2 v_texcoord;\n"
"void main (void)\n"
"{\n"
" tc = gl_MultiTexCoord0.st;\n"
" gl_Position = ftransform();\n"
" tc = v_texcoord.st;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform float e_time;\n"
"uniform float r_wateralpha;\n"
"uniform float cvar_r_wateralpha;\n"
"void main (void)\n"
"{\n"
@ -1041,7 +1063,7 @@ struct sbuiltin_s
" ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
" vec3 ts = vec3(texture2D(s_t0, ntc));\n"
" gl_FragColor = vec4(ts, r_wateralpha);\n"
" gl_FragColor = vec4(ts, cvar_r_wateralpha);\n"
"}\n"
"#endif\n"
},
@ -1091,12 +1113,15 @@ struct sbuiltin_s
{QR_OPENGL, 110, "defaultsky",
"#version 110\n"
"#ifdef VERTEX_SHADER\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n"
"attribute vec3 v_position;\n"
"varying vec3 pos;\n"
"void main (void)\n"
"{\n"
" pos = gl_Vertex.xyz;\n"
" gl_Position = ftransform();\n"
" pos = v_position.xyz;\n"
" gl_Position = m_projection * m_modelview * vec4(v_position, 1.0);\n"
"}\n"
"#endif\n"
@ -1447,7 +1472,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames)
if (!prog->handle[p].glsl)
continue;
GLSlang_UseProgram(prog->handle[p].glsl);
uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, u[i].name);
uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, va("cvar_%s", tmpname));
if (uniformloc != -1)
qglUniform1fARB(uniformloc, cvar->value);
}
@ -1791,6 +1816,7 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t
{
pass->texgen = T_GEN_DIFFUSE;
pass->tcgen = TC_GEN_BASE;
shader->flags |= SHADER_NOIMAGE;
}
else if (!Q_stricmp (tname, "$normalmap"))
{
@ -2626,6 +2652,7 @@ void Shader_Free (shader_t *shader)
if (shader->bucket.data == shader)
Hash_RemoveData(&shader_active_hash, shader->name, shader);
shader->bucket.data = NULL;
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL && shader->prog)
@ -2657,6 +2684,25 @@ void Shader_Free (shader_t *shader)
shader->numpasses = 0;
}
void Shader_Reset(shader_t *s)
{
char name[MAX_QPATH];
int uses = s->uses;
shader_gen_t *defaultgen = s->generator;
const char *genargs = s->genargs;
texnums_t dt = s->defaulttextures;
Q_strncpyz(name, s->name, sizeof(name));
Shader_Free(s);
memset(s, 0, sizeof(*s));
s->defaulttextures = dt;
s->generator = defaultgen;
s->genargs = genargs;
s->uses = uses;
Q_strncpyz(s->name, name, sizeof(s->name));
Hash_Add(&shader_active_hash, s->name, s, &s->bucket);
}
void Shader_Shutdown (void)
{
int i;
@ -3057,14 +3103,9 @@ void Shader_Finish (shader_t *s)
s->flags = 0;
if (!(s->flags & SHADER_SKY))
{
char name[MAX_QPATH];
Q_strncpyz(name, s->name, sizeof(name));
Shader_Free(s);
memset(s, 0, sizeof(*s));
Shader_Reset(s);
Q_strncpyz(s->name, name, sizeof(s->name));
Shader_DefaultScript(name, s,
Shader_DefaultScript(s->name, s,
"{\n"
"sort sky\n"
"{\n"
@ -3078,6 +3119,9 @@ void Shader_Finish (shader_t *s)
}
}
if (TEXVALID(s->defaulttextures.base))
s->flags &= ~SHADER_NOIMAGE;
if (!s->numpasses && !(s->flags & (SHADER_NODRAW|SHADER_SKY)) && !s->fog_dist)
{
pass = &s->passes[s->numpasses++];
@ -3375,7 +3419,11 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader)
/*dlights/realtime lighting needs some stuff*/
if (!TEXVALID(tn->base))
{
tn->base = R_LoadHiResTexture(shader->name, NULL, IF_NOALPHA);
}
if (TEXVALID(tn->base))
shader->flags &= ~SHADER_NOIMAGE;
if (gl_bump.ival)
{
@ -3716,8 +3764,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args)
return;
builtin = NULL;
/*if the r_skybox failed to load or whatever, reset and fall through and just use the regular sky*/
Shader_Free(s);
memset (s, 0, sizeof(*s));
Shader_Reset(s);
}
if (!builtin)
builtin = (
@ -3898,9 +3945,10 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
{
Shader_DefaultScript(shortname, s,
"{\n"
#ifdef USE_EGL
"if $nofixed\n"
"[\n"
"program default2d\n"
#endif
"]\n"
"nomipmaps\n"
"{\n"
"clampmap $diffuse\n"
@ -3917,10 +3965,18 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
{
unsigned char data[4*4] = {0};
s->defaulttextures.base = R_LoadTexture8("black", 4, 4, data, 0, 0);
s->flags |= SHADER_NOIMAGE;
s->width = 64;
s->height = 64;
}
else
{
s->flags &= ~SHADER_NOIMAGE;
s->width = image_width;
s->height = image_height;
}
}
//loads a shader string into an existing shader object, and finalises it and stuff
static void Shader_ReadShader(shader_t *s, char *shadersource)
@ -4010,10 +4066,7 @@ static qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s)
return false;
}
Shader_Free(s);
memset ( s, 0, sizeof( shader_t ) );
Com_sprintf ( s->name, MAX_QPATH, "%s",usename ); // warning: format not a string literal and no format arguments
Hash_Add(&shader_active_hash, s->name, s, &s->bucket);
Shader_Reset(s);
Shader_ReadShader(s, file);
@ -4037,6 +4090,10 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
char shortname[MAX_QPATH];
shader_t *s;
if (!*name)
name = "gfx/white";
*(int*)shortname = 0;
COM_StripExtension ( name, shortname, sizeof(shortname));
COM_CleanUpPath(shortname);
@ -4071,6 +4128,10 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
s = &r_shaders[f];
Q_strncpyz(s->name, shortname, sizeof(s->name));
s->generator = defaultgen;
s->genargs = genargs;
if (ruleset_allow_shaders.ival)
{
#ifdef GLQUAKE
@ -4080,8 +4141,6 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
{
if (Shader_ParseShader(va("%s_gles2", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
@ -4089,8 +4148,6 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
{
if (Shader_ParseShader(va("%s_glsl3", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
@ -4098,8 +4155,6 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
{
if (Shader_ParseShader(va("%s_glsl", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
@ -4111,8 +4166,6 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
{
if (Shader_ParseShader(va("%s_hlsl", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
@ -4120,18 +4173,16 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
#endif
if (Shader_ParseShader(shortname, shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
return f;
}
}
// make a default shader
if (defaultgen)
if (s->generator)
{
memset(s, 0, sizeof(shader_t));
Com_sprintf(s->name, MAX_QPATH, "%s", shortname); // warning: format not a string literal and no format arguments
Shader_Reset(s);
if (!strcmp(shortname, "textures/common/clip"))
Shader_DefaultScript(shortname, s,
"{\n"
@ -4139,13 +4190,13 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
"surfaceparm nodlight\n"
"}\n");
else
defaultgen(shortname, s, genargs);
Hash_Add(&shader_active_hash, s->name, s, &s->bucket);
s->generator = defaultgen;
s->genargs = genargs;
s->generator(shortname, s, s->genargs);
return f;
}
else
{
r_shaders[i].uses = 0;
}
return -1;
}
@ -4154,9 +4205,6 @@ void Shader_DoReload(void)
shader_t *s;
unsigned int i;
char shortname[MAX_QPATH];
shader_gen_t *defaultgen;
const char *genargs;
texnums_t oldtn;
if (shader_rescan_needed && ruleset_allow_shaders.ival)
{
@ -4182,10 +4230,6 @@ void Shader_DoReload(void)
if (!s->uses)
continue;
defaultgen = s->generator;
genargs = s->genargs;
oldtn = s->defaulttextures;
strcpy(shortname, s->name);
if (ruleset_allow_shaders.ival)
{
@ -4194,33 +4238,20 @@ void Shader_DoReload(void)
{
if (Shader_ParseShader(va("%s_glsl", shortname), shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
R_BuildDefaultTexnums(&oldtn, s);
continue;
}
}
#endif
if (Shader_ParseShader(shortname, shortname, s))
{
s->generator = defaultgen;
s->genargs = genargs;
R_BuildDefaultTexnums(&oldtn, s);
continue;
}
}
if (s->generator)
{
Shader_Free(s);
memset ( s, 0, sizeof( shader_t ) );
Shader_Reset(s);
defaultgen(shortname, s, genargs);
s->generator = defaultgen;
s->genargs = genargs;
Com_sprintf ( s->name, MAX_QPATH, "%s", shortname ); // warning: format not a string literal and no format arguments
Hash_Add(&shader_active_hash, s->name, s, &s->bucket);
R_BuildDefaultTexnums(&oldtn, s);
s->generator(shortname, s, s->genargs);
}
}
}

View file

@ -714,19 +714,16 @@ static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *v
}
#endif
static void SHM_MarkLeavesQ1(dlight_t *dl, unsigned char *lvis, unsigned char *vvis)
static void SHM_MarkLeavesQ1(dlight_t *dl, unsigned char *lvis)
{
mnode_t *node;
int i;
sh_shadowframe++;
if (!dl->die || !vvis)
{
//static
//variation on mark leaves
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
{
if (lvis[i>>3] & (1<<(i&7)))// && vvis[i>>3] & (1<<(i&7)))
if (lvis[i>>3] & (1<<(i&7)))
{
node = (mnode_t *)&cl.worldmodel->leafs[i+1];
do
@ -739,26 +736,6 @@ static void SHM_MarkLeavesQ1(dlight_t *dl, unsigned char *lvis, unsigned char *v
}
}
}
else
{
//dynamic lights will be discarded after this frame anyway, so only include leafs that are visible
//variation on mark leaves
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
{
if (lvis[i>>3] & vvis[i>>3] & (1<<(i&7)))
{
node = (mnode_t *)&cl.worldmodel->leafs[i+1];
do
{
if (node->shadowframe == sh_shadowframe)
break;
node->shadowframe = sh_shadowframe;
node = node->parent;
} while (node);
}
}
}
}
#ifdef Q3BSPS
void SHM_RecursiveWorldNodeQ3_r (dlight_t *dl, mnode_t *node)
@ -893,7 +870,7 @@ static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned cha
if (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife)
{
SHM_BeginShadowMesh(dl);
SHM_MarkLeavesQ1(dl, lvis, vvis);
SHM_MarkLeavesQ1(dl, lvis);
SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes);
}
#ifdef Q3BSPS
@ -980,6 +957,8 @@ static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned cha
static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2)
{
int i, m;
if (!v2)
return false;
m = (cl.worldmodel->numleafs-1)>>3;
for (i=0 ; i<m ; i++)
{

View file

@ -352,8 +352,17 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
else
gl_config.gles = false;
gl_config.nofixedfunc = (gl_config.gles && gl_config.glversion >= 2) /*||
(!gl_config.gles && gl_config.glversion >= 3 && noncompat)*/;
if (gl_config.gles)
gl_config.nofixedfunc = gl_config.glversion >= 2;
else
{
/*in gl3.0 things are depricated but not removed*/
/*in gl3.1 depricated things are removed unless compatibility is present*/
if (gl_config.glversion >= 3.1)
gl_config.nofixedfunc = !GL_CheckExtension("GL_ARB_compatibility");
else
gl_config.nofixedfunc = false;
}
//multitexture
gl_mtexable = false;
@ -1022,6 +1031,16 @@ void GL_Init(void *(*getglfunction) (char *name))
qglDrawRangeElements = GL_DrawRangeElementsEmul;
}
else if (gl_config.nofixedfunc)
{
qglLoadMatrixf = NULL;
qglPolygonMode = NULL;
qglShadeModel = NULL;
qglDepthRange = NULL;
qglEnableClientState = GL_ClientStateStub;
qglDisableClientState = GL_ClientStateStub;
}
qglClearColor (0,0,0,0); //clear to black so that it looks a little nicer on start.
qglClear(GL_COLOR_BUFFER_BIT);

View file

@ -1001,7 +1001,7 @@ qboolean VID_AttachGL (rendererstate_t *info)
if ((opengl3 = qwglCreateContextAttribsARB(maindc, NULL, attribs)))
{
qwglMakeCurrent(NULL, NULL);
qwglMakeCurrent(maindc, NULL);
qwglDeleteContext(baseRC);
baseRC = opengl3;

View file

@ -447,7 +447,7 @@ static void gl_skyspherecalc(int skytype)
static void GL_SkyForceDepth(batch_t *batch)
{
if (!cls.allow_skyboxes) //allow a little extra fps.
if (!cls.allow_skyboxes && batch->texture) //allow a little extra fps.
{
BE_SelectMode(BEM_DEPTHONLY);
BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, &batch->texture->vbo, &batch->shader->defaulttextures, batch->flags);

View file

@ -342,7 +342,7 @@ void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_a
// gl_heightmap.c
//
#ifdef GLQUAKE
void GL_DrawHeightmapModel (entity_t *e);
void GL_DrawHeightmapModel (batch_t **batch, entity_t *e);
qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer);
#endif

View file

@ -367,7 +367,7 @@ struct shader_s
SHADER_DEFORMV_BULGE = 1 << 5,
SHADER_AUTOSPRITE = 1 << 6,
SHADER_FLARE = 1 << 7,
// SHADER_REMOVED = 1 << 8,
SHADER_NOIMAGE = 1 << 8,
SHADER_ENTITY_MERGABLE = 1 << 9,
SHADER_VIDEOMAP = 1 << 10,
SHADER_DEPTHWRITE = 1 << 11,

View file

@ -525,18 +525,20 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
}
if (cl->dataislisten) //accept a connect.
{
int err;
int _true = true;
int temp;
struct sockaddr_in adr;
int adrlen = sizeof(adr);
temp = accept(cl->datasock, (struct sockaddr *)&adr, &adrlen);
err = qerrno;
closesocket(cl->datasock);
cl->datasock = temp;
cl->dataislisten = false;
if (cl->datasock == INVALID_SOCKET)
{
QueueMessageva (cl, "425 Your client connected too slowly - %i.\r\n", qerrno);
QueueMessageva (cl, "425 Your client connected too slowly - %i.\r\n", err);
continue;
}
else

View file

@ -49,11 +49,11 @@ cont: //last statement may have been a breakpoint
st = pr_statements + s;
reeval:
switch (st->op & ~0x8000)
#else
st++;
#endif
switch (st->op)
#endif
{
case OP_ADD_F:
OPC->_float = OPA->_float + OPB->_float;
@ -1109,14 +1109,6 @@ if (pr_typecurrent != 0)
st = &pr_statements[s]; //let the user move execution
pr_xstatement = s = st-pr_statements;
#if 0 //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement
memcpy(&fakeop, st, sizeof(dstatement_t)); //don't hit the new statement as a break point, cos it's probably the same one.
fakeop.op &= ~0x8000;
st = &fakeop; //a little remapping...
#else
st->op &= ~0x8000; //just remove the breakpoint and go around again, but this time in the debugger.
#endif
goto reeval; //reexecute
}
pr_xstatement = st-pr_statements;

View file

@ -252,7 +252,44 @@ func_t PR_FindFunc(progfuncs_t *progfuncs, char *funcname, progsnum_t pnum)
return 0;
}
eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum)
void QC_FindPrefixedGlobals(progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) )
{
unsigned int i;
ddef16_t *def16;
ddef32_t *def32;
int len = strlen(prefix);
unsigned int pnum;
for (pnum = 0; pnum < maxprogs; pnum++)
{
if (!pr_progstate[pnum].progs)
continue;
switch(pr_progstate[pnum].structtype)
{
case PST_DEFAULT:
case PST_KKQWSV:
for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
{
def16 = &pr_progstate[pnum].globaldefs16[i];
if (!strncmp(def16->s_name+progfuncs->stringtable,prefix, len))
found(progfuncs, def16->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def16->ofs], def16->type);
}
break;
case PST_QTEST:
case PST_FTE32:
for (i=1 ; i<pr_progstate[pnum].progs->numglobaldefs ; i++)
{
def32 = &pr_progstate[pnum].globaldefs32[i];
if (!strncmp(def32->s_name+progfuncs->stringtable,prefix, len))
found(progfuncs, def32->s_name+progfuncs->stringtable, (eval_t *)&pr_progstate[pnum].globals[def32->ofs], def32->type);
}
break;
}
}
}
eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum, etype_t *type)
{
unsigned int i;
ddef16_t *var16;
@ -266,7 +303,7 @@ eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum)
{
if (!pr_progstate[i].progs)
continue;
ev = PR_FindGlobal(progfuncs, globname, i);
ev = PR_FindGlobal(progfuncs, globname, i, type);
if (ev)
return ev;
}
@ -281,12 +318,16 @@ eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum)
if (!(var16 = ED_FindGlobalFromProgs16(progfuncs, globname, pnum)))
return NULL;
if (type)
*type = var16->type;
return (eval_t *)&pr_progstate[pnum].globals[var16->ofs];
case PST_QTEST:
case PST_FTE32:
if (!(var32 = ED_FindGlobalFromProgs32(progfuncs, globname, pnum)))
return NULL;
if (type)
*type = var32->type;
return (eval_t *)&pr_progstate[pnum].globals[var32->ofs];
}
Sys_Error("Error with def size (PR_FindGlobal)");
@ -646,7 +687,8 @@ progfuncs_t deffuncs = {
PR_StringToNative,
0,
PR_QueryField,
QC_ClearEdict
QC_ClearEdict,
QC_FindPrefixedGlobals
};
#undef printf

View file

@ -502,10 +502,17 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
sprintf (line, "%s", PR_StringToNative(progfuncs, val->string));
break;
case ev_entity:
// if (val->edict >= maxedicts)
fielddef = ED_FindField(progfuncs, "classname");
if (fielddef && val->edict < sv_num_edicts)
{
edictrun_t *ed;
string_t *v;
ed = (edictrun_t *)EDICT_NUM(progfuncs, val->edict);
v = (string_t *)((char *)edvars(ed) + fielddef->ofs*4);
sprintf (line, "entity %i(%s)", val->edict, PR_StringToNative(progfuncs, *v));
}
else
sprintf (line, "entity %i", val->edict);
// else
// sprintf (line, "entity %i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)) );
break;
case ev_function:
if (!val->function)
@ -3095,7 +3102,7 @@ retry:
if (progfuncs->stringtablesize + progfuncs->stringtable < pr_strings + pr_progs->numstrings)
progfuncs->stringtablesize = (pr_strings + pr_progs->numstrings) - progfuncs->stringtable;
eval = PR_FindGlobal(progfuncs, "thisprogs", progstype);
eval = PR_FindGlobal(progfuncs, "thisprogs", progstype, NULL);
if (eval)
eval->prog = progstype;
@ -3157,7 +3164,7 @@ retry:
break;
}
eval = PR_FindGlobal(progfuncs, "__ext__fasttrackarrays", PR_CURRENT);
eval = PR_FindGlobal(progfuncs, "__ext__fasttrackarrays", PR_CURRENT, NULL);
if (eval) //we support these opcodes
eval->_float = true;

View file

@ -90,6 +90,8 @@ progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_
{
current_progstate->builtins = builtins;
current_progstate->numbuiltins = numbuiltins;
if (a <= progfuncs->numprogs)
progfuncs->numprogs = a+1;
#ifdef QCJIT
if (prinst->usejit)

View file

@ -445,7 +445,7 @@ var(unsigned int, addressablesize);
} prinst_t;
extern vec3_t vec3_origin;
eval_t *PR_FindGlobal(progfuncs_t *prfuncs, char *globname, progsnum_t pnum);
eval_t *PR_FindGlobal(progfuncs_t *prfuncs, char *globname, progsnum_t pnum, etype_t *type);
ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type);
ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type);
ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum);

View file

@ -86,7 +86,7 @@ struct progfuncs_s {
char *(*saveent) (progfuncs_t *prinst, char *buf, int *size, struct edict_s *ed); //will save just one entities vars
struct edict_s *(*restoreent) (progfuncs_t *prinst, char *buf, int *size, struct edict_s *ed); //will restore the entity that had it's values saved (can use NULL for ed)
union eval_s *(*FindGlobal) (progfuncs_t *prinst, char *name, progsnum_t num); //find a pointer to the globals value
union eval_s *(*FindGlobal) (progfuncs_t *prinst, char *name, progsnum_t num, etype_t *type); //find a pointer to the globals value
char *(*AddString) (progfuncs_t *prinst, char *val, int minlength); //dump a string into the progs memory (for setting globals and whatnot)
void *(*Tempmem) (progfuncs_t *prinst, int ammount, char *whatfor); //grab some mem for as long as the progs stays loaded
@ -137,6 +137,7 @@ struct progfuncs_s {
int (*QueryField) (progfuncs_t *prinst, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache); //find info on a field definition at an offset
void (*EntClear) (progfuncs_t *progfuncs, struct edict_s *e);
void (*FindPrefixGlobals) (progfuncs_t *progfuncs, char *prefix, void (*found) (progfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type) );
};
typedef struct progexterns_s {
@ -249,7 +250,7 @@ typedef union eval_s
#define PR_PrintEdict(pf,ed) (*pf->PrintEdict) (pf, ed)
#define PR_FindFunction(pf, name, num) (*pf->FindFunction) (pf, name, num)
#define PR_FindGlobal(pf, name, progs) (*pf->FindGlobal) (pf, name, progs)
#define PR_FindGlobal(pf, name, progs, type) (*pf->FindGlobal) (pf, name, progs, type)
#define PR_AddString(pf, ed, len) (*pf->AddString) (pf, ed, len)
#define PR_Alloc(pf,size) (*pf->Tempmem) (pf, size)

View file

@ -178,7 +178,6 @@ extern char qccmsourcedir[];
void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
{
char fullname[1024];
char *stripfrom;
int doubledots;
char *end = fullname;
@ -187,6 +186,7 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
return;
doubledots = 0;
/*count how far up we need to go*/
while(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
{
newfile+=3;
@ -195,26 +195,31 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, char *rootpath)
currentfile += strlen(rootpath); //could this be bad?
for(stripfrom = currentfile+strlen(currentfile)-1; stripfrom>currentfile; stripfrom--)
{
if (*stripfrom == '/' || *stripfrom == '\\')
{
if (doubledots>0)
doubledots--;
else
{
stripfrom++;
break;
}
}
}
strcpy(end, rootpath); end = end+strlen(end);
strcpy(fullname, rootpath);
end = fullname+strlen(end);
if (*fullname && end[-1] != '/')
{
strcpy(end, "/");
end = end+strlen(end);
}
strncpy(end, currentfile, stripfrom - currentfile); end += stripfrom - currentfile; *end = '\0';
strcpy(end, currentfile);
end = end+strlen(end);
while (end > fullname)
{
end--;
/*stop at the slash, unless we're meant to go further*/
if (*end == '/' || *end == '\\')
{
if (!doubledots)
{
end++;
break;
}
doubledots--;
}
}
strcpy(end, newfile);
QCC_Include(fullname);

View file

@ -2858,7 +2858,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
MAX_REGS = 65536;
MAX_STRINGS = 1000000;
MAX_GLOBALS = 32768;
MAX_GLOBALS = 65535;
MAX_FIELDS = 2048;
MAX_STATEMENTS = 0x80000;
MAX_FUNCTIONS = 16384;

View file

@ -575,6 +575,7 @@ static int multicastpos; //writecoord*3 offset
static int multicasttype;
static int requireextension;
static qboolean ignoreprotocol;
static int te_515sevilhackworkaround;
#define svc_setfrags 14
#define svc_updatecolors 17
@ -713,6 +714,22 @@ void NPP_NQFlush(void)
case svc_temp_entity:
switch (buffer[1])
{
default:
if (te_515sevilhackworkaround)
{
/*shift the data up by two bytes, but don't care about the first byte*/
memmove(buffer+3, buffer+1, bufferlen-1);
/*replace the svc itself*/
buffer[0] = svcfte_cgamepacket;
/*add a length in the 2nd/3rd bytes*/
buffer[1] = (bufferlen-1);
buffer[2] = (bufferlen-1) >> 8;
bufferlen += 2;
}
break;
case TENQ_EXPLOSION2: //happens with rogue.
bufferlen -= 2; //trim the colour
buffer[1] = TE_EXPLOSION;
@ -852,6 +869,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
break;
case svc_sound:
case svc_temp_entity:
te_515sevilhackworkaround = false;
break;
case svc_setangle:
protocollen = sizeof(qbyte) + destprim->anglesize*3;
@ -1044,6 +1062,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
default:
protocollen = sizeof(buffer);
te_515sevilhackworkaround = true;
Con_Printf("NQWriteByte: bad tempentity %i\n", data);
PR_StackTrace(svprogfuncs);
break;
@ -1456,6 +1475,22 @@ void NPP_QWFlush(void)
case svc_temp_entity:
switch(minortype)
{
default:
if (te_515sevilhackworkaround)
{
/*shift the data up by two bytes*/
memmove(buffer+3, buffer+1, bufferlen-1);
/*replace the svc itself*/
buffer[0] = svcfte_cgamepacket;
/*add a length in the 2nd/3rd bytes*/
buffer[1] = (bufferlen-1);
buffer[2] = (bufferlen-1) >> 8;
bufferlen += 2;
}
break;
case TEQW_LIGHTNINGBLOOD:
case TEQW_BLOOD: //needs to be converted to a particle
{

View file

@ -61,6 +61,7 @@ cvar_t pr_fixbrokenqccarrays = SCVARF("pr_fixbrokenqccarrays", "1", CVAR_LATCH);
cvar_t pr_maxedicts = SCVARF("pr_maxedicts", "2048", CVAR_LATCH);
cvar_t pr_no_playerphysics = SCVARF("pr_no_playerphysics", "0", CVAR_LATCH);
cvar_t pr_no_parsecommand = SCVARF("pr_no_parsecommand", "0", 0);
cvar_t progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER);
cvar_t qc_nonetaccess = SCVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc.
@ -496,6 +497,9 @@ void PR_Deinit(void)
Z_FreeTags(Z_QC_TAG);
}
#ifdef TEXTEDITOR
Editor_ProgsKilled(svprogfuncs);
#endif
svprogfuncs=NULL;
//clear out function pointers (so changing game modes cannot lead to confusions)
@ -524,12 +528,12 @@ void PR_LoadGlabalStruct(void)
int i;
int *v;
nqglobalvars_t *pr_globals = pr_nqglobal_struct;
#define globalfloat(need,name) ((nqglobalvars_t*)pr_nqglobal_struct)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n");
#define globalint(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalvec_(need,name) ((nqglobalvars_t*)pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) {static func_t strippedout; strippedout = PR_FindFunction(svprogfuncs, #name, 0); if (strippedout) ((nqglobalvars_t*)pr_globals)->name = &strippedout; else SV_Error("Could not find function \""#name"\" in progs\n"); }
#define globalfloat(need,name) ((nqglobalvars_t*)pr_nqglobal_struct)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n");
#define globalint(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalvec_(need,name) ((nqglobalvars_t*)pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) {static func_t strippedout; strippedout = PR_FindFunction(svprogfuncs, #name, 0); if (strippedout) ((nqglobalvars_t*)pr_globals)->name = &strippedout; else SV_Error("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);
@ -587,7 +591,7 @@ void PR_LoadGlabalStruct(void)
memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed));
for (i = 0; i < NUM_SPAWN_PARMS; i++)
spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0);
spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0, NULL);
#define ensurefloat(name,var) if (!((nqglobalvars_t*)pr_globals)->name) ((nqglobalvars_t*)pr_globals)->name = &var;
@ -599,19 +603,19 @@ void PR_LoadGlabalStruct(void)
// qtest renames and missing variables
if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal)
{
((nqglobalvars_t*)pr_globals)->V_trace_plane_normal = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_normal", 0);
((nqglobalvars_t*)pr_globals)->V_trace_plane_normal = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_normal", 0, NULL);
if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal)
SV_Error("Could not find export trace_plane_normal in progs\n");
}
if (!((nqglobalvars_t*)pr_globals)->V_trace_endpos)
{
((nqglobalvars_t*)pr_globals)->V_trace_endpos = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_impact", 0);
((nqglobalvars_t*)pr_globals)->V_trace_endpos = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_impact", 0, NULL);
if (!((nqglobalvars_t*)pr_globals)->V_trace_endpos)
SV_Error("Could not find export trace_endpos in progs\n");
}
if (!((nqglobalvars_t*)pr_globals)->trace_fraction)
{
((nqglobalvars_t*)pr_globals)->trace_fraction = (float *)PR_FindGlobal(svprogfuncs, "trace_frac", 0);
((nqglobalvars_t*)pr_globals)->trace_fraction = (float *)PR_FindGlobal(svprogfuncs, "trace_frac", 0, NULL);
if (!((nqglobalvars_t*)pr_globals)->trace_fraction)
SV_Error("Could not find export trace_fraction in progs\n");
}
@ -669,7 +673,7 @@ void PR_LoadGlabalStruct(void)
QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->other-v, 1);
QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->time-v, 1);
pr_items2 = !!PR_FindGlobal(svprogfuncs, "items2", 0);
pr_items2 = !!PR_FindGlobal(svprogfuncs, "items2", 0, NULL);
SV_ClearQCStats();
@ -826,6 +830,8 @@ progsnum_t AddProgs(char *name)
Con_Printf("Loaded %s\n", name);
PR_AutoCvarSetup(svprogfuncs);
if (!svs.numprogs)
{
PF_InitTempStrings(svprogfuncs);
@ -1055,6 +1061,7 @@ void PR_Init(void)
Cvar_Register(&pr_maxedicts, cvargroup_progs);
Cvar_Register(&pr_no_playerphysics, cvargroup_progs);
Cvar_Register(&pr_no_parsecommand, cvargroup_progs);
for (i = 0; i < MAXADDONS; i++)
{
@ -1098,6 +1105,14 @@ void PR_Init(void)
#endif
}
void SVQ1_CvarChanged(cvar_t *var)
{
if (svprogfuncs)
{
PR_AutoCvar(svprogfuncs, var);
}
}
void SV_RegisterH2CustomTents(void);
void Q_InitProgs(void)
{
@ -1563,6 +1578,10 @@ qboolean PR_KrimzonParseCommand(char *s)
if (!svprogfuncs)
return false;
/*some people are irresponsible*/
if (pr_no_parsecommand.ival)
return false;
if (gfuncs.ParseClientCommand)
{ //the QC is expected to send it back to use via a builtin.
@ -8711,6 +8730,19 @@ static void QCBUILTIN PF_SendPacket(progfuncs_t *prinst, struct globalvars_s *pr
NET_SendPacket(NS_SERVER, strlen(contents), contents, to);
}
static void QCBUILTIN PF_sv_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int action = G_FLOAT(OFS_PARM0);
float *pos = G_VECTOR(OFS_PARM1);
float radius = G_FLOAT(OFS_PARM2);
float quant = G_FLOAT(OFS_PARM3);
#if defined(TERRAIN)
G_FLOAT(OFS_RETURN) = Heightmap_Edit(sv.world.worldmodel, action, pos, radius, quant);
#else
G_FLOAT(OFS_RETURN) = false;
#endif
}
BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"fixme", PF_Fixme, 0, 0, 0},
{"ignore", PF_Ignore, 0, 0, 0},
@ -9017,7 +9049,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"globalstat", PF_globalstat, 0, 0, 0, 233}, //EXT_CSQC_1 actually
//END EXT_CSQC
{"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234},
//{"rotatevectorsbyangle", PF_rotatevectorsbyangles,0,0,0, 235}, // #235
//{"rotatevectorsbymatrix", PF_rotatevectorsbymatrix,0,0,0, 236}, // #236
{"skinforname", PF_skinforname, 0, 0, 0, 237}, // #237
{"shaderforname", PF_Fixme, 0, 0, 0, 238},
{"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239},
{"checkpvs", PF_checkpvs, 0, 0, 0, 240},
@ -9042,9 +9077,25 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"stoh", PF_stoh, 0, 0, 0, 261},
{"htos", PF_htos, 0, 0, 0, 262},
#if 0
{"skel_create", PF_skel_create, 0, 0, 0, 263},//float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_build", PF_skel_build, 0, 0, 0, 264},//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_get_numbones",PF_skel_get_numbones,0, 0, 0, 265},//float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_get_bonename",PF_skel_get_bonename,0, 0, 0, 266},//string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) (returns tempstring)
{"skel_get_boneparent",PF_skel_get_boneparent,0,0, 0, 267},//float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_find_bone", PF_skel_find_bone, 0, 0, 0, 268},//float(float skel, string tagname) skel_get_boneidx = #268; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_get_bonerel",PF_skel_get_bonerel,0, 0, 0, 269},//vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc)
{"skel_get_boneabs",PF_skel_get_boneabs,0, 0, 0, 270},//vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc)
{"skel_set_bone", PF_skel_set_bone, 0, 0, 0, 271},//void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc)
{"skel_mul_bone", PF_skel_mul_bone, 0, 0, 0, 272},//void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc)
{"skel_mul_bones", PF_skel_mul_bones, 0, 0, 0, 273},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #273; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc)
{"skel_copybones", PF_skel_copybones, 0, 0, 0, 274},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_delete", PF_skel_delete, 0, 0, 0, 275},//void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS)
#endif
{"frameforname", PF_frameforname, 0, 0, 0, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS)
{"frameduration", PF_frameduration, 0, 0, 0, 277},//float(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS)
{"terrain_edit", PF_sv_terrain_edit, 0, 0, 0, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??
//EXT_CSQC
// {"setmodelindex", PF_sv_SetModelIndex,0, 0, 0, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
@ -9268,6 +9319,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"precache_vwep_model",PF_precache_vwep_model,0,0, 0, 532}, // #532 float(string mname) precache_vwep_model
{"sprintf", PF_sprintf, 0, 0, 0, 627},
//don't exceed sizeof(pr_builtin)/sizeof(pr_builtin[0]) (currently 1024) without modifing the size of pr_builtin
{NULL}

View file

@ -463,7 +463,7 @@ static eval_t *Q1QVMPF_GetEdictFieldValue(progfuncs_t *pf, edict_t *e, char *fie
return NULL;
}
static eval_t *Q1QVMPF_FindGlobal (progfuncs_t *prinst, char *name, progsnum_t num)
static eval_t *Q1QVMPF_FindGlobal (progfuncs_t *prinst, char *name, progsnum_t num, etype_t *type)
{
return NULL;
}

View file

@ -28,6 +28,8 @@ struct edict_s;
#define NUM_SPAWN_PARMS 64 //moved from server.h because of include ordering :(.
void SVQ1_CvarChanged(cvar_t *var);
#define NewGetEdictFieldValue GetEdictFieldValue
void Q_SetProgsParms(qboolean forcompiler);
void PR_Deinit(void);

View file

@ -703,10 +703,10 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
if (!ignoreplayers)
{
eval = PR_FindGlobal(svprogfuncs, "startspot", 0);
eval = PR_FindGlobal(svprogfuncs, "startspot", 0, NULL);
if (eval) eval->_int = (int)PR_NewString(svprogfuncs, startspot, 0);
eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0);
eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL);
if (eval)
for (i=0 ; i<MAX_CLIENTS ; i++)
{

View file

@ -498,6 +498,7 @@ typedef struct client_s
qboolean csqcactive;
#ifdef PROTOCOL_VERSION_FTE
qboolean pextknown;
unsigned long fteprotocolextensions;
unsigned long fteprotocolextensions2;
#endif

View file

@ -524,29 +524,38 @@ void SV_Map_f (void)
}
else
{
snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level);
if (!COM_FCheckExists (expanded))
char *exts[] = {"maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", NULL};
int i, j;
for (i = 0; exts[i]; i++)
{
snprintf (expanded, sizeof(expanded), exts[i], level);
if (COM_FCheckExists (expanded))
break;
}
if (!exts[i])
{
for (i = 0; exts[i]; i++)
{
//doesn't exist, so try lowercase. Q3 does this.
for (i = 0; i < sizeof(level) && level[i]; i++)
for (j = 0; j < sizeof(level) && level[j]; j++)
{
if (level[i] >= 'A' && level[i] <= 'Z')
level[i] = level[i] - 'A' + 'a';
if (level[j] >= 'A' && level[j] <= 'Z')
level[j] = level[j] - 'A' + 'a';
}
snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level);
if (!COM_FCheckExists (expanded))
{
snprintf (expanded, sizeof(expanded), "maps/%s.cm", level);
if (!COM_FCheckExists (expanded))
snprintf (expanded, sizeof(expanded), exts[i], level);
if (COM_FCheckExists (expanded))
break;
}
if (!exts[i])
{
// FTE is still a Quake engine so report BSP missing
snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level);
snprintf (expanded, sizeof(expanded), exts[0], level);
Con_TPrintf (STL_CANTFINDMAP, expanded);
return;
}
}
}
}
if (sv.mvdrecording)
SV_MVDStop_f();

View file

@ -1093,15 +1093,13 @@ void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t
int SV_HullNumForPlayer(int h2hull, float *mins, float *maxs)
{
vec3_t size;
int diff;
int best;
int hullnum, i;
if (sv.world.worldmodel->fromgame != fg_quake)
{
VectorSubtract (maxs, mins, size);
return size[2]; //clients are expected to decide themselves.
return -mins[2] + 32; //clients are expected to decide themselves.
}
if (h2hull)

View file

@ -357,7 +357,7 @@ void SV_SaveSpawnparms (qboolean dontsave)
continue;
// call the progs to get default spawn parms for the new client
if (PR_FindGlobal(svprogfuncs, "ClientReEnter", 0))
if (PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL))
{//oooh, evil.
char buffer[65536];
int bufsize = sizeof(buffer);
@ -844,11 +844,16 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
}
else
{
char *exts[] = {"maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", NULL};
strcpy (sv.name, server);
sprintf (sv.modelname,"maps/%s.bsp", server);
sprintf (sv.modelname, exts[0], server);
if (!COM_FCheckExists(sv.modelname))
if (COM_FCheckExists(va("maps/%s.cm", server)))
sprintf (sv.modelname,"maps/%s.cm", server);
{
if (COM_FCheckExists(va(exts[1], server)))
sprintf (sv.modelname,exts[1], server);
else if (COM_FCheckExists(va(exts[2], server)))
sprintf (sv.modelname,exts[2], server);
}
}
sv.state = ss_loading;
sv.world.worldmodel = Mod_ForName (sv.modelname, true);
@ -1224,20 +1229,20 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
cvar_t *cv;
if (coop.value)
{
eval = PR_FindGlobal(svprogfuncs, "coop", 0);
eval = PR_FindGlobal(svprogfuncs, "coop", 0, NULL);
if (eval) eval->_float = coop.value;
}
else
{
eval = PR_FindGlobal(svprogfuncs, "deathmatch", 0);
eval = PR_FindGlobal(svprogfuncs, "deathmatch", 0, NULL);
if (eval) eval->_float = deathmatch.value;
}
cv = Cvar_Get("randomclass", "0", CVAR_LATCH, "Hexen2");
eval = PR_FindGlobal(svprogfuncs, "randomclass", 0);
eval = PR_FindGlobal(svprogfuncs, "randomclass", 0, NULL);
if (eval && cv) eval->_float = cv->value;
cv = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2");
eval = PR_FindGlobal(svprogfuncs, "cl_playerclass", 0);
eval = PR_FindGlobal(svprogfuncs, "cl_playerclass", 0, NULL);
if (eval && cv) eval->_float = cv->value;
}
else
@ -1459,7 +1464,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
if (svprogfuncs && startspot)
{
eval_t *eval;
eval = PR_FindGlobal(svprogfuncs, "startspot", 0);
eval = PR_FindGlobal(svprogfuncs, "startspot", 0, NULL);
if (eval) eval->string = PR_NewString(svprogfuncs, startspot, 0);
}

View file

@ -1082,7 +1082,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
if (svprogfuncs)
{
v = PR_FindGlobal(svprogfuncs, "worldstatus", PR_ANY);
v = PR_FindGlobal(svprogfuncs, "worldstatus", PR_ANY, NULL);
if (v)
gamestatus = PR_GetString(svprogfuncs, v->string);
else

View file

@ -1349,7 +1349,7 @@ void SV_QCStatGlobal(int type, char *globalname, int statnum)
if (type < 0)
return;
glob = svprogfuncs->FindGlobal(svprogfuncs, globalname, PR_ANY);
glob = svprogfuncs->FindGlobal(svprogfuncs, globalname, PR_ANY, NULL);
if (!glob)
{
Con_Printf("couldn't find named global for csqc stat (%s)\n", globalname);
@ -1398,6 +1398,7 @@ void SV_ClearQCStats(void)
numqcstats = 0;
}
extern cvar_t dpcompat_stats;
void SV_UpdateQCStats(edict_t *ent, int *statsi, char **statss, float *statsf)
{
char *s;
@ -1425,6 +1426,11 @@ void SV_UpdateQCStats(edict_t *ent, int *statsi, char **statss, float *statsf)
case ev_float:
statsf[qcstats[i].statnum] = eval->_float;
break;
case ev_vector:
statsf[qcstats[i].statnum+0] = eval->_vector[0];
statsf[qcstats[i].statnum+1] = eval->_vector[1];
statsf[qcstats[i].statnum+2] = eval->_vector[2];
break;
case ev_integer:
statsi[qcstats[i].statnum] = eval->_int;
break;
@ -1607,31 +1613,6 @@ void SV_UpdateClientStats (client_t *client, int pnum)
#ifdef PEXT_CSQC
if ((client->fteprotocolextensions & PEXT_CSQC) && (sv.csqcchecksum || progstype == PROG_H2))
{
if (statsf[i] && statsf[i] - (float)(int)statsf[i] == 0)
{
statsi[i] = statsf[i];
statsf[i] = 0;
}
else if (statsf[i] != client->statsf[i])
{
client->statsf[i] = statsf[i];
// client->statsi[i] = statsi[i];
if (pnum)
{
ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 8);
ClientReliableWrite_Byte(client->controller, pnum);
ClientReliableWrite_Byte(client->controller, svcfte_updatestatfloat);
ClientReliableWrite_Byte(client->controller, i);
ClientReliableWrite_Float(client->controller, statsf[i]);
}
else
{
ClientReliableWrite_Begin(client, svcfte_updatestatfloat, 6);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Float(client, statsf[i]);
}
}
if (statss[i] || client->statss[i])
if (strcmp(statss[i]?statss[i]:"", client->statss[i]?client->statss[i]:""))
{
@ -1652,14 +1633,63 @@ void SV_UpdateClientStats (client_t *client, int pnum)
}
}
}
else
#endif
if (!statsi[i])
if (dpcompat_stats.ival)
{
if (statsf[i])
{
statsi[i] = statsf[i];
if (statsi[i] != client->statsi[i])
statsf[i] = 0;
}
}
#endif
if (statsf[i])
{
if (statsf[i] != client->statsf[i])
{
if (statsf[i] - (float)(int)statsf[i] == 0 && statsf[i] >= 0 && statsf[i] <= 255)
{
if (pnum)
{
ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 5);
ClientReliableWrite_Byte(client->controller, pnum);
ClientReliableWrite_Byte(client->controller, svc_updatestat);
ClientReliableWrite_Byte(client->controller, i);
ClientReliableWrite_Byte(client->controller, statsf[i]);
}
else
{
ClientReliableWrite_Begin(client, svc_updatestat, 3);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Byte(client, statsf[i]);
}
}
else
{
if (pnum)
{
ClientReliableWrite_Begin(client->controller, svcfte_choosesplitclient, 8);
ClientReliableWrite_Byte(client->controller, pnum);
ClientReliableWrite_Byte(client->controller, svcfte_updatestatfloat);
ClientReliableWrite_Byte(client->controller, i);
ClientReliableWrite_Float(client->controller, statsf[i]);
}
else
{
ClientReliableWrite_Begin(client, svcfte_updatestatfloat, 6);
ClientReliableWrite_Byte(client, i);
ClientReliableWrite_Float(client, statsf[i]);
}
}
client->statsf[i] = statsf[i];
/*make sure statsf is correct*/
client->statsi[i] = statsf[i];
}
}
else if (statsi[i] != client->statsi[i])
{
client->statsi[i] = statsi[i];
client->statsf[i] = 0;
client->statsf[i] = statsi[i];
if (statsi[i] >=0 && statsi[i] <= 255)
{

View file

@ -406,6 +406,13 @@ void SVNQ_New_f (void)
char message[2048];
int i;
if (!host_client->pextknown)
{
MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
MSG_WriteString (&host_client->netchan.message, "cmd pext\n");
return;
}
MSG_WriteByte (&host_client->netchan.message, svc_print);
sprintf (message, "%c\n%s server\n", 2, version_string());
MSG_WriteString (&host_client->netchan.message,message);
@ -436,6 +443,18 @@ void SVNQ_New_f (void)
}
MSG_WriteByte (&host_client->netchan.message, svc_serverdata);
if (host_client->fteprotocolextensions)
{
MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION_FTE);
MSG_WriteLong (&host_client->netchan.message, host_client->fteprotocolextensions);
}
if (host_client->fteprotocolextensions2)
{
MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (&host_client->netchan.message, host_client->fteprotocolextensions2);
}
switch(host_client->protocol)
{
#ifdef NQPROT
@ -1119,9 +1138,15 @@ void SV_PreSpawn_f (void)
if (!sv.demofile || (sv.demofile && !sv.democausesreconnect)) //demo playing causes no check. If it's the return level, check anyway to avoid that loophole.
#endif
{
char *msg;
SV_ClientTPrintf (host_client, PRINT_HIGH,
STL_MAPCHEAT,
sv.modelname, check, sv.world.worldmodel->checksum, sv.world.worldmodel->checksum2);
msg = va("\n//kickfile \"%s\"\n", sv.modelname);
ClientReliableWrite_Begin (host_client, svc_stufftext, 3+strlen(msg));
ClientReliableWrite_String (host_client, msg);
SV_DropClient (host_client);
return;
}
@ -1567,7 +1592,7 @@ void SV_Begin_Core(client_t *split)
if (svprogfuncs)
{
eval_t *eval, *eval2;
eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0);
eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL);
if (eval && split->spawninfo)
{
globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
@ -4762,6 +4787,37 @@ void SVNQ_Ping_f(void)
}
}
void SV_Pext_f(void)
{
int i;
char *tag;
char *val;
if (host_client->pextknown)
return;
host_client->pextknown = true;
for (i = 1; i < Cmd_Argc(); )
{
tag = Cmd_Argv(i++);
val = Cmd_Argv(i++);
switch(strtoul(tag, NULL, 0))
{
case PROTOCOL_VERSION_FTE:
host_client->fteprotocolextensions = strtoul(val, NULL, 0) & svs.fteprotocolextensions;
break;
case PROTOCOL_VERSION_FTE2:
host_client->fteprotocolextensions2 = strtoul(val, NULL, 0) & svs.fteprotocolextensions2;
break;
}
}
if (ISNQCLIENT(host_client))
SVNQ_New_f();
else
SV_New_f();
}
ucmd_t nqucmds[] =
{
{"new", SVNQ_New_f, true},
@ -4803,6 +4859,15 @@ ucmd_t nqucmds[] =
{"topten", Rank_ListTop10_f},
#endif
{"pext", SV_Pext_f},
#ifdef VOICECHAT
{"voicetarg", SV_Voice_Target_f},
{"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/
{"muteall", SV_Voice_MuteAll_f}, /*disables*/
{"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/
#endif
{NULL, NULL}
};
/*
@ -6284,6 +6349,12 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
if (cl->state == cs_zombie)
return; // disconnect command
break;
#ifdef PEXT2_VOICECHAT
case clc_voicechat:
SV_VoiceReadPacket();
break;
#endif
}
}
}
@ -6474,6 +6545,12 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
case clcdp_ackdownloaddata:
SV_DarkPlacesDownloadAck(host_client);
break;
#ifdef PEXT2_VOICECHAT
case clc_voicechat:
SV_VoiceReadPacket();
break;
#endif
}
}
}

View file

@ -928,6 +928,12 @@ qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, v
trace->inopen = true; //probably wrong...
VectorCopy (end, trace->endpos);
if (IS_NAN(end[0]) || IS_NAN(end[1]) || IS_NAN(end[2]))
{
Con_DPrintf("Nan in traceline\n");
return false;
}
// don't rotate non bsp ents. Too small to bother.
if (model)
{