fix misc junk that was buggy. hurrah for handy test cases.

q3 shader remapping now a bit more robust.
portals finally work properly.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4610 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-02-14 09:59:32 +00:00
parent fd70ec0c62
commit 8f6c1a3e92
16 changed files with 190 additions and 53 deletions

View File

@ -805,7 +805,7 @@ ifeq (win_SDL,$(findstring win,$(FTE_TARGET))$(findstring _SDL,$(FTE_TARGET)))
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(WINDOWSSERVERONLY_OBJS) $(BOTLIB_OBJS) $(LTO_END) resources.o $(LTO_START)
SV_EXE_NAME=../fteqw_sdl_sv$(BITS)$(EXEPOSTFIX)
SV_CFLAGS=$(SERVER_ONLY_CFLAGS) -DFTE_SDL
SV_LDFLAGS=$(MINGW_LIBS_DIR)/libz.a -lm -lmingw32 -lws2_32 -lwinmm
SV_LDFLAGS=$(MINGW_LIBS_DIR)/libz.a -lm -lmingw32 -lws2_32 -lwinmm `$(SDLCONFIG) --libs`
MINGL_DIR=mingl_sdlwin$(BITS)
MINGL_EXE_NAME=../fteqw_sdl_mingl$(BITS)$(EXEPOSTFIX)
@ -1139,15 +1139,15 @@ endif
ifeq ($(FTE_TARGET),droid)
BASELDFLAGS=
SV_CFLAGS=
SV_LDFLAGS=
SV_DIR=sv_droid-$(DROID_ARCH)
SV_LDFLAGS=-lz
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(BOTLIB_OBJS) svmodel.o sys_droid.o
SV_EXE_NAME=libftedroid.so
SV_LDFLAGS=
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) gl_viddroid.o sys_droid.o cd_null.o snd_droid.o
GL_CFLAGS=$(GLCFLAGS)
GL_LDFLAGS=$(GLLDFLAGS)
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) $(BOTLIB_OBJS) gl_viddroid.o sys_droid.o cd_null.o snd_droid.o
GLB_DIR=gl_droid-$(DROID_ARCH)
GL_EXE_NAME=libftedroid.so
endif

View File

@ -349,6 +349,7 @@ qboolean CGQ3_GetUserCmd(int cmdNumber, q3usercmd_t *ucmd)
static vm_t *cgvm;
extern int keycatcher;
char bigconfigstring[65536];
qboolean CG_GetServerCommand(int cmdnum)
{
@ -361,6 +362,23 @@ qboolean CG_GetServerCommand(int cmdnum)
Con_DPrintf("Dispaching %s\n", str);
Cmd_TokenizeString(str, false, false);
if (!strcmp(Cmd_Argv(0), "bcs0"))
{
Q_snprintfz(bigconfigstring, sizeof(bigconfigstring), "cs %s \"%s", Cmd_Argv(1), Cmd_Argv(2));
return false;
}
if (!strcmp(Cmd_Argv(0), "bcs1"))
{
Q_strncatz(bigconfigstring, Cmd_Argv(2), sizeof(bigconfigstring));
return false;
}
if (!strcmp(Cmd_Argv(0), "bcs2"))
{
Q_strncatz(bigconfigstring, Cmd_Argv(2), sizeof(bigconfigstring));
Q_strncatz(bigconfigstring, "\"", sizeof(bigconfigstring));
Cmd_TokenizeString(bigconfigstring, false, false);
}
if (!strcmp(Cmd_Argv(0), "cs"))
CG_InsertIntoGameState(atoi(Cmd_Argv(1)), Cmd_Argv(2));
return true;
@ -548,6 +566,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
VM_LONG(ret) = VM_FRead(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), 1);
break;
case CG_FS_WRITE: //fwrite
Con_DPrintf("CG_FS_WRITE: not implemented\n");
break;
case CG_FS_FCLOSEFILE: //fclose
VM_fclose(VM_LONG(arg[0]), 1);
@ -703,6 +722,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_R_LOADWORLDMAP: //FTE can't distinguish. :/
Con_DPrintf("CG_R_LOADWORLDMAP: not implemented\n");
break; //So long as noone has one collision model with a different rendering one, we'll be fine
case CG_CM_LOADMAP:
@ -839,8 +859,16 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_S_ADDLOOPINGSOUND:
//entnum, origin, velocity, sfx
// Con_DPrintf("CG_S_ADDLOOPINGSOUND: not implemented\n");
break;
case CG_S_ADDREALLOOPINGSOUND:
//entnum, origin, velocity, sfx
// Con_DPrintf("CG_S_ADDREALLOOPINGSOUND: not implemented\n");
break;
case CG_S_STOPLOOPINGSOUND:
//entnum
// Con_DPrintf("CG_S_STOPLOOPINGSOUND: not implemented\n");
break;
case CG_S_STARTBACKGROUNDTRACK:
@ -850,9 +878,13 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
Media_BackgroundTrack(NULL, NULL);
return 0;
case CG_S_CLEARLOOPINGSOUNDS:
//clearall
Con_DPrintf("CG_S_CLEARLOOPINGSOUNDS: not implemented\n");
break;
case CG_S_UPDATEENTITYPOSITION://void trap_S_UpdateEntityPosition( int entityNum, const vec3_t origin );
//entnum, org
// Con_DPrintf("CG_S_UPDATEENTITYPOSITION: not implemented\n");
break;
case CG_S_RESPATIALIZE://void trap_S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
{
@ -870,9 +902,6 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
}
break;
case CG_S_ADDREALLOOPINGSOUND:
break;
case CG_KEY_ISDOWN:
{
extern qboolean keydown[256];
@ -986,6 +1015,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_PC_READ_TOKEN:
//fixme: memory protect.
VALIDATEPOINTER(arg[1], sizeof(struct pc_token_s));
return Script_Read(arg[0], VM_POINTER(arg[1]));
// standard Q3

View File

@ -1942,10 +1942,10 @@ void CL_ParseDownload (void)
}
if (size == -3)
{
char *localname;
char *requestedname;
Q_strncpyz(name, MSG_ReadString(), sizeof(name));
localname = MSG_ReadString();
Con_DPrintf("Download for %s redirected to %s\n", localname, name);
requestedname = MSG_ReadString();
Con_DPrintf("Download for %s redirected to %s\n", requestedname, name);
/*quakeforge http download redirection*/
if (cls.downloadqw)
{

View File

@ -1650,7 +1650,7 @@ void SCR_SetUpToDrawConsole (void)
Key_Dest_Add(kdm_console);
scr_conlines = scr_con_current = vid.height * fullscreenpercent;
}
else if ((!Key_Dest_Has(~(kdm_console|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false))
else if (!Key_Dest_Has(kdm_menu) && (!Key_Dest_Has(~(kdm_console|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false))
{
//go fullscreen if we're not doing anything
#ifdef VM_UI

View File

@ -407,6 +407,8 @@ void VQ3_AddEntity(const q3refEntity_t *q3)
if (q3->customSkin)
ent.skinnum = Mod_SkinNumForName(ent.model, VM_FROMSTRCACHE(q3->customSkin));
else
ent.skinnum = q3->skinNum;
ent.shaderRGBAf[0] = q3->shaderRGBA[0]/255.0f;
ent.shaderRGBAf[1] = q3->shaderRGBA[1]/255.0f;

View File

@ -2430,6 +2430,7 @@ void Surf_DeInit(void)
numlightmaps=0;
Alias_Shutdown();
Shader_ResetRemaps();
}
void Surf_Clear(model_t *mod)

View File

@ -333,6 +333,8 @@ cvar_t gl_texturemode2d = CVARFC("gl_texturemode2d", "GL_LINEAR",
cvar_t vid_triplebuffer = CVARAFD ("vid_triplebuffer", "1", "gl_triplebuffer", CVAR_ARCHIVE, "Specifies whether the hardware is forcing tripplebuffering on us, this is the number of extra page swaps required before old data has been completely overwritten.");
cvar_t r_portalrecursion = CVARD ("r_portalrecursion", "1", "The number of portals the camera is allowed to recurse through.");
cvar_t r_portaldrawplanes = CVARD ("r_portaldrawplanes", "0", "Draw front and back planes in portals. Debug feature.");
cvar_t r_portalonly = CVARD ("r_portalonly", "0", "Don't draw things which are not portals. Debug feature.");
cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0");
cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE);
cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting.");
@ -406,6 +408,8 @@ void GLRenderer_Init(void)
Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS);
Cvar_Register (&r_noframegrouplerp, GLRENDEREROPTIONS);
Cvar_Register (&r_portalrecursion, GLRENDEREROPTIONS);
Cvar_Register (&r_portaldrawplanes, GLRENDEREROPTIONS);
Cvar_Register (&r_portalonly, GLRENDEREROPTIONS);
Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS);
Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_basetexture, GLRENDEREROPTIONS);

View File

@ -1436,7 +1436,7 @@ float MSG_ReadFloat (void)
char *MSG_ReadString (void)
{
static char string[2048];
static char string[8192];
int l,c;
l = 0;

View File

@ -261,7 +261,7 @@ void deleetstring(char *result, char *leet);
//============================================================================
extern char com_token[1024];
extern char com_token[65536];
typedef enum {TTP_UNKNOWN, TTP_STRING, TTP_LINEENDING} com_tokentype_t;
extern com_tokentype_t com_tokentype;

View File

@ -386,7 +386,7 @@ struct traceinfo_s
vec3_t end;
};
#if 0
#if 1
#include "shader.h"
void BE_GenPolyBatches(batch_t **batches);
void TestDrawPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue)

View File

@ -766,7 +766,7 @@ void Netchan_TransmitQ3( netchan_t *chan, int length, const qbyte *data )
Netchan_TransmitNextFragment( chan );
if( chan->reliable_length )
{
Con_Printf( "%s: unsent fragments\n", NET_AdrToString( adr, sizeof(adr), &chan->remote_address ) );
Con_DPrintf( "%s: unsent fragments\n", NET_AdrToString( adr, sizeof(adr), &chan->remote_address ) );
return;
}
/*drop the outgoing packet if we fragmented*/

View File

@ -58,7 +58,7 @@ static const char LIGHTPASS_SHADER[] = "\
}\n\
}";
extern cvar_t r_glsl_offsetmapping, r_portalrecursion;
extern cvar_t r_glsl_offsetmapping, r_portalrecursion, r_portalonly;
static void BE_SendPassBlendDepthMask(unsigned int sbits);
void GLBE_SubmitBatch(batch_t *batch);
@ -1583,7 +1583,7 @@ static void tcmod(const tcmod_t *tcmod, int cnt, const float *src, float *dst, c
t1 = src[0];
t2 = src[1];
dst[0] = t1 * tcmod->args[0] + t2 * tcmod->args[2] + tcmod->args[4];
dst[1] = t2 * tcmod->args[1] + t1 * tcmod->args[3] + tcmod->args[5];
dst[1] = t1 * tcmod->args[1] + t2 * tcmod->args[3] + tcmod->args[5];
}
break;
@ -4374,8 +4374,13 @@ void GLBE_SubmitMeshes (qboolean drawworld, int start, int stop)
if (drawworld)
{
if (i == SHADER_SORT_PORTAL && r_refdef.recurse < portaldepth)
{
GLBE_SubmitMeshesPortals(model->batches, shaderstate.mbatches[i]);
if (!r_refdef.recurse && r_portalonly.ival)
return;
}
GLBE_SubmitMeshesSortList(model->batches[i]);
}
GLBE_SubmitMeshesSortList(shaderstate.mbatches[i]);

View File

@ -77,6 +77,8 @@ extern cvar_t gl_ati_truform_type;
extern cvar_t gl_ati_truform_tesselation;
extern cvar_t gl_blendsprites;
extern cvar_t r_portaldrawplanes;
extern cvar_t r_portalonly;
#ifdef R_XFLIP
cvar_t r_xflip = SCVAR("leftisright", "0");
@ -793,7 +795,8 @@ void R_ObliqueNearClip(float *viewmat, mplane_t *wplane)
r_refdef.m_projection[10] = c[2] + 1.0F;
r_refdef.m_projection[14] = c[3];
}
//void TestDrawPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue);
void TestDrawPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue);
void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], int portaltype)
{
entity_t *view;
@ -805,6 +808,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
int i;
mesh_t *mesh = batch->mesh[batch->firstmesh];
qbyte newvis[(MAX_MAP_LEAFS+7)/8];
plane_t oplane;
float ivmat[16], trmat[16];
if (r_refdef.recurse >= R_MAX_RECURSE-1)
return;
@ -910,16 +915,15 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
#ifdef CSQC_DAT
if (CSQC_SetupToRenderPortal(batch->ent->keynum))
{
plane_t oplane = plane;
float ivmat[16], trmat[16];
oplane = plane;
//transform the old surface plane into the new view matrix
Matrix4_Invert(r_refdef.m_view, ivmat);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
Matrix4_Multiply(ivmat, vmat, trmat);
plane.normal[0] = (oplane.normal[0] * trmat[0] + oplane.normal[1] * trmat[4] + oplane.normal[2] * trmat[8]);
plane.normal[1] = (oplane.normal[0] * trmat[1] + oplane.normal[1] * trmat[5] + oplane.normal[2] * trmat[9]);
plane.normal[2] = (oplane.normal[0] * trmat[2] + oplane.normal[1] * trmat[6] + oplane.normal[2] * trmat[10]);
plane.normal[0] = -(oplane.normal[0] * trmat[0] + oplane.normal[1] * trmat[1] + oplane.normal[2] * trmat[2]);
plane.normal[1] = -(oplane.normal[0] * trmat[4] + oplane.normal[1] * trmat[5] + oplane.normal[2] * trmat[6]);
plane.normal[2] = -(oplane.normal[0] * trmat[8] + oplane.normal[1] * trmat[9] + oplane.normal[2] * trmat[10]);
plane.dist = -oplane.dist + trmat[12]*oplane.normal[0] + trmat[13]*oplane.normal[1] + trmat[14]*oplane.normal[2];
if (Cvar_Get("temp_useplaneclip", "1", 0, "temp")->ival)
@ -938,6 +942,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
for (i = 1; i < mesh->numvertexes; i++)
VectorAdd(r_refdef.pvsorigin, mesh->xyz_array[i], r_refdef.pvsorigin);
VectorScale(r_refdef.pvsorigin, 1.0/mesh->numvertexes, r_refdef.pvsorigin);
portaltype = 1;
}
else
{
@ -945,6 +951,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
vec3_t paxis[3], porigin, vaxis[3], vorg;
void PerpendicularVector( vec3_t dst, const vec3_t src );
oplane = plane;
/*calculate where the surface is meant to be*/
VectorCopy(mesh->normals_array[0], paxis[0]);
PerpendicularVector(paxis[1], paxis[0]);
@ -961,31 +969,59 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
VectorCopy(vorg, r_refdef.pvsorigin);
/*rotate it a bit*/
RotatePointAroundVector(vaxis[1], vaxis[0], view->axis[1], sin(realtime)*4);
CrossProduct(vaxis[0], vaxis[1], vaxis[2]);
if (view->framestate.g[FS_REG].frame[1]) //oldframe
{
if (view->framestate.g[FS_REG].frame[0]) //newframe
d = realtime * view->framestate.g[FS_REG].frame[0]; //newframe
else
d = view->skinnum + sin(realtime)*4;
}
else
d = view->skinnum;
if (d)
{
vec3_t rdir;
VectorCopy(vaxis[1], rdir);
RotatePointAroundVector(vaxis[1], vaxis[0], rdir, d);
CrossProduct(vaxis[0], vaxis[1], vaxis[2]);
}
TransformCoord(oldrefdef.vieworg, paxis, porigin, vaxis, vorg, r_refdef.vieworg);
TransformDir(vpn, paxis, vaxis, vpn);
TransformDir(vright, paxis, vaxis, vright);
TransformDir(vup, paxis, vaxis, vup);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
//transform the old surface plane into the new view matrix
if (Matrix4_Invert(r_refdef.m_view, ivmat))
{
extern cvar_t temp1;
Matrix4_Multiply(ivmat, vmat, trmat);
plane.normal[0] = -(oplane.normal[0] * trmat[0] + oplane.normal[1] * trmat[1] + oplane.normal[2] * trmat[2]);
plane.normal[1] = -(oplane.normal[0] * trmat[4] + oplane.normal[1] * trmat[5] + oplane.normal[2] * trmat[6]);
plane.normal[2] = -(oplane.normal[0] * trmat[8] + oplane.normal[1] * trmat[9] + oplane.normal[2] * trmat[10]);
plane.dist = -oplane.dist + trmat[12]*oplane.normal[0] + trmat[13]*oplane.normal[1] + trmat[14]*oplane.normal[2];
portaltype = 1;
}
}
break;
}
/*FIXME: can we get away with stenciling the screen?*/
/*Add to frustum culling instead of clip planes?*/
/* if (qglClipPlane)
/* if (qglClipPlane && portaltype)
{
GLdouble glplane[4];
glplane[0] = -plane.normal[0];
glplane[1] = -plane.normal[1];
glplane[2] = -plane.normal[2];
glplane[0] = plane.normal[0];
glplane[1] = plane.normal[1];
glplane[2] = plane.normal[2];
glplane[3] = plane.dist;
qglClipPlane(GL_CLIP_PLANE0, glplane);
qglEnable(GL_CLIP_PLANE0);
}*/
//fixme: we can probably scissor a smaller frusum
}
*/ //fixme: we can probably scissor a smaller frusum
R_SetFrustum (r_refdef.m_projection, vmat);
if (r_refdef.frustum_numplanes < MAXFRUSTUMPLANES)
{
@ -1070,14 +1106,17 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2],
// if (qglClipPlane)
// qglDisable(GL_CLIP_PLANE0);
//the front of the plane should generally point away from the camera, and will be drawn in bright green. woo
// TestDrawPlane(plane.normal, plane.dist+0.01, 0.0, 0.5, 0.0, false);
// TestDrawPlane(plane.normal, plane.dist-0.01, 0.0, 0.5, 0.0, false);
//the back of the plane points towards the camera, and will be drawn in blue, for the luls
// VectorNegate(plane.normal, plane.normal);
// plane.dist *= -1;
// TestDrawPlane(plane.normal, plane.dist+0.01, 0.0, 0.0, 0.2, false);
// TestDrawPlane(plane.normal, plane.dist-0.01, 0.0, 0.0, 0.2, false);
if (r_portaldrawplanes.ival)
{
//the front of the plane should generally point away from the camera, and will be drawn in bright green. woo
TestDrawPlane(plane.normal, plane.dist+0.01, 0.0, 0.5, 0.0, false);
TestDrawPlane(plane.normal, plane.dist-0.01, 0.0, 0.5, 0.0, false);
//the back of the plane points towards the camera, and will be drawn in blue, for the luls
VectorNegate(plane.normal, plane.normal);
plane.dist *= -1;
TestDrawPlane(plane.normal, plane.dist+0.01, 0.0, 0.0, 0.2, false);
TestDrawPlane(plane.normal, plane.dist-0.01, 0.0, 0.0, 0.2, false);
}
r_refdef = oldrefdef;

View File

@ -5409,6 +5409,20 @@ cin_t *R_ShaderFindCinematic(char *name)
#endif
}
void Shader_ResetRemaps(void)
{
shader_t *s;
int i;
for (i = 0; i < r_numshaders; i++)
{
s = r_shaders[i];
if (!s)
continue;
s->remapto = s;
s->remaptime = 0;
}
}
void R_RemapShader(const char *sourcename, const char *destname, float timeoffset)
{
shader_t *o;

View File

@ -570,7 +570,8 @@ void Shader_DefaultSkybox(char *shortname, shader_t *s, const void *args);
void Shader_DefaultCinematic(char *shortname, shader_t *s, const void *args);
void Shader_DefaultScript(char *shortname, shader_t *s, const void *args);
void Shader_DoReload(void);
void Shader_ResetRemaps(void); //called on map changes to reset remapped shaders.
void Shader_DoReload(void); //called when the shader system dies.
void Shader_Shutdown (void);
qboolean Shader_Init (void);
void Shader_NeedReload(qboolean rescanfs);

View File

@ -384,7 +384,7 @@ static int SVQ3_EntitiesInBox(vec3_t mins, vec3_t maxs, int *list, int maxcount)
#define ENTITYNUM_NONE (MAX_GENTITIES-1)
#define ENTITYNUM_WORLD (MAX_GENTITIES-2)
static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int entnum, int contentmask)
static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int entnum, int contentmask, qboolean capsule)
{
int contactlist[128];
trace_t tr;
@ -550,20 +550,20 @@ static int SVQ3_PointContents(vec3_t pos, int entnum)
return cont;
}
static int SVQ3_Contact(vec3_t mins, vec3_t maxs, q3sharedEntity_t *ent)
static int SVQ3_Contact(vec3_t mins, vec3_t maxs, q3sharedEntity_t *ent, qboolean capsule)
{
model_t *mod;
trace_t tr;
if (!ent->s.modelindex || ent->r.bmodel)
mod = CM_TempBoxModel(ent->r.mins, ent->r.maxs);
else
if (ent->r.bmodel)
mod = Mod_ForName(va("*%i", ent->s.modelindex), false);
else
mod = CM_TempBoxModel(ent->r.mins, ent->r.maxs);
if (mod->needload || !mod->funcs.NativeTrace)
return false;
mod->funcs.NativeTrace(mod, 0, 0, NULL, vec3_origin, vec3_origin, mins, maxs, 0xffffffff, &tr);
tr = CM_TransformedBoxTrace(mod, vec3_origin, vec3_origin, mins, maxs, 0xffffffff, ent->r.currentOrigin, ent->r.currentAngles);
if (tr.startsolid)
return true;
@ -637,16 +637,51 @@ void SVQ3_SendServerCommand(client_t *cl, char *str)
Q_strncpyz(cl->server_commands[cl->num_server_commands & TEXTCMD_MASK], str, sizeof(cl->server_commands[0]));
}
void SVQ3_SendConfigString(client_t *dest, int num, char *string)
{
int len = strlen(string);
#define CONFIGSTRING_MAXCHUNK (1024-24)
if (len > CONFIGSTRING_MAXCHUNK)
{
char *cmd;
char buf[CONFIGSTRING_MAXCHUNK+1];
int off = 0;
for (;;)
{
int chunk = len - off;
if (chunk > CONFIGSTRING_MAXCHUNK)
chunk = CONFIGSTRING_MAXCHUNK;
//split it up into multiple commands.
if (!off)
cmd = "bcs0"; //initial chunk
else if (off + chunk == len)
cmd = "bcs2"; //terminator
else
cmd = "bcs1"; //mid chunk
memcpy(buf, string+off, chunk);
buf[chunk] = 0;
SVQ3_SendServerCommand(dest, va("%s %i \"%s\"\n", cmd, num, buf));
off += chunk;
if (off == len)
break;
}
}
else
SVQ3_SendServerCommand(dest, va("cs %i \"%s\"\n", num, string));
}
void SVQ3_SetConfigString(int num, char *string)
{
int len;
if (!string)
string = "";
len = strlen(string);
if (svq3_configstrings[num])
Z_Free(svq3_configstrings[num]);
svq3_configstrings[num] = Z_Malloc(strlen(string)+1);
svq3_configstrings[num] = Z_Malloc(len+1);
strcpy(svq3_configstrings[num], string);
SVQ3_SendServerCommand( NULL, va("cs %i \"%s\"\n", num, string));
SVQ3_SendConfigString(num, string);
}
static int FloatAsInt(float f)
@ -869,13 +904,19 @@ static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn,
break;
case G_TRACE: // ( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask );
VALIDATEPOINTER(arg[0], sizeof(q3trace_t));
SVQ3_Trace(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_POINTER(arg[3]), VM_POINTER(arg[4]), VM_LONG(arg[5]), VM_LONG(arg[6]));
SVQ3_Trace(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_POINTER(arg[3]), VM_POINTER(arg[4]), VM_LONG(arg[5]), VM_LONG(arg[6]), false);
break;
case G_TRACECAPSULE: // ( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask );
VALIDATEPOINTER(arg[0], sizeof(q3trace_t));
SVQ3_Trace(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_POINTER(arg[3]), VM_POINTER(arg[4]), VM_LONG(arg[5]), VM_LONG(arg[6]), true);
break;
case G_ENTITY_CONTACT:
// ( const vec3_t mins, const vec3_t maxs, const gentity_t *ent ); 33
// perform an exact check against inline brush models of non-square shape
return SVQ3_Contact(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]));
break;
return SVQ3_Contact(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), false);
case G_ENTITY_CONTACTCAPSULE:
return SVQ3_Contact(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), true);
case G_ENTITIES_IN_BOX: // ( const vec3_t mins, const vec3_t maxs, gentity_t **list, int maxcount ); 32
// EntitiesInBox will return brush models based on their bounding box,
// so exact determination must still be done with EntityContact
@ -1536,7 +1577,7 @@ static char *QDECL BL_BSPEntityData(void)
static void QDECL BL_Trace(bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask)
{
q3trace_t tr;
SVQ3_Trace(&tr, start, mins, maxs, end, passent, contentmask);
SVQ3_Trace(&tr, start, mins, maxs, end, passent, contentmask, false);
trace->allsolid = tr.allsolid;
trace->startsolid = tr.startsolid;