1
0
Fork 0
forked from fte/fteqw

fix issue with more submodels than the precache model limit. bump model precache limit.

move some of the weird hexen2 features into a HEXEN2 define, which will be disabled by the QUAKETC define.
preliminary attempt at capsule collision support. only capsule/q3bsp support, no capsule/box, box/capsule, or capsule/capsule support, yet.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4753 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-09-17 03:04:08 +00:00
parent 811d49720d
commit 45bafbf374
63 changed files with 1132 additions and 890 deletions

View file

@ -577,8 +577,13 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
unsigned int pc;
unsigned int modhandle = VM_LONG(arg[1]);
model_t *mod;
if (modhandle >= MAX_MODELS)
mod = &box_model;
if (modhandle >= MAX_PRECACHE_MODELS)
{
// if (modhandle == MAX_PRECACHE_MODELS+1)
// mod = &capsule_model;
// else
mod = &box_model;
}
else
mod = cl.model_precache[modhandle+1];
if (mod && !mod->needload)
@ -597,7 +602,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
float *origin = VM_POINTER(arg[2]);
float *angles = VM_POINTER(arg[3]);
model_t *mod;
if (modhandle >= MAX_MODELS)
if (modhandle >= MAX_PRECACHE_MODELS)
mod = &box_model;
else
mod = cl.model_precache[modhandle+1];
@ -626,6 +631,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
}
break;
case CG_CM_TRANSFORMEDCAPSULETRACE:
case CG_CM_TRANSFORMEDBOXTRACE:
// void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
// const vec3_t mins, const vec3_t maxs,
@ -643,7 +649,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
float *origin = VM_POINTER(arg[7]);
float *angles = VM_POINTER(arg[8]);
model_t *mod;
if (modhandle >= MAX_MODELS)
if (modhandle >= MAX_PRECACHE_MODELS)
mod = &box_model;
else
mod = cl.model_precache[modhandle+1];
@ -656,15 +662,15 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
origin = vec3_origin;
if (!angles)
angles = vec3_origin;
if (mod)
#ifndef CLIENTONLY
TransformedNativeTrace(mod, 0, 0, start, end, mins, maxs, brushmask, &tr, origin, angles);
if (mod && !mod->needload)
#if !defined(CLIENTONLY) || defined(CSQC_DAT)
World_TransformedTrace(mod, 0, 0, start, end, mins, maxs, fn==CG_CM_TRANSFORMEDCAPSULETRACE, &tr, origin, angles, brushmask);
#else
{
#ifdef warningmsg
#pragma warningmsg("FIXME: G3 CGame requires TransformedNativeTrace!")
#pragma warningmsg("FIXME: G3 CGame requires World_TransformedTrace!")
#endif
memset(&tr, 0, sizeof(tr));
memset(&tr, 0, sizeof(tr));
tr.allsolid = tr.startsolid = true;
tr.contents = 1;
}
@ -685,6 +691,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
memcpy(&results->plane, &tr.plane, sizeof(cplane_t));
}
break;
case CG_CM_CAPSULETRACE:
case CG_CM_BOXTRACE:
// void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
// const vec3_t mins, const vec3_t maxs,
@ -700,7 +707,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
unsigned int modhandle = VM_LONG(arg[5]);
int brushmask = VM_LONG(arg[6]);
model_t *mod;
if (modhandle >= MAX_MODELS)
if (modhandle >= MAX_PRECACHE_MODELS)
mod = &box_model;
else
mod = cl.model_precache[modhandle+1];
@ -709,7 +716,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
mins = vec3_origin;
if (!maxs)
maxs = vec3_origin;
mod->funcs.NativeTrace(mod, 0, 0, NULL, start, end, mins, maxs, brushmask, &tr);
mod->funcs.NativeTrace(mod, 0, 0, NULL, start, end, mins, maxs, fn==CG_CM_CAPSULETRACE, brushmask, &tr);
results->allsolid = tr.allsolid;
results->contents = tr.contents;
results->fraction = tr.fraction;
@ -754,7 +761,11 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
case CG_CM_TEMPBOXMODEL:
CM_TempBoxModel(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
VM_LONG(ret) = MAX_MODELS;
VM_LONG(ret) = MAX_PRECACHE_MODELS;
break;
case CG_CM_TEMPCAPSULEMODEL:
CM_TempBoxModel(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
VM_LONG(ret) = MAX_PRECACHE_MODELS+1;
break;
case CG_R_MODELBOUNDS:

View file

@ -1291,10 +1291,10 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, svc_spawnstatic);
for (j = 1; j < MAX_MODELS; j++)
for (j = 1; j < MAX_PRECACHE_MODELS; j++)
if (ent->model == cl.model_precache[j])
break;
if (j == MAX_MODELS)
if (j == MAX_PRECACHE_MODELS)
MSG_WriteByte (&buf, 0);
else
MSG_WriteByte (&buf, j);

View file

@ -1790,7 +1790,6 @@ void V_ClearEntity(entity_t *e)
e->playerindex = -1;
e->topcolour = TOP_DEFAULT;
e->bottomcolour = BOTTOM_DEFAULT;
e->h2playerclass = 0;
}
entity_t *V_AddEntity(entity_t *in)
{
@ -2478,10 +2477,29 @@ void CLQ1_AddVisibleBBoxes(void)
}
else
{
VectorCopy(e->v->absmin, min);
VectorCopy(e->v->absmax, max);
if (e->v->solid == SOLID_BSP)
{
VectorCopy(e->v->absmin, min);
VectorCopy(e->v->absmax, max);
}
else
{
VectorAdd(e->v->origin, e->v->mins, min);
VectorAdd(e->v->origin, e->v->maxs, max);
}
}
CLQ1_AddOrientedCube(s, min, max, NULL, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
if (e->xv->geomtype == GEOMTYPE_CAPSULE)
{
float rad = ((e->v->maxs[0]-e->v->mins[0]) + (e->v->maxs[1]-e->v->mins[1]))/4.0;
float height = (e->v->maxs[2]-e->v->mins[2])/2;
float matrix[12] = {1,0,0,0,0,1,0,0,0,0,1,0};
matrix[3] = e->v->origin[0];
matrix[7] = e->v->origin[1];
matrix[11] = e->v->origin[2] + (e->v->maxs[2]-height);
CLQ1_AddOrientedCylinder(s, rad*2, height*2, true, matrix, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
}
else
CLQ1_AddOrientedCube(s, min, max, NULL, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
}
}
@ -3276,7 +3294,9 @@ void CL_LinkPacketEntities (void)
ent->customskin = 0;
ent->topcolour = TOP_DEFAULT;
ent->bottomcolour = BOTTOM_DEFAULT;
#ifdef HEXEN2
ent->h2playerclass = 0;
#endif
ent->light_known = 0;
ent->forcedshader = NULL;
@ -3593,12 +3613,15 @@ void CL_LinkPacketEntities (void)
#ifdef warningmsg
#pragma warningmsg("Replace this flag on load for hexen2 models")
#endif
#ifdef HEXEN2
if (strncmp(model->name, "models/sflesh", 13))
#endif
{ //hmm. hexen spider gibs...
rad = 200;
rad += r_lightflicker.value?((flicker + state->number)&31):0;
}
}
#ifdef HEXEN2
else if (modelflags & MFH2_FIREBALL)
{
rad = 120 - (r_lightflicker.value?(rand() % 20):10);
@ -3618,6 +3641,7 @@ void CL_LinkPacketEntities (void)
dclr[2] = -dclr[2];
rad = 120 - (r_lightflicker.value?(rand() % 20):10);
}
#endif
if (rad)
{
@ -3736,7 +3760,9 @@ void CL_LinkProjectiles (void)
ent->playerindex = -1;
ent->topcolour = TOP_DEFAULT;
ent->bottomcolour = BOTTOM_DEFAULT;
#ifdef HEXEN2
ent->h2playerclass = 0;
#endif
#ifdef PEXT_SCALE
ent->scale = 1;
#endif
@ -4457,7 +4483,9 @@ void CL_LinkPlayers (void)
ent->playerindex = j;
ent->topcolour = info->ttopcolor;
ent->bottomcolour = info->tbottomcolor;
#ifdef HEXEN2
ent->h2playerclass = info->h2playerclass;
#endif
#ifdef PEXT_SCALE
ent->scale = state->scale;
@ -4617,7 +4645,7 @@ void CL_LinkViewModel(void)
if (cl.intermission)
return;
if (pv->stats[STAT_WEAPON] <= 0 || pv->stats[STAT_WEAPON] >= MAX_MODELS)
if (pv->stats[STAT_WEAPON] <= 0 || pv->stats[STAT_WEAPON] >= MAX_PRECACHE_MODELS)
return;
if (r_drawviewmodel.value > 0 && r_drawviewmodel.value < 1)

View file

@ -1281,7 +1281,9 @@ void CL_ClearState (void)
CL_ClearTEnts();
CL_ClearCustomTEnts();
Surf_ClearLightmaps();
#ifdef HEXEN2
T_FreeInfoStrings();
#endif
SCR_ShowPic_Clear(false);
if (cl.playerview[0].playernum == -1)
@ -2935,7 +2937,6 @@ void CLNQ_ConnectionlessPacket(void)
return;
case CCREP_REJECT:
connectinfo.trying = false;
s = MSG_ReadString();
Con_Printf("Connect failed\n%s\n", s);
return;

View file

@ -682,7 +682,7 @@ void CL_DownloadFinished(qdownload_t *dl)
}
}
*/
for (i = 0; i < MAX_MODELS; i++) //go and load this model now.
for (i = 0; i < MAX_PRECACHE_MODELS; i++) //go and load this model now.
{
if (!strcmp(cl.model_name[i], filename))
{
@ -1134,7 +1134,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload)
}
else
{
for (i=1 ; i<MAX_MODELS ; i++)
for (i=1 ; i<MAX_PRECACHE_MODELS ; i++)
{
if (!cl.model_name[i][0])
continue;
@ -1285,7 +1285,7 @@ int CL_LoadSounds(int stage, qboolean dontactuallyload)
//#define atstage() ((cl.contentstage == stage++)?++cl.contentstage:false)
//#define endstage() if (giveuptime<Sys_DoubleTime()) return -1;
for (i=1 ; i<MAX_SOUNDS ; i++)
for (i=1 ; i<MAX_PRECACHE_SOUNDS ; i++)
{
if (!cl.sound_name[i][0])
break;
@ -3255,7 +3255,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
str = MSG_ReadString ();
if (!str[0])
break;
if (nummodels==MAX_MODELS)
if (nummodels==MAX_PRECACHE_MODELS)
{
Con_TPrintf ("Server sent too many model precaches\n");
return;
@ -3272,7 +3272,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
str = MSG_ReadString ();
if (!str[0])
break;
if (numsounds==MAX_SOUNDS)
if (numsounds==MAX_PRECACHE_SOUNDS)
{
Con_TPrintf ("Server sent too many sound precaches\n");
return;
@ -3553,7 +3553,7 @@ void CL_ParseSoundlist (qboolean lots)
if (!str[0])
break;
numsounds++;
if (numsounds >= MAX_SOUNDS)
if (numsounds >= MAX_PRECACHE_SOUNDS)
Host_EndGame ("Server sent too many sound_precache");
// if (strlen(str)>4)
@ -3626,7 +3626,7 @@ void CL_ParseModellist (qboolean lots)
if (!str[0])
break;
nummodels++;
if (nummodels>=MAX_MODELS)
if (nummodels>=MAX_PRECACHE_MODELS)
Host_EndGame ("Server sent too many model_precache");
strcpy (cl.model_name[nummodels], str);
@ -4466,12 +4466,14 @@ void CL_ProcessUserInfo (int slot, player_info_t *player)
*/
player->model = NULL;
#ifdef HEXEN2
/*if we're running hexen2, they have to be some class...*/
player->h2playerclass = atoi(Info_ValueForKey (player->userinfo, "cl_playerclass"));
if (player->h2playerclass > 5)
player->h2playerclass = 5;
if (player->h2playerclass < 1)
player->h2playerclass = 1;
#endif
player->colourised = TP_FindColours(player->name);
@ -5625,7 +5627,7 @@ void CL_ParsePrecache(void)
switch(code & PC_TYPE)
{
case PC_MODEL:
if (i >= 1 && i < MAX_MODELS)
if (i >= 1 && i < MAX_PRECACHE_MODELS)
{
model_t *model;
CL_CheckOrEnqueDownloadFile(s, s, 0);
@ -5638,12 +5640,12 @@ void CL_ParsePrecache(void)
cl.model_precaches_added = true;
}
else
Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_MODELS);
Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_PRECACHE_MODELS);
break;
case PC_UNUSED:
break;
case PC_SOUND:
if (i >= 1 && i < MAX_SOUNDS)
if (i >= 1 && i < MAX_PRECACHE_SOUNDS)
{
sfx_t *sfx;
if (S_HaveOutput())
@ -5655,7 +5657,7 @@ void CL_ParsePrecache(void)
Q_strncpyz (cl.sound_name[i], s, sizeof(cl.sound_name[i]));
}
else
Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_SOUNDS);
Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_PRECACHE_SOUNDS);
break;
case PC_PARTICLE:
if (i >= 1 && i < MAX_SSPARTICLESPRE)

View file

@ -170,7 +170,7 @@ q2trace_t VARGS CLQ2_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end
trace_t t;
// check against world
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, start, end, mins, maxs, MASK_PLAYERSOLID, &t);
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, start, end, mins, maxs, false, MASK_PLAYERSOLID, &t);
if (t.fraction < 1.0)
t.ent = (struct edict_s *)1;
@ -406,6 +406,7 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state
movevars.bunnyspeedcap = cl.bunnyspeedcap;
pmove.onladder = false;
pmove.safeorigin_known = false;
pmove.capsule = false; //FIXME
VectorCopy(from->szmins, pmove.player_mins);
VectorCopy(from->szmaxs, pmove.player_maxs);
@ -666,7 +667,7 @@ static void CL_DecodeStateSize(unsigned short solid, int modelindex, vec3_t mins
{
if (solid == ES_SOLID_BSP)
{
if (modelindex < MAX_MODELS && cl.model_precache[modelindex] && !cl.model_precache[modelindex]->needload)
if (modelindex < MAX_PRECACHE_MODELS && cl.model_precache[modelindex] && !cl.model_precache[modelindex]->needload)
{
VectorCopy(cl.model_precache[modelindex]->mins, mins);
VectorCopy(cl.model_precache[modelindex]->maxs, maxs);

View file

@ -1094,7 +1094,7 @@ void SCR_CrosshairPosition(playerview_t *pview, float *x, float *y)
memset(&tr, 0, sizeof(tr));
tr.fraction = 1;
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, MASK_WORLDSOLID, &tr);
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr);
start[2]-=16;
if (tr.fraction != 1)
{

View file

@ -3370,7 +3370,6 @@ entity_t *CL_NewTempEntity (void)
ent->playerindex = -1;
ent->topcolour = TOP_DEFAULT;
ent->bottomcolour = BOTTOM_DEFAULT;
ent->h2playerclass = 0;
#ifdef PEXT_SCALE
ent->scale = 1;

View file

@ -175,7 +175,9 @@ typedef struct player_info_s
struct model_s *model;
// unsigned short vweapindex;
#ifdef HEXEN2
unsigned char h2playerclass;
#endif
int prevcount;
@ -724,14 +726,14 @@ typedef struct
// information that is static for the entire time connected to a server
//
char model_name_vwep[MAX_VWEP_MODELS][MAX_QPATH];
char model_name[MAX_MODELS][MAX_QPATH];
char sound_name[MAX_SOUNDS][MAX_QPATH];
char model_name[MAX_PRECACHE_MODELS][MAX_QPATH];
char sound_name[MAX_PRECACHE_SOUNDS][MAX_QPATH];
char *particle_ssname[MAX_SSPARTICLESPRE];
char image_name[Q2MAX_IMAGES][MAX_QPATH];
struct model_s *model_precache_vwep[MAX_VWEP_MODELS];
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS];
struct model_s *model_precache[MAX_PRECACHE_MODELS];
struct sfx_s *sound_precache[MAX_PRECACHE_SOUNDS];
int particle_ssprecache[MAX_SSPARTICLESPRE]; //these are actually 1-based, so 0 can be used to lazy-init them. I cheat.
char model_csqcname[MAX_CSMODELS][MAX_QPATH];

View file

@ -2034,15 +2034,16 @@ void M_Menu_Main_f (void)
}
else if (mgt == MGT_HEXEN2)
{
p = R2D_SafeCachePic("gfx/menu/title0.lmp");
if (!p)
return;
m_state = m_complex;
Key_Dest_Add(kdm_menu);
mainm = M_CreateMenu(0);
mainm->key = MC_Main_Key;
MC_AddPicture(mainm, 16, 0, 35, 176, "gfx/menu/hplaque.lmp");
p = R2D_SafeCachePic("gfx/menu/title0.lmp");
if (!p)
return;
MC_AddCenterPicture(mainm, 0, 60, "gfx/menu/title0.lmp");
#ifndef CLIENTONLY

View file

@ -3,7 +3,7 @@
#include "quakedef.h"
#include "winquake.h"
#include "shader.h"
#ifndef NOBUITINMENUS
#ifndef NOBUILTINMENUS
#ifndef CLIENTONLY
//=============================================================================
/* LOAD/SAVE MENU */

View file

@ -185,7 +185,7 @@ void M_PrintWhite (int cx, int cy, qbyte *str)
void M_BuildTranslationTable(int top, int bottom, unsigned int *translationTable)
{
int j;
#ifdef HEXEN2
int pc = Cvar_Get("cl_playerclass", "1", 0, "Hexen2")->value;
if (h2playertranslations && pc)
{
@ -207,6 +207,7 @@ void M_BuildTranslationTable(int top, int bottom, unsigned int *translationTable
}
}
else
#endif
{
for(j=0;j<255;j++)
{

View file

@ -3739,7 +3739,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
VectorSubtract(org, t2, tangent);
VectorAdd(org, t2, t2);
if (cl.worldmodel && cl.worldmodel->funcs.NativeTrace (cl.worldmodel, 0, 0, NULL, tangent, t2, vec3_origin, vec3_origin, MASK_WORLDSOLID, &tr))
if (cl.worldmodel && cl.worldmodel->funcs.NativeTrace (cl.worldmodel, 0, 0, NULL, tangent, t2, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr))
{
if (tr.fraction < dist)
{

View file

@ -575,7 +575,7 @@ static model_t *CSQC_GetModelForIndex(int index)
{
if (index == 0)
return NULL;
else if (index > 0 && index < MAX_MODELS)
else if (index > 0 && index < MAX_PRECACHE_MODELS)
return cl.model_precache[index];
else if (index < 0 && index > -MAX_CSMODELS)
{
@ -1899,7 +1899,7 @@ static int FindModel(const char *name, int *free)
if (!strcmp(cl.model_csqcname[i], name))
return -i;
}
for (i = 1; i < MAX_MODELS; i++)
for (i = 1; i < MAX_PRECACHE_MODELS; i++)
{
if (!strcmp(cl.model_name[i], name))
return i;
@ -1923,7 +1923,7 @@ static void csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int modelind
}
else
{
if (modelindex >= MAX_MODELS)
if (modelindex >= MAX_PRECACHE_MODELS)
return;
ent->v->model = PR_SetString(prinst, cl.model_name[modelindex]);
model = cl.model_precache[modelindex];
@ -1981,7 +1981,7 @@ static void QCBUILTIN PF_cs_PrecacheModel(pubprogfuncs_t *prinst, struct globalv
return;
}
for (i = 1; i < MAX_MODELS; i++) //Make sure that the server specified model is loaded..
for (i = 1; i < MAX_PRECACHE_MODELS; i++) //Make sure that the server specified model is loaded..
{
if (!*cl.model_name[i])
break;
@ -2531,6 +2531,7 @@ static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct glo
pmove.cmd.upmove = csqcg.input_movevalues[2];
pmove.cmd.buttons = *csqcg.input_buttons;
pmove.safeorigin_known = false;
pmove.capsule = false; //FIXME
if (ent)
{
@ -3853,8 +3854,8 @@ void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent)
// ent->v->effects = srcp->effects;
}
unsigned int deltaflags[MAX_MODELS];
func_t deltafunction[MAX_MODELS];
unsigned int deltaflags[MAX_PRECACHE_MODELS];
func_t deltafunction[MAX_PRECACHE_MODELS];
typedef struct
{
@ -3878,7 +3879,7 @@ qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state)
{
func_t func;
if (!state || state->modelindex <= 0 || state->modelindex >= MAX_MODELS)
if (!state || state->modelindex <= 0 || state->modelindex >= MAX_PRECACHE_MODELS)
{
if (csqcdelta_playerents[playernum])
{
@ -4045,7 +4046,7 @@ static void QCBUILTIN PF_DeltaListen(pubprogfuncs_t *prinst, struct globalvars_s
if (!strcmp(mname, "*"))
{
//yes, even things that are not allocated yet
for (i = 0; i < MAX_MODELS; i++)
for (i = 0; i < MAX_PRECACHE_MODELS; i++)
{
deltafunction[i] = func;
deltaflags[i] = flags;
@ -4053,7 +4054,7 @@ static void QCBUILTIN PF_DeltaListen(pubprogfuncs_t *prinst, struct globalvars_s
}
else
{
for (i = 1; i < MAX_MODELS; i++)
for (i = 1; i < MAX_PRECACHE_MODELS; i++)
{
if (!*cl.model_name[i])
break;
@ -5491,8 +5492,6 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
csqcentsize = PR_InitEnts(csqcprogs, pr_csqc_maxedicts.value);
ED_Alloc(csqcprogs); //we need a world entity.
//world edict becomes readonly
worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0);
worldent->isfree = false;

View file

@ -227,10 +227,10 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
{
AngleVectors(pe->angles, axis[0], axis[1], axis[2]);
VectorNegate(axis[1], axis[1]);
pe->model->funcs.NativeTrace(pe->model, 0, 0, axis, ts, te, vec3_origin, vec3_origin, MASK_WORLDSOLID, &trace);
pe->model->funcs.NativeTrace(pe->model, 0, 0, axis, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
}
else
pe->model->funcs.NativeTrace(pe->model, 0, 0, NULL, ts, te, vec3_origin, vec3_origin, MASK_WORLDSOLID, &trace);
pe->model->funcs.NativeTrace(pe->model, 0, 0, NULL, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
if (trace.fraction<1)
{
VectorSubtract(trace.endpos, ts, delta);

View file

@ -2224,12 +2224,12 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
bef = BEF_PUSHDEPTH;
if (ent->flags & RF_ADDITIVE)
bef |= BEF_FORCEADDITIVE;
else if (ent->drawflags & DRF_TRANSLUCENT && r_wateralpha.value != 1)
else if ((ent->drawflags & DRF_TRANSLUCENT) && r_wateralpha.value != 1)
{
bef |= BEF_FORCETRANSPARENT;
ent->shaderRGBAf[3] = r_wateralpha.value;
}
else if (ent->flags & RF_TRANSLUCENT && cls.protocol != CP_QUAKE3)
else if ((ent->flags & RF_TRANSLUCENT) && cls.protocol != CP_QUAKE3)
bef |= BEF_FORCETRANSPARENT;
if (ent->flags & RF_NODEPTHTEST)
bef |= BEF_FORCENODEPTH;
@ -2827,7 +2827,7 @@ void Surf_BuildLightmaps (void)
r_oldviewcluster2 = -1;
numlightmaps = 0;
for (j=1 ; j<MAX_MODELS ; j++)
for (j=1 ; j<MAX_PRECACHE_MODELS ; j++)
{
m = cl.model_precache[j];
if (!m)

View file

@ -104,7 +104,9 @@ typedef struct entity_s
int playerindex; //for qw skins
int topcolour; //colourmapping
int bottomcolour; //colourmapping
#ifdef HEXEN2
int h2playerclass; //hexen2's quirky colourmapping
#endif
// struct efrag_s *efrag; // linked list of efrags (FIXME)
// int visframe; // last frame this entity was

View file

@ -1093,9 +1093,11 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
BZ_Free(colormap);
}
#ifdef HEXEN2
if (h2playertranslations)
BZ_Free(h2playertranslations);
h2playertranslations = FS_LoadMallocFile ("gfx/player.lmp");
#endif
if (vid.fullbright < 2)
vid.fullbright = 0; //transparent colour doesn't count.
@ -1183,7 +1185,7 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
SV_UnspawnServer();
else if (svs.gametype == GT_PROGS)
{
for (i = 0; i < MAX_MODELS; i++)
for (i = 0; i < MAX_PRECACHE_MODELS; i++)
{
if (sv.strings.model_precache[i] && *sv.strings.model_precache[i] && (!strcmp(sv.strings.model_precache[i] + strlen(sv.strings.model_precache[i]) - 4, ".bsp") || i-1 < sv.world.worldmodel->numsubmodels))
sv.models[i] = Mod_FindName(sv.strings.model_precache[i]);
@ -1211,7 +1213,7 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
#ifdef Q2SERVER
else if (svs.gametype == GT_QUAKE2)
{
for (i = 0; i < MAX_MODELS; i++)
for (i = 0; i < MAX_PRECACHE_MODELS; i++)
{
if (sv.strings.configstring[Q2CS_MODELS+i] && *sv.strings.configstring[Q2CS_MODELS+i] && (!strcmp(sv.strings.configstring[Q2CS_MODELS+i] + strlen(sv.strings.configstring[Q2CS_MODELS+i]) - 4, ".bsp") || i-1 < sv.world.worldmodel->numsubmodels))
sv.models[i] = Mod_FindName(sv.strings.configstring[Q2CS_MODELS+i]);
@ -1276,7 +1278,7 @@ TRACE(("dbg: R_ApplyRenderer: starting on client state\n"));
//FIXME: this code should not be here. call CL_LoadModels instead? that does csqc loading etc though. :s
TRACE(("dbg: R_ApplyRenderer: reloading ALL models\n"));
for (i=1 ; i<MAX_MODELS ; i++)
for (i=1 ; i<MAX_PRECACHE_MODELS ; i++)
{
if (!cl.model_name[i][0])
break;
@ -1364,7 +1366,7 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
}
else
{
if (cl_static_entities[i].mdlidx < MAX_MODELS)
if (cl_static_entities[i].mdlidx < MAX_PRECACHE_MODELS)
cl_static_entities[i].ent.model = cl.model_precache[cl_static_entities[i].mdlidx];
}
}

View file

@ -116,7 +116,9 @@ qboolean sb_showscores;
qboolean sb_showteamscores;
qboolean sbarfailed;
#ifdef HEXEN2
qboolean sbar_hexen2;
#endif
vrect_t sbar_rect; //screen area that the sbar must fit.
float sbar_rect_left;
@ -832,8 +834,10 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar.
sb_nums[1][i] = Sbar_PicFromWad (va("anum_%i",i));
}
#ifdef HEXEN2
if (sb_nums[0][0] && sb_nums[0][0]->width < 13)
sbar_hexen2 = true;
#endif
sb_nums[0][10] = Sbar_PicFromWad ("num_minus");
sb_nums[1][10] = Sbar_PicFromWad ("anum_minus");
@ -2065,6 +2069,7 @@ void Sbar_DrawScoreboard (void)
}
#ifdef HEXEN2
static void Sbar_Hexen2DrawActiveStuff(playerview_t *pv)
{
int x = r_refdef.grect.x + r_refdef.grect.width;
@ -2368,7 +2373,7 @@ static void Sbar_Hexen2DrawMinimal(playerview_t *pv)
Sbar_Hexen2DrawNum(38, y+18, pv->stats[STAT_HEALTH], 3);
}
#endif
static void Sbar_DrawTeamStatus(playerview_t *pv)
{
@ -2593,7 +2598,7 @@ void Sbar_Draw (playerview_t *pv)
sb_updates++;
#ifdef HEXEN2
if (sbar_hexen2)
{
//hexen2 hud
@ -2611,7 +2616,9 @@ void Sbar_Draw (playerview_t *pv)
Sbar_Hexen2DrawActiveStuff(pv);
}
else if (sbarfailed) //files failed to load.
else
#endif
if (sbarfailed) //files failed to load.
{
//fallback hud
if (pv->stats[STAT_HEALTH] > 0) //when dead, show nothing

View file

@ -467,15 +467,19 @@ void Skin_NextDownload (void)
{
*slash = 0;
CL_CheckOrEnqueDownloadFile(va("players/%s/tris.md2", skinname), NULL, 0);
for (j = 0; j < MAX_MODELS; j++)
for (j = 1; j < MAX_PRECACHE_MODELS; j++)
{
if (cl.model_name[j][0] == '#')
CL_CheckOrEnqueDownloadFile(va("players/%s/%s", skinname, cl.model_name[j]+1), NULL, 0);
if (!*cl.model_name[j])
break;
}
for (j = 0; j < MAX_SOUNDS; j++)
for (j = 1; j < MAX_PRECACHE_SOUNDS; j++)
{
if (cl.sound_name[j][0] == '*')
CL_CheckOrEnqueDownloadFile(va("players/%s/%s", skinname, cl.sound_name[j]+1), NULL, 0);
if (!*cl.sound_name[j])
break;
}
*slash = '/';
CL_CheckOrEnqueDownloadFile(va("players/%s.pcx", skinname), NULL, 0);

View file

@ -1758,7 +1758,7 @@ void S_DoRestart (void)
S_StopAllSounds (true);
for (i=1 ; i<MAX_SOUNDS ; i++)
for (i=1 ; i<MAX_PRECACHE_SOUNDS ; i++)
{
if (!cl.sound_name[i][0])
break;

View file

@ -1165,6 +1165,9 @@ void V_ApplyRefdef (void)
V_ApplyAFov(r_refdef.playerview);
r_refdef.dirty = 0;
if (chase_active.ival && cls.allow_cheats)
CL_EditExternalModels(0, NULL, 0);
}
//if the view entities differ, removes all externalmodel flags except for adding it to the new entity, and removes weaponmodels.
@ -1304,18 +1307,38 @@ void V_CalcRefdef (playerview_t *pv)
loadmodel = cl.worldmodel;
}
if (chase_active.ival)
if (chase_active.ival && cls.allow_cheats) //cheat restriction might be lifted some time when any wallhacks are solved.
{
vec3_t axis[3];
vec3_t camorg;
vec3_t camorg, camdir;
trace_t tr;
float len;
AngleVectors(r_refdef.viewangles, axis[0], axis[1], axis[2]);
VectorMA(r_refdef.vieworg, -chase_back.value, axis[0], camorg);
VectorMA(camorg, -chase_up.value, pv->gravitydir, camorg);
// if (cl.worldmodel && cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, r_refdef.vieworg, camorg, vec3_origin, vec3_origin, MASK_WORLDSOLID, &tr))
VectorCopy(camorg, r_refdef.vieworg);
CL_EditExternalModels(0, NULL, 0);
VectorScale(axis[0], -chase_back.value, camdir);
VectorMA(camdir, -chase_up.value, pv->gravitydir, camdir);
len = VectorLength(camdir);
VectorMA(r_refdef.vieworg, (len+128)/len, camdir, camorg); //push it 128qu further
if (cl.worldmodel && cl.worldmodel->funcs.NativeTrace)
{
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, r_refdef.vieworg, camorg, vec3_origin, vec3_origin, true, MASK_WORLDSOLID, &tr);
if (!tr.startsolid)
{
float extralen;
if (tr.fraction < 1)
{
//we found a plane, bisect it weirdly to push 4qu infront
float d1,d2, frac;
VectorMA(r_refdef.vieworg, 1, camdir, camorg);
d1 = DotProduct(r_refdef.vieworg, tr.plane.normal) - (tr.plane.dist+4);
d2 = DotProduct(camorg, tr.plane.normal) - (tr.plane.dist+4);
frac = d1 / (d1-d2);
frac = bound(0, frac, 1);
VectorMA(r_refdef.vieworg, frac, camdir, r_refdef.vieworg);
}
else
VectorMA(r_refdef.vieworg, 1, camdir, r_refdef.vieworg);
}
}
}
}
@ -1775,7 +1798,7 @@ void V_Init (void)
Cvar_Register (&v_contrast, VIEWVARS);
Cvar_Register (&v_brightness, VIEWVARS);
// Cvar_Register (&chase_active, VIEWVARS);
// Cvar_Register (&chase_back, VIEWVARS);
// Cvar_Register (&chase_up, VIEWVARS);
Cvar_Register (&chase_active, VIEWVARS);
Cvar_Register (&chase_back, VIEWVARS);
Cvar_Register (&chase_up, VIEWVARS);
}

View file

@ -2479,7 +2479,7 @@ static item_t tp_items[] = {
#define NUMITEMS (sizeof(tp_items) / sizeof(tp_items[0]))
static item_t *model2item[MAX_MODELS];
static item_t *model2item[MAX_PRECACHE_MODELS];
static void TP_FindModelNumbers (void)
{
@ -2487,7 +2487,7 @@ static void TP_FindModelNumbers (void)
char *s;
item_t *item;
for (i=0 ; i<MAX_MODELS ; i++) {
for (i=0 ; i<MAX_PRECACHE_MODELS ; i++) {
model2item[i] = NULL;
s = cl.model_name[i];
if (!s)

View file

@ -135,11 +135,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//#define BOTLIB_STATIC
#endif
#ifdef _WIN32
//needs testing on other platforms
//#define AVAIL_OPENAL
#endif
#define ODE_DYNAMIC
#ifdef NO_OPENAL
@ -223,6 +218,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define Q2CLIENT //client can connect to q2 servers
#define Q3CLIENT
#define Q3SERVER
#define HEXEN2 //technically server only
// #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
// #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
#define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect')
@ -269,6 +265,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
//#define QUAKETC
#ifdef QUAKETC
#define NOBUILTINMENUS //kill engine menus (should be replaced with ewither csqc or menuqc)
#undef Q2CLIENT //not useful
@ -281,6 +279,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef VM_LUA //not useful
#undef HALFLIFEMODELS //yuck
#undef RUNTIMELIGHTING //presumably not useful
#undef HEXEN2
#endif
//#define QUAKESPYAPI //define this if you want the engine to be usable via gamespy/quakespy, which has been dead for a long time now.
@ -473,7 +472,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// defs common to client and server
#ifndef PLATFORM
#if defined(_WIN32)
#if defined(FTE_TARGET_WEB)
#define PLATFORM "Web"
#elif defined(NACL)
#define PLATFORM "Nacl"
#elif defined(_WIN32)
#if defined(__amd64__)
#define PLATFORM "Win64"
#else
@ -619,8 +622,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#define MAX_LIGHTSTYLES 255
#define MAX_STANDARDLIGHTSTYLES 64
#define MAX_MODELS 1024 // these are sent over the net as bytes
#define MAX_SOUNDS 1024 // so they cannot be blindly increased
#define MAX_PRECACHE_MODELS 2048 // these are sent over the net as bytes/shorts
#define MAX_PRECACHE_SOUNDS 1024 // so they cannot be blindly increased
#define MAX_SSPARTICLESPRE 1024 // precached particle effect names, for server-side pointparticles/trailparticles.
#define MAX_VWEP_MODELS 32

View file

@ -893,11 +893,11 @@ typedef struct
#define MAX_ENT_LEAFS 32
typedef struct pvscache_s
{
int num_leafs;
short leafnums[MAX_ENT_LEAFS];
int num_leafs;
unsigned short leafnums[MAX_ENT_LEAFS];
#if defined(Q2BSPS) || defined(TERRAIN)
int areanum; //q2bsp
int areanum2; //q2bsp
int headnode; //q2bsp
int areanum; //q2bsp
int areanum2; //q2bsp
int headnode; //q2bsp
#endif
} pvscache_t;

View file

@ -1463,8 +1463,70 @@ static void Alias_BuildSkeletalVPositionsPose(float *xyzout, skeltype_t bonetype
#ifndef SERVERONLY
#ifdef GLQUAKE
#include "glquake.h"
static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int bonecount, int basebone)
#endif
static void Alias_DrawSkeletalBones(galiasbone_t *bones, float *bonepose, int bonecount, int basebone)
{
#ifndef GLQUAKE
scenetris_t *t;
int flags = BEF_NODLIGHT|BEF_NOSHADOWS|BEF_LINES;
int first;
if (cl_numstris && cl_stris[cl_numstris-1].shader == shader && cl_stris[cl_numstris-1].flags == flags)
t = &cl_stris[cl_numstris-1];
else
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris += 8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->numidx = 0;
t->numvert = 0;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
t->flags = flags;
}
if (cl_numstrisvert + bonecount*2 > cl_maxstrisvert)
{
cl_maxstrisvert = cl_numstrisvert + bonecount*2;
cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert);
cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(vec2_t)*cl_maxstrisvert);
cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(vec4_t)*cl_maxstrisvert);
}
if (cl_maxstrisidx < cl_numstrisidx+bonecount*2)
{
cl_maxstrisidx = cl_numstrisidx+bonecount*2;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
first = cl_numstrisvert-t->firstvert;
for (i = 0; i < bonecount; i++)
{
//fixme: transform by model matrix
cl_strisvertv[cl_numstrisvert][0] = bonepose[i*12+3];
cl_strisvertv[cl_numstrisvert][1] = bonepose[i*12+7];
cl_strisvertv[cl_numstrisvert][2] = bonepose[i*12+11];
cl_strisvertt[cl_numstrisvert][0] = 0;
cl_strisvertt[cl_numstrisvert][1] = 0;
cl_strisvertc[cl_numstrisvert][0] = (i < basebone)?0:1;
cl_strisvertc[cl_numstrisvert][1] = (i < basebone)?0:0;
cl_strisvertc[cl_numstrisvert][2] = (i < basebone)?1:0;
cl_strisvertc[cl_numstrisvert][3] = 1;
cl_numstrisvert++;
p = bones[i].parent;
if (p < 0)
p = 0;
cl_strisidx[cl_numstrisidx++] = first+i;
cl_strisidx[cl_numstrisidx++] = first+p;
}
t->numvert += bonecount;
t->numidx = cl_numstrisidx - t->firstidx;
#else
PPL_RevertToKnownState();
BE_SelectEntity(currententity);
qglColor3f(1, 0, 0);
@ -1529,8 +1591,8 @@ static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int
*/
// mesh->numindexes = 0; //don't draw this mesh, as that would obscure the bones. :(
}
#endif
}
#endif //GLQUAKE
#endif //!SERVERONLY
#endif //SKELETALMODELS
@ -1723,7 +1785,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
meshcache.usebonepose = Alias_GetBoneInformation(inf, &e->framestate, meshcache.bonecachetype=SKEL_ABSOLUTE, meshcache.boneposebuffer1, meshcache.boneposebuffer2, MAX_BONES);
if (qrenderer == QR_OPENGL)
{
Alias_GLDrawSkeletalBones(inf->ofsbones, (float *)meshcache.usebonepose, inf->numbones, e->framestate.g[0].endbone);
Alias_DrawSkeletalBones(inf->ofsbones, (float *)meshcache.usebonepose, inf->numbones, e->framestate.g[0].endbone);
}
#endif
}
@ -2042,7 +2104,7 @@ qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, v
}
//The whole reason why model loading is supported in the server.
qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentsmask, trace_t *trace)
qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contentsmask, trace_t *trace)
{
galiasinfo_t *mod = Mod_Extradata(model);
galiasgroup_t *group;
@ -2592,6 +2654,7 @@ extern float r_avertexnormals[NUMVERTEXNORMALS][3];
static void Alias_LoadPose(vecV_t *verts, vec3_t *normals, vec3_t *svec, vec3_t *tvec, dtrivertx_t *pinframe, int *seamremaps, int mdltype)
{
int j;
#ifdef HEXEN2
if (mdltype == 2)
{
for (j = 0; j < galias->numverts; j++)
@ -2605,6 +2668,7 @@ static void Alias_LoadPose(vecV_t *verts, vec3_t *normals, vec3_t *svec, vec3_t
}
}
else
#endif
{
for (j = 0; j < pq1inmodel->numverts; j++)
{
@ -3062,7 +3126,6 @@ qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer, size_t fsize)
int i, onseams;
dstvert_t *pinstverts;
dtriangle_t *pinq1triangles;
dh2triangle_t *pinh2triangles;
int *seamremap;
index_t *indexes;
daliasskintype_t *skinstart;
@ -3072,7 +3135,10 @@ qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer, size_t fsize)
unsigned int hdrsize;
void *end;
qboolean qtest = false;
#ifdef HEXEN2
dh2triangle_t *pinh2triangles;
qboolean rapo = false;
#endif
loadmodel=mod;
@ -3088,11 +3154,13 @@ qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer, size_t fsize)
hdrsize = (size_t)&((dmdl_t*)NULL)->flags;
qtest = true;
}
#ifdef HEXEN2
else if (version == 50)
{
hdrsize = sizeof(dmdl_t);
rapo = true;
}
#endif
else if (version != ALIAS_VERSION)
{
Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n",
@ -3162,6 +3230,7 @@ qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer, size_t fsize)
break;
}
#ifdef HEXEN2
if (rapo)
{
/*each triangle can use one coord and one st, for each vert, that's a lot of combinations*/
@ -3248,6 +3317,7 @@ qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer, size_t fsize)
BZ_Free(seamremap);
}
else
#endif
{
/*onseam means +=skinwidth/2
verticies that are marked as onseam potentially generate two output verticies.
@ -7206,7 +7276,9 @@ qboolean QDECL Mod_LoadCompositeAnim(model_t *mod, void *buffer, size_t fsize)
void Alias_Register(void)
{
Mod_RegisterModelFormatMagic(NULL, "Quake1 Model (mdl)", IDPOLYHEADER, Mod_LoadQ1Model);
#ifdef HEXEN2
Mod_RegisterModelFormatMagic(NULL, "Hexen2 Model (mdl)", RAPOLYHEADER, Mod_LoadQ1Model);
#endif
#ifdef MD2MODELS
Mod_RegisterModelFormatMagic(NULL, "Quake2 Model (md2)", MD2IDALIASHEADER, Mod_LoadQ2Model);
#endif

View file

@ -96,25 +96,7 @@ 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=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
cvar_t com_nogamedirnativecode = CVARFD("com_nogamedirnativecode", "1", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger remote exploits in any engine (including "FULLENGINENAME"which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 0, as well as ensure that you don't run unsafe clients.\n");
#ifdef FTE_TARGET_WEB
cvar_t sys_platform = CVAR("sys_platform", "web");
#elif defined(NACL)
cvar_t sys_platform = CVAR("sys_platform", "nacl");
#elif defined(ANDROID)
cvar_t sys_platform = CVAR("sys_platform", "android");
#elif defined(FTE_SDL)
cvar_t sys_platform = CVAR("sys_platform", "sdl");
#elif defined(_WIN64)
cvar_t sys_platform = CVAR("sys_platform", "win64");
#elif defined(_WIN32)
cvar_t sys_platform = CVAR("sys_platform", "win32");
#elif defined(__linux__)
cvar_t sys_platform = CVAR("sys_platform", "linux");
#elif defined(__APPLE__)
cvar_t sys_platform = CVAR("sys_platform", "mac");
#else
cvar_t sys_platform = CVAR("sys_platform", "");
#endif
cvar_t sys_platform = CVAR("sys_platform", PLATFORM);
qboolean com_modified; // set true if using non-id files

View file

@ -54,7 +54,7 @@ qboolean Mod_LoadSurfedges (lump_t *l);
void Mod_LoadLighting (lump_t *l);
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contents, trace_t *trace);
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace);
static unsigned int CM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
static unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p);
static int CM_PointCluster (model_t *mod, vec3_t p);
@ -180,7 +180,12 @@ qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out);
extern model_t *loadmodel;
extern qbyte *mod_base;
#define capsuledist(dist,plane,mins,maxs) \
case shape_iscapsule: \
dist = DotProduct(trace_up, plane->normal); \
dist = dist*(trace_capsulesize[(dist<0)?1:2]) - trace_capsulesize[0]; \
dist = plane->dist - dist; \
break;
unsigned char d_q28to24table[1024];
@ -4796,12 +4801,19 @@ static vec3_t trace_start, trace_end;
static vec3_t trace_mins, trace_maxs;
static vec3_t trace_extents;
static vec3_t trace_absmins, trace_absmaxs;
static vec3_t trace_up; //capsule points upwards in this direction
static vec3_t trace_capsulesize; //radius, up, down
static float trace_truefraction;
static float trace_nearfraction;
static trace_t trace_trace;
static int trace_contents;
static qboolean trace_ispoint; // optimized case
static enum
{
shape_isbox,
shape_iscapsule,
shape_ispoint
} trace_shape; // optimized case
/*
================
@ -4838,11 +4850,10 @@ static void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
side = brush->brushside+i;
plane = side->plane;
// FIXME: special case for axial
if (!trace_ispoint)
{ // general box case
switch(trace_shape)
{
default:
case shape_isbox: // general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
@ -4855,10 +4866,11 @@ static void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
}
else
{ // special point case
break;
capsuledist(dist,plane,mins,maxs)
case shape_ispoint: // special point case
dist = plane->dist;
break;
}
d1 = DotProduct (p1, plane->normal) - dist;
@ -4953,12 +4965,13 @@ static void CM_ClipBoxToPlanes (vec3_t trmins, vec3_t trmaxs, vec3_t p1, vec3_t
for (i=0 ; i<numplanes ; i++, plane++)
{
// FIXME: special case for axial
if (!trace_ispoint)
{ // general box case
switch(trace_shape)
{
default:
case shape_isbox: // general box case
// push the plane out apropriately for mins/maxs
// FIXME: special case for axial
// FIXME: use signbits into 8 way lookup for each mins/maxs
for (j=0 ; j<3 ; j++)
{
@ -4969,10 +4982,11 @@ static void CM_ClipBoxToPlanes (vec3_t trmins, vec3_t trmaxs, vec3_t p1, vec3_t
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
}
else
{ // special point case
break;
capsuledist(dist,plane,trmins,trmaxs)
case shape_ispoint: // special point case
dist = plane->dist;
break;
}
d1 = DotProduct (p1, plane->normal) - dist;
@ -5187,11 +5201,11 @@ static void CM_ClipBoxToPatch (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
side = brush->brushside+i;
plane = side->plane;
if (!trace_ispoint)
{ // general box case
// push the plane out apropriately for mins/maxs
// push the plane out apropriately for mins/maxs
switch(trace_shape)
{
default:
case shape_isbox: // general box case
// FIXME: use signbits into 8 way lookup for each mins/maxs
for (j=0 ; j<3 ; j++)
{
@ -5202,10 +5216,11 @@ static void CM_ClipBoxToPatch (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
}
else
{ // special point case
break;
capsuledist(dist,plane,mins,maxs)
case shape_ispoint: // special point case
dist = plane->dist;
break;
}
d1 = DotProduct (p1, plane->normal) - dist;
@ -5290,22 +5305,29 @@ static void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1,
side = brush->brushside+i;
plane = side->plane;
// FIXME: special case for axial
// general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for (j=0 ; j<3 ; j++)
switch(trace_shape)
{
if (plane->normal[j] < 0)
ofs[j] = maxs[j];
else
ofs[j] = mins[j];
default:
case shape_isbox: // general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for (j=0 ; j<3 ; j++)
{
if (plane->normal[j] < 0)
ofs[j] = maxs[j];
else
ofs[j] = mins[j];
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
break;
capsuledist(dist,plane,mins,maxs)
case shape_ispoint:
dist = plane->dist;
break;
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
d1 = DotProduct (p1, plane->normal) - dist;
@ -5339,21 +5361,31 @@ static void CM_TestBoxInPatch (vec3_t mins, vec3_t maxs, vec3_t p1,
side = brush->brushside+i;
plane = side->plane;
// general box case
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for (j=0 ; j<3 ; j++)
switch(trace_shape)
{
if (plane->normal[j] < 0)
ofs[j] = maxs[j];
else
ofs[j] = mins[j];
}
default:
case shape_isbox:
// general box case
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
// push the plane out apropriately for mins/maxs
// FIXME: use signbits into 8 way lookup for each mins/maxs
for (j=0 ; j<3 ; j++)
{
if (plane->normal[j] < 0)
ofs[j] = maxs[j];
else
ofs[j] = mins[j];
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
break;
capsuledist(dist,plane,mins,maxs)
case shape_ispoint:
dist = plane->dist;
break;
}
d1 = DotProduct (p1, plane->normal) - dist;
@ -5567,7 +5599,7 @@ static void CM_RecursiveHullCheck (model_t *mod, int num, float p1f, float p2f,
{
t1 = DotProduct (plane->normal, p1) - plane->dist;
t2 = DotProduct (plane->normal, p2) - plane->dist;
if (trace_ispoint)
if (trace_shape == shape_ispoint)
offset = 0;
else
offset = fabs(trace_extents[0]*plane->normal[0]) +
@ -5651,7 +5683,7 @@ CM_BoxTrace
==================
*/
static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
vec3_t mins, vec3_t maxs,
vec3_t mins, vec3_t maxs, qboolean capsule,
int brushmask)
{
int i;
@ -5679,21 +5711,65 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
// build a bounding box of the entire move (for patches)
ClearBounds (trace_absmins, trace_absmaxs);
VectorAdd (start, trace_mins, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (start, trace_maxs, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (end, trace_mins, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (end, trace_maxs, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
//determine the type of trace that we're going to use, and the max extents
if (trace_mins[0] == 0 && trace_mins[1] == 0 && trace_mins[2] == 0 && trace_maxs[0] == 0 && trace_maxs[1] == 0 && trace_maxs[2] == 0)
{
trace_shape = shape_ispoint;
VectorSet (trace_extents, 1/32.0, 1/32.0, 1/32.0);
//acedemic
AddPointToBounds (start, trace_absmins, trace_absmaxs);
AddPointToBounds (end, trace_absmins, trace_absmaxs);
}
else if (capsule)
{
float ext;
trace_shape = shape_iscapsule;
//determine the capsule sizes
trace_capsulesize[0] = ((maxs[0]-mins[0]) + (maxs[1]-mins[1]))/4.0;
trace_capsulesize[1] = maxs[2];
trace_capsulesize[2] = mins[2];
ext = (trace_capsulesize[1] > -trace_capsulesize[2])?trace_capsulesize[1]:-trace_capsulesize[2];
trace_capsulesize[1] -= trace_capsulesize[0];
trace_capsulesize[2] += trace_capsulesize[0];
trace_extents[0] = ext+1;
trace_extents[1] = ext+1;
trace_extents[2] = ext+1;
//determine the total range
VectorSubtract (start, trace_extents, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (start, trace_extents, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorSubtract (end, trace_extents, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (end, trace_extents, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
}
else
{
VectorAdd (start, trace_mins, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (start, trace_maxs, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (end, trace_mins, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
VectorAdd (end, trace_maxs, point);
AddPointToBounds (point, trace_absmins, trace_absmaxs);
trace_shape = shape_isbox;
trace_extents[0] = ((-trace_mins[0] > trace_maxs[0]) ? -trace_mins[0] : trace_maxs[0])+1;
trace_extents[1] = ((-trace_mins[1] > trace_maxs[1]) ? -trace_mins[1] : trace_maxs[1])+1;
trace_extents[2] = ((-trace_mins[2] > trace_maxs[2]) ? -trace_mins[2] : trace_maxs[2])+1;
}
#if 0
if (0)
{ //treat *ALL* tests against the actual geometry instead of using any brushes.
//also ignores the bsp etc. not fast. testing only.
trace_ispoint = trace_mins[0] == 0 && trace_mins[1] == 0 && trace_mins[2] == 0
&& trace_maxs[0] == 0 && trace_maxs[1] == 0 && trace_maxs[2] == 0;
&& trace_maxs[0] == 0 && trace_maxs[1] == 0 && trace_maxs[2] == 0;
for (i = 0; i < mod->numsurfaces; i++)
{
@ -5703,13 +5779,14 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
else
if (0)
{
trace_ispoint = trace_mins[0] == 0 && trace_mins[1] == 0 && trace_mins[2] == 0
&& trace_maxs[0] == 0 && trace_maxs[1] == 0 && trace_maxs[2] == 0;
trace_ispoint = trace_mins[0] == 0 && trace_mins[1] == 0 && trace_mins[2] == 0
&& trace_maxs[0] == 0 && trace_maxs[1] == 0 && trace_maxs[2] == 0;
for (i = 0; i < mod->numleafs; i++)
CM_TraceToLeaf(&mod->leafs[i]);
}
else
#endif
//
// check for position test special case
//
@ -5739,24 +5816,10 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
return trace_trace;
}
//
// check for point special case
//
else if (trace_mins[0] == 0 && trace_mins[1] == 0 && trace_mins[2] == 0
&& trace_maxs[0] == 0 && trace_maxs[1] == 0 && trace_maxs[2] == 0)
{
trace_ispoint = true;
VectorClear (trace_extents);
CM_RecursiveHullCheck (mod, mod->hulls[0].firstclipnode, 0, 1, trace_start, trace_end);
}
//
// general aabb trace
//
else
{
trace_ispoint = false;
trace_extents[0] = ((-trace_mins[0] > trace_maxs[0]) ? -trace_mins[0] : trace_maxs[0])+1;
trace_extents[1] = ((-trace_mins[1] > trace_maxs[1]) ? -trace_mins[1] : trace_maxs[1])+1;
trace_extents[2] = ((-trace_mins[2] > trace_maxs[2]) ? -trace_mins[2] : trace_maxs[2])+1;
CM_RecursiveHullCheck (mod, mod->hulls[0].firstclipnode, 0, 1, trace_start, trace_end);
}
@ -5776,7 +5839,7 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
return trace_trace;
}
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contents, trace_t *trace)
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace)
{
if (axis)
{
@ -5788,12 +5851,13 @@ static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3
end_l[0] = DotProduct(end, axis[0]);
end_l[1] = DotProduct(end, axis[1]);
end_l[2] = DotProduct(end, axis[2]);
*trace = CM_BoxTrace(model, start_l, end_l, mins, maxs, contents);
VectorSet(trace_up, axis[0][2], -axis[1][2], axis[2][2]);
*trace = CM_BoxTrace(model, start_l, end_l, mins, maxs, capsule, contents);
#ifdef TERRAIN
if (model->terrain)
{
trace_t hmt;
Heightmap_Trace(model, forcehullnum, frame, NULL, start, end, mins, maxs, contents, &hmt);
Heightmap_Trace(model, forcehullnum, frame, NULL, start, end, mins, maxs, capsule, contents, &hmt);
if (hmt.fraction < trace->fraction)
*trace = hmt;
}
@ -5819,12 +5883,13 @@ static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3
}
else
{
*trace = CM_BoxTrace(model, start, end, mins, maxs, contents);
VectorSet(trace_up, 0, 0, 1);
*trace = CM_BoxTrace(model, start, end, mins, maxs, capsule, contents);
#ifdef TERRAIN
if (model->terrain)
{
trace_t hmt;
Heightmap_Trace(model, forcehullnum, frame, NULL, start, end, mins, maxs, contents, &hmt);
Heightmap_Trace(model, forcehullnum, frame, NULL, start, end, mins, maxs, capsule, contents, &hmt);
if (hmt.fraction < trace->fraction)
*trace = hmt;
}
@ -5860,6 +5925,7 @@ trace_t CM_TransformedBoxTrace (model_t *mod, vec3_t start, vec3_t end,
vec3_t forward, right, up;
vec3_t temp;
qboolean rotated;
qboolean capsule = false;
// subtract origin offset
VectorSubtract (start, origin, start_l);
@ -5885,10 +5951,16 @@ trace_t CM_TransformedBoxTrace (model_t *mod, vec3_t start, vec3_t end,
end_l[0] = DotProduct (temp, forward);
end_l[1] = -DotProduct (temp, right);
end_l[2] = DotProduct (temp, up);
VectorSet(trace_up, forward[2], -right[2], up[2]);
}
else
{
VectorSet(trace_up, 0, 0, 1);
}
// sweep the box through the model
trace = CM_BoxTrace (mod, start_l, end_l, mins, maxs, brushmask);
trace = CM_BoxTrace (mod, start_l, end_l, mins, maxs, capsule, brushmask);
if (rotated && trace.fraction != 1.0)
{

View file

@ -921,7 +921,7 @@ void PM_CategorizePosition (void)
VectorMA (pmove.origin, 24, flatforward, fwd1);
pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, 0, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, MASK_PLAYERSOLID, &t);
pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, 0, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, pmove.capsule, MASK_PLAYERSOLID, &t);
if (t.surface && t.surface->flags & Q3SURF_LADDER)
{
pmove.onladder = true;

View file

@ -67,6 +67,7 @@ typedef struct
int pm_type;
vec3_t player_mins;
vec3_t player_maxs;
qboolean capsule;
// world state
int numphysent;

View file

@ -226,7 +226,7 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
{
AngleVectors (angles, axis[0], axis[1], axis[2]);
VectorNegate(axis[1], axis[1]);
model->funcs.NativeTrace(model, 0, 0, axis, start_l, end_l, player_mins, player_maxs, MASK_PLAYERSOLID, trace);
model->funcs.NativeTrace(model, 0, 0, axis, start_l, end_l, player_mins, player_maxs, pmove.capsule, MASK_PLAYERSOLID, trace);
}
else
{
@ -237,7 +237,7 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
if (start_l[i]+player_maxs[i] < model->mins[i] && end_l[i] + player_maxs[i] < model->mins[i])
return false;
}
model->funcs.NativeTrace(model, 0, 0, NULL, start_l, end_l, player_mins, player_maxs, MASK_PLAYERSOLID, trace);
model->funcs.NativeTrace(model, 0, 0, NULL, start_l, end_l, player_mins, player_maxs, pmove.capsule, MASK_PLAYERSOLID, trace);
}
}
else

View file

@ -3911,11 +3911,7 @@ void QCBUILTIN PF_argescape(pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
void QCBUILTIN PF_random (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float num;
num = (rand ()&0x7fff) / ((float)0x8000);
G_FLOAT(OFS_RETURN) = num;
G_FLOAT(OFS_RETURN) = (rand ()&0x7fff) / ((float)0x8000);
}
//float(float number, float quantity) bitshift = #218;
@ -4284,15 +4280,14 @@ void QCBUILTIN PF_vectoyaw (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
//float(vector) vlen
void QCBUILTIN PF_vlen (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *value1;
float newv;
value1 = G_VECTOR(OFS_PARM0);
newv = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
newv = sqrt(newv);
G_FLOAT(OFS_RETURN) = newv;
float *value1 = G_VECTOR(OFS_PARM0);
G_FLOAT(OFS_RETURN) = sqrt(DotProduct(value1, value1));
}
//float(vector) vhlen
void QCBUILTIN PF_vhlen (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *value1 = G_VECTOR(OFS_PARM0);
G_FLOAT(OFS_RETURN) = sqrt(DotProduct2(value1, value1));
}
//vector vectoangles(vector)

View file

@ -144,6 +144,7 @@ void QCBUILTIN PF_fputs (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
void QCBUILTIN PF_fgets (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_normalize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_vlen (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_vhlen (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_changeyaw (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_changepitch (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_vectoyaw (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -435,8 +436,8 @@ void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored);
/*these are server ones, provided by pr_cmds.c, as required by pr_q1qvm.c*/
#ifdef VM_Q1
void PR_SV_FillWorldGlobals(world_t *w);
model_t *SVPR_GetCModel(world_t *w, int modelindex);
void SVPR_Event_Touch(world_t *w, wedict_t *s, wedict_t *o);
void QCBUILTIN PF_WriteByte (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_WriteChar (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_WriteShort (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View file

@ -2,7 +2,6 @@
#include "pr_common.h"
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, trace_t *trace);
/*
============================================================================
@ -840,7 +839,7 @@ hull_t *Q1BSP_ChooseHull(model_t *model, int forcehullnum, vec3_t mins, vec3_t m
VectorSubtract (hull->clip_mins, mins, offset);
return hull;
}
qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, trace_t *trace)
qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int hitcontentsmask, trace_t *trace)
{
hull_t *hull;
vec3_t start_l, end_l;
@ -942,7 +941,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
if (model->terrain && trace->fraction)
{
trace_t hmt;
Heightmap_Trace(model, forcehullnum, frame, axis, start, end, mins, maxs, hitcontentsmask, &hmt);
Heightmap_Trace(model, forcehullnum, frame, axis, start, end, mins, maxs, capsule, hitcontentsmask, &hmt);
if (hmt.fraction < trace->fraction)
*trace = hmt;
}

View file

@ -147,7 +147,7 @@ void TL_InitLanguages(void)
//#ifndef CLIENTONLY
#ifdef HEXEN2
//this stuff is for hexen2 translation strings.
//(hexen2 is uuuuggllyyyy...)
static char *strings_list;
@ -213,7 +213,6 @@ char *T_GetString(int num)
return strings_table[num];
}
//#endif
#ifndef SERVERONLY
//for hexen2's objectives and stuff.
@ -281,6 +280,7 @@ char *T_GetInfoString(int num)
return info_strings_table[num];
}
#endif
#endif
struct poline_s
{

View file

@ -248,6 +248,8 @@ int World_PointContents (world_t *w, vec3_t p);
wedict_t *World_TestEntityPosition (world_t *w, wedict_t *ent);
qboolean World_TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask);
/*
World_Move:
mins and maxs are reletive

View file

@ -2743,6 +2743,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
if (e->scale != 1 && e->scale != 0) //hexen 2 stuff
{
#ifdef HEXEN2
float z;
float escale;
escale = e->scale;
@ -2778,6 +2779,11 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
break;
}
}
#else
VectorScale((m+0), e->scale, (m+0));
VectorScale((m+4), e->scale, (m+4));
VectorScale((m+8), e->scale, (m+8));
#endif
}
else if (mod && !strcmp(mod->name, "progs/eyes.mdl"))
{

View file

@ -2614,6 +2614,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
if (e->scale != 1 && e->scale != 0) //hexen 2 stuff
{
#ifdef HEXEN2
float z;
float escale;
escale = e->scale;
@ -2649,6 +2650,11 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
break;
}
}
#else
VectorScale((m+0), e->scale, (m+0));
VectorScale((m+4), e->scale, (m+4));
VectorScale((m+8), e->scale, (m+8));
#endif
}
else if (mod && !strcmp(mod->name, "progs/eyes.mdl"))
{

View file

@ -601,7 +601,11 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
}
tc = e->topcolour;
bc = e->bottomcolour;
#ifdef HEXEN2
pc = e->h2playerclass;
#else
pc = 0;
#endif
if (forced || tc != TOP_DEFAULT || bc != BOTTOM_DEFAULT || plskin)
{
@ -690,7 +694,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
Hash_Add(&skincolourmapped, cm->name, cm, &cm->bucket);
cm->tcolour = tc;
cm->bcolour = bc;
cm->pclass = pc;
cm->pclass = pc; //is this needed? surely it'll be baked as part of the modelname?
cm->skinnum = e->skinnum;
cm->subframe = subframe;
cm->texnum.fullbright = r_nulltex;
@ -828,6 +832,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (scaled_height < 4)
scaled_height = 4;
#ifdef HEXEN2
if (h2playertranslations && pc)
{
unsigned int color_offsets[5] = {2*14*256,0,1*14*256,2*14*256,2*14*256};
@ -847,6 +852,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
translate32[0] = 0;
}
else
#endif
{
for (i=0 ; i<256 ; i++)
translate32[i] = d_8to24rgbtable[i];

View file

@ -3200,6 +3200,7 @@ typedef struct {
vec4_t plane;
vec3_t mins;
vec3_t maxs;
qboolean capsule;
float frac;
float htilesize;
heightmap_t *hm;
@ -3357,7 +3358,7 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
//do the trace
memset(&etr, 0, sizeof(etr));
etr.fraction = 1;
model->funcs.NativeTrace (model, 0, frame, s->ents[i]->ent.axis, start_l, end_l, tr->mins, tr->maxs, tr->hitcontentsmask, &etr);
model->funcs.NativeTrace (model, 0, frame, s->ents[i]->ent.axis, start_l, end_l, tr->mins, tr->maxs, tr->capsule, tr->hitcontentsmask, &etr);
tr->result->startsolid |= etr.startsolid;
tr->result->allsolid |= etr.allsolid;
@ -3528,7 +3529,7 @@ Why is recursion good?
Obviously, we don't care all that much about 1
*/
qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec3_t mataxis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace)
qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec3_t mataxis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
{
vec2_t pos, npos;
qboolean nudge[2];
@ -3551,6 +3552,7 @@ qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec
hmtrace.plane[1] = 0;
hmtrace.plane[2] = 0;
hmtrace.plane[3] = 0;
hmtrace.capsule = capsule;
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;

View file

@ -205,7 +205,7 @@ typedef struct {
unsigned int (*BoxContents) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
//deals with whatever is native for the bsp (gamecode is expected to distinguish this).
qboolean (*NativeTrace) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace);
qboolean (*NativeTrace) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace);
unsigned int (*NativeContents)(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
unsigned int (*FatPVS) (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge);
@ -499,7 +499,6 @@ int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangen
void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node);
void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
qboolean Q1BSP_Trace(struct model_s *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, struct trace_s *trace);
qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace);
qbyte *Q1BSP_LeafPVS (struct model_s *model, mleaf_t *leaf, qbyte *buffer, unsigned int buffersize);
@ -976,7 +975,7 @@ void Terr_FreeModel(model_t *mod);
void Terr_PurgeTerrainModel(model_t *hm, qboolean lightmapsonly, qboolean lightmapreusable);
void *Mod_LoadTerrainInfo(model_t *mod, char *loadname, qboolean force); //call this after loading a bsp
qboolean Terrain_LocateSection(char *name, flocation_t *loc); //used on servers to generate sections for download.
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, struct trace_s *trace);
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contentmask, struct trace_s *trace);
unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org);
struct fragmentdecal_s;
void Terrain_ClipDecal(struct fragmentdecal_s *dec, float *center, float radius, model_t *model);

View file

@ -312,6 +312,7 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
if (e->scale != 1 && e->scale != 0) //hexen 2 stuff
{
#ifdef HEXEN2
float z;
float escale;
escale = e->scale;
@ -347,6 +348,11 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
break;
}
}
#else
VectorScale((m+0), e->scale, (m+0));
VectorScale((m+4), e->scale, (m+4));
VectorScale((m+8), e->scale, (m+8));
#endif
}
else if (mod && !strcmp(mod->name, "progs/eyes.mdl"))
{

View file

@ -61,7 +61,7 @@ vec_t CastRay (vec3_t p1, vec3_t p2)
trace_t trace;
vec3_t move;
lightmodel->funcs.NativeTrace (lightmodel, 0, 0, NULL, p1, p2, vec3_origin, vec3_origin, FTECONTENTS_SOLID, &trace);
lightmodel->funcs.NativeTrace (lightmodel, 0, 0, NULL, p1, p2, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &trace);
if (trace.fraction < 1)
return -1;

View file

@ -18,7 +18,6 @@
#define fakeop fakeop16
#define dstatement_t dstatement16_t
#define sofs signed short
#define uofs unsigned short
#elif INTSIZE == 32
#define cont cont32
#define reeval reeval32
@ -26,7 +25,6 @@
#define fakeop fakeop32
#define dstatement_t dstatement32_t
#define sofs signed int
#define uofs unsigned int
#elif INTSIZE == 24
#error INTSIZE should be set to 32.
#else
@ -397,109 +395,6 @@ reeval:
*(unsigned char *)ptr = (char)OPA->_float;
break;
case OP_MULSTORE_F: // f *= f
OPB->_float *= OPA->_float;
break;
case OP_MULSTORE_VF: // v *= f
tmpf = OPA->_float;
OPB->_vector[0] *= tmpf;
OPB->_vector[1] *= tmpf;
OPB->_vector[2] *= tmpf;
break;
case OP_MULSTOREP_F: // e.f *= f
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float *= OPA->_float);
break;
case OP_MULSTOREP_VF: // e.v *= f
if (QCPOINTERWRITEFAIL(OPB, sizeof(vec3_t)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
tmpf = OPA->_float;
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] *= tmpf);
OPC->_vector[1] = (ptr->_vector[1] *= tmpf);
OPC->_vector[2] = (ptr->_vector[2] *= tmpf);
break;
case OP_DIVSTORE_F: // f /= f
OPB->_float /= OPA->_float;
break;
case OP_DIVSTOREP_F: // e.f /= f
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float /= OPA->_float);
break;
case OP_ADDSTORE_F: // f += f
OPB->_float += OPA->_float;
break;
case OP_ADDSTORE_V: // v += v
OPB->_vector[0] += OPA->_vector[0];
OPB->_vector[1] += OPA->_vector[1];
OPB->_vector[2] += OPA->_vector[2];
break;
case OP_ADDSTOREP_F: // e.f += f
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float += OPA->_float);
break;
case OP_ADDSTOREP_V: // e.v += v
if (QCPOINTERWRITEFAIL(OPB, sizeof(vec3_t)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]);
OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]);
OPC->_vector[2] = (ptr->_vector[2] += OPA->_vector[2]);
break;
case OP_SUBSTORE_F: // f -= f
OPB->_float -= OPA->_float;
break;
case OP_SUBSTORE_V: // v -= v
OPB->_vector[0] -= OPA->_vector[0];
OPB->_vector[1] -= OPA->_vector[1];
OPB->_vector[2] -= OPA->_vector[2];
break;
case OP_SUBSTOREP_F: // e.f -= f
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float -= OPA->_float);
break;
case OP_SUBSTOREP_V: // e.v -= v
if (QCPOINTERWRITEFAIL(OPB, sizeof(vec3_t)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]);
OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]);
OPC->_vector[2] = (ptr->_vector[2] -= OPA->_vector[2]);
break;
//get a pointer to a field var
case OP_ADDRESS:
if ((unsigned)OPA->edict >= (unsigned)sv_num_edicts)
@ -941,30 +836,31 @@ reeval:
OPC->_int = OPA->_int << OPB->_int;
break;
//hexen2 arrays contain a prefix global set to (arraysize-1) inserted before the actual array data
//for vectors, this prefix is the number of vectors rather than the number of globals. this can cause issues with using OP_FETCH_GBL_V within structs.
case OP_FETCH_GBL_F:
case OP_FETCH_GBL_S:
case OP_FETCH_GBL_E:
case OP_FETCH_GBL_FNC:
i = (int)OPB->_float;
if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
i = OPB->_float;
if((unsigned)i > (unsigned)((eval_t *)&glob[st->a-1])->_int)
{
pr_xstatement = st-pr_statements;
PR_RunError(&progfuncs->funcs, "array index out of bounds: %s[%d] (max %d)", PR_GlobalStringNoContents(progfuncs, st->a), i, ((eval_t *)&glob[st->a-1])->_int);
}
t = (eval_t *)&glob[(uofs)st->a + i];
OPC->_int = t->_int;
OPC->_int = ((eval_t *)&glob[st->a + i])->_int;
break;
case OP_FETCH_GBL_V:
i = (int)OPB->_float;
if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
i = OPB->_float;
if((unsigned)i > (unsigned)((eval_t *)&glob[st->a-1])->_int)
{
pr_xstatement = st-pr_statements;
PR_RunError(&progfuncs->funcs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
}
t = (eval_t *)&glob[(uofs)st->a + i*3];
OPC->_vector[0] = t->_vector[0];
OPC->_vector[1] = t->_vector[1];
OPC->_vector[2] = t->_vector[2];
ptr = (eval_t *)&glob[st->a + i*3];
OPC->_vector[0] = ptr->_vector[0];
OPC->_vector[1] = ptr->_vector[1];
OPC->_vector[2] = ptr->_vector[2];
break;
case OP_CSTATE:
@ -979,143 +875,184 @@ reeval:
externs->thinktimeop(&progfuncs->funcs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float);
break;
case OP_BITSETSTORE_F: // b (+) a
OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
case OP_MULSTORE_F:
/*OPC->_float = */OPB->_float *= OPA->_float;
break;
case OP_BITSETSTOREP_F: // .b (+) a
case OP_MULSTORE_VF:
tmpf = OPA->_float; //don't break on vec*=vec_x;
/*OPC->_vector[0] = */OPB->_vector[0] *= tmpf;
/*OPC->_vector[1] = */OPB->_vector[1] *= tmpf;
/*OPC->_vector[2] = */OPB->_vector[2] *= tmpf;
break;
case OP_MULSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_float = (float)((int)ptr->_float | (int)OPA->_float);
OPC->_float = ptr->_float *= OPA->_float;
break;
case OP_BITCLRSTORE_F: // b (-) a
OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
break;
case OP_BITCLRSTOREP_F: // .b (-) a
case OP_MULSTOREP_VF:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name));
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float));
tmpf = OPA->_float; //don't break on vec*=vec_x;
OPC->_vector[0] = ptr->_vector[0] *= tmpf;
OPC->_vector[1] = ptr->_vector[1] *= tmpf;
OPC->_vector[2] = ptr->_vector[2] *= tmpf;
break;
case OP_DIVSTORE_F:
/*OPC->_float = */OPB->_float /= OPA->_float;
break;
case OP_DIVSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = ptr->_float /= OPA->_float;
break;
case OP_ADDSTORE_F:
/*OPC->_float = */OPB->_float += OPA->_float;
break;
case OP_ADDSTORE_V:
/*OPC->_vector[0] =*/ OPB->_vector[0] += OPA->_vector[0];
/*OPC->_vector[1] =*/ OPB->_vector[1] += OPA->_vector[1];
/*OPC->_vector[2] =*/ OPB->_vector[2] += OPA->_vector[2];
break;
case OP_ADDSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = ptr->_float += OPA->_float;
break;
case OP_ADDSTOREP_V:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = ptr->_vector[0] += OPA->_vector[0];
OPC->_vector[1] = ptr->_vector[1] += OPA->_vector[1];
OPC->_vector[2] = ptr->_vector[2] += OPA->_vector[2];
break;
case OP_SUBSTORE_F:
/*OPC->_float = */OPB->_float -= OPA->_float;
break;
case OP_SUBSTORE_V:
/*OPC->_vector[0] = */OPB->_vector[0] -= OPA->_vector[0];
/*OPC->_vector[1] = */OPB->_vector[1] -= OPA->_vector[1];
/*OPC->_vector[2] = */OPB->_vector[2] -= OPA->_vector[2];
break;
case OP_SUBSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_float = ptr->_float -= OPA->_float;
break;
case OP_SUBSTOREP_V:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = ptr->_vector[0] -= OPA->_vector[0];
OPC->_vector[1] = ptr->_vector[1] -= OPA->_vector[1];
OPC->_vector[2] = ptr->_vector[2] -= OPA->_vector[2];
break;
case OP_BITSETSTORE_F:
OPB->_float = (int)OPB->_float | (int)OPA->_float;
break;
case OP_BITSETSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_float = (int)ptr->_float | (int)OPA->_float;
break;
case OP_BITCLRSTORE_F:
OPB->_float = (int)OPB->_float & ~(int)OPA->_float;
break;
case OP_BITCLRSTOREP_F:
if (QCPOINTERWRITEFAIL(OPB, sizeof(float)))
{
pr_xstatement = st-pr_statements;
PR_RunError (&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name), OPB->_int, prinst.addressableused);
}
ptr = QCPOINTER(OPB);
ptr->_float = (int)ptr->_float & ~(int)OPA->_float;
break;
//for scaler randoms, prevent the random value from ever reaching 1
//this avoids issues when array[random()*array.length]
case OP_RAND0:
OPC->_float = (rand()&0x7fff)/((float)0x7fff);
OPC->_float = (rand ()&0x7fff) / ((float)0x8000);
break;
case OP_RAND1:
OPC->_float = (rand()&0x7fff)/((float)0x7fff)*OPA->_float;
OPC->_float = (rand ()&0x7fff) / ((float)0x8000)*OPA->_float;
break;
case OP_RAND2:
if(OPA->_float < OPB->_float)
{
OPC->_float = OPA->_float+((rand()&0x7fff)/((float)0x7fff)
*(OPB->_float-OPA->_float));
}
else
{
OPC->_float = OPB->_float+((rand()&0x7fff)/((float)0x7fff)
*(OPA->_float-OPB->_float));
}
case OP_RAND2: //backwards range shouldn't matter (except that it is b that is never reached, rather than the higher of the two)
OPC->_float = OPA->_float + (rand ()&0x7fff) / ((float)0x8000)*(OPB->_float-OPA->_float);
break;
//random vectors DO result in 0 to 1 inclusive, to try to ensure a more balanced range
case OP_RANDV0:
OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff);
OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff);
OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff);
OPC->_vector[0] = (rand ()&0x7fff) / ((float)0x7fff);
OPC->_vector[1] = (rand ()&0x7fff) / ((float)0x7fff);
OPC->_vector[2] = (rand ()&0x7fff) / ((float)0x7fff);
break;
case OP_RANDV1:
OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0];
OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1];
OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2];
OPC->_vector[0] = (rand ()&0x7fff) / ((float)0x7fff)*OPA->_vector[0];
OPC->_vector[1] = (rand ()&0x7fff) / ((float)0x7fff)*OPA->_vector[1];
OPC->_vector[2] = (rand ()&0x7fff) / ((float)0x7fff)*OPA->_vector[2];
break;
case OP_RANDV2:
for(i = 0; i < 3; i++)
{
if(OPA->_vector[i] < OPB->_vector[i])
{
OPC->_vector[i] = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff)
*(OPB->_vector[i]-OPA->_vector[i]));
}
else
{
OPC->_vector[i] = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX)
*(OPA->_vector[i]-OPB->_vector[i]));
}
}
case OP_RANDV2: //backwards range shouldn't matter
OPC->_vector[0] = OPA->_vector[0] + (rand ()&0x7fff) / ((float)0x7fff)*(OPB->_vector[0]-OPA->_vector[0]);
OPC->_vector[1] = OPA->_vector[1] + (rand ()&0x7fff) / ((float)0x7fff)*(OPB->_vector[1]-OPA->_vector[1]);
OPC->_vector[2] = OPA->_vector[2] + (rand ()&0x7fff) / ((float)0x7fff)*(OPB->_vector[2]-OPA->_vector[2]);
break;
case OP_SWITCH_F:
case OP_SWITCH_V:
case OP_SWITCH_S:
case OP_SWITCH_E:
case OP_SWITCH_FNC:
swtch = OPA;
swtchtype = OPCODE;
//the case opcodes depend upon the preceding switch.
//otherwise the switch itself is much like a goto
//don't embed the case/caserange checks directly into the switch so that custom caseranges can be potentially be implemented with hybrid emulation.
switchcomparison = OPCODE - OP_SWITCH_F;
switchref = OPA;
RUNAWAYCHECK();
st += (sofs)st->b - 1; // offset the st++
st += (sofs)st->b - 1; // offset the s++
break;
case OP_CASE:
switch(swtchtype)
//if the comparison is true, jump (back up) to the relevent code block
if (casecmp[switchcomparison](progfuncs, switchref, OPA))
{
case OP_SWITCH_F:
if (swtch->_float == OPA->_float)
{
RUNAWAYCHECK();
st += (sofs)st->b-1; // -1 to offset the s++
}
break;
case OP_SWITCH_E:
case OP_SWITCH_FNC:
if (swtch->_int == OPA->_int)
{
RUNAWAYCHECK();
st += (sofs)st->b-1; // -1 to offset the s++
}
break;
case OP_SWITCH_S:
if (swtch->_int == OPA->_int)
{
RUNAWAYCHECK();
st += (sofs)st->b-1; // -1 to offset the s++
}
if ((!swtch->_int && PR_StringToNative(&progfuncs->funcs, OPA->string)) || (!OPA->_int && PR_StringToNative(&progfuncs->funcs, swtch->string))) //one is null (cannot be not both).
break;
if (!strcmp(PR_StringToNative(&progfuncs->funcs, swtch->string), PR_StringToNative(&progfuncs->funcs, OPA->string)))
{
RUNAWAYCHECK();
st += (sofs)st->b-1; // -1 to offset the s++
}
break;
case OP_SWITCH_V:
if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2])
{
RUNAWAYCHECK();
st += (sofs)st->b-1; // -1 to offset the s++
}
break;
default:
PR_RunError (&progfuncs->funcs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype);
break;
RUNAWAYCHECK();
st += (sofs)st->b-1; // -1 to offset the s++
}
break;
case OP_CASERANGE:
switch(swtchtype)
//if the comparison is true, jump (back up) to the relevent code block
if (casecmprange[switchcomparison](progfuncs, switchref, OPA, OPC))
{
case OP_SWITCH_F:
if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float)
{
RUNAWAYCHECK();
st += (sofs)st->c-1; // -1 to offset the s++
}
break;
default:
PR_RunError (&progfuncs->funcs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype);
RUNAWAYCHECK();
st += (sofs)st->c-1; // -1 to offset the s++
}
break;
@ -1126,7 +1063,6 @@ reeval:
case OP_BITAND_IF:
OPC->_int = (OPA->_int & (int)OPB->_float);
break;
@ -1316,7 +1252,6 @@ reeval:
#undef fakeop
#undef dstatement_t
#undef sofs
#undef uofs
#undef OPCODE
#undef ENGINEPOINTER

View file

@ -755,7 +755,7 @@ pbool LocateDebugTerm(progfuncs_t *progfuncs, char *key, eval_t **result, etype_
ed = PROG_TO_EDICT(progfuncs, val->_int);
if (!ed)
return false;
if (fofs < 0 || fofs >= max_fields_size)
if (fofs < 0 || fofs >= (int)max_fields_size)
return false;
val = (eval_t *) (((char *)ed->fields) + fofs*4);
}
@ -1240,6 +1240,41 @@ static char *lastfile = 0;
return statement;
}
static pbool casecmp_f(progfuncs_t *progfuncs, eval_t *ref, eval_t *val) {return ref->_float == val->_float;}
static pbool casecmp_i(progfuncs_t *progfuncs, eval_t *ref, eval_t *val) {return ref->_int == val->_int;}
static pbool casecmp_v(progfuncs_t *progfuncs, eval_t *ref, eval_t *val) {return ref->_vector[0] == val->_vector[0] &&
ref->_vector[1] == val->_vector[1] &&
ref->_vector[2] == val->_vector[2];}
static pbool casecmp_s(progfuncs_t *progfuncs, eval_t *ref, eval_t *val) { const char *refs = PR_StringToNative(&progfuncs->funcs, ref->string);
const char *vals = PR_StringToNative(&progfuncs->funcs, val->string);
return !strcmp(refs, vals);}
static pbool casecmprange_f(progfuncs_t *progfuncs, eval_t *ref, eval_t *min, eval_t *max) {return ref->_float >= min->_float && ref->_float <= max->_float;}
static pbool casecmprange_i(progfuncs_t *progfuncs, eval_t *ref, eval_t *min, eval_t *max) {return ref->_int >= min->_int && ref->_int <= max->_int;}
static pbool casecmprange_v(progfuncs_t *progfuncs, eval_t *ref, eval_t *min, eval_t *max) {return ref->_vector[0] >= min->_vector[0] && ref->_vector[0] <= max->_vector[0] &&
ref->_vector[1] >= min->_vector[1] && ref->_vector[1] <= max->_vector[1] &&
ref->_vector[2] >= min->_vector[2] && ref->_vector[2] <= max->_vector[2];}
static pbool casecmprange_bad(progfuncs_t *progfuncs, eval_t *ref, eval_t *min, eval_t *max){ PR_RunError (&progfuncs->funcs, "OP_CASERANGE type not supported");//BUG: pr_xstatement will not be correct.
return false;}
typedef pbool (*casecmp_t)(progfuncs_t *progfuncs, eval_t *ref, eval_t *val);
typedef pbool (*casecmprange_t)(progfuncs_t *progfuncs, eval_t *ref, eval_t *min, eval_t *max);
static casecmp_t casecmp[] =
{
casecmp_f, //float
casecmp_v, //vector
casecmp_s, //string
casecmp_i, //ent
casecmp_i //func
//pointer, field, int, etc are emulated with func or something. I dunno
};
static casecmprange_t casecmprange[] =
{
casecmprange_f, //float
casecmprange_v, //vector - I'm using a bbox, not really sure what it should be
casecmprange_bad, //string - should it use stof? string ranges don't relly make sense, at all.
casecmprange_i, //ent - doesn't really make sense, but as ints/pointers/fields/etc might be emulated with this, allow it anyway, as an int type.
casecmprange_i //func
};
#define RUNAWAYCHECK() \
if (!--*runaway) \
{ \
@ -1255,9 +1290,7 @@ static char *lastfile = 0;
static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *fte_restrict runaway)
{
eval_t *t, *swtch=NULL;
int swtchtype = 0; //warning about not being initialized before use
unsigned int switchcomparison = 0;
const dstatement16_t *fte_restrict st;
mfunction_t *fte_restrict newf;
int i;
@ -1268,6 +1301,8 @@ static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
float tmpf;
int tmpi;
eval_t *switchref = (eval_t*)glob;
#define OPA ((eval_t *)&glob[st->a])
#define OPB ((eval_t *)&glob[st->b])
#define OPC ((eval_t *)&glob[st->c])
@ -1312,9 +1347,7 @@ static int PR_ExecuteCode32 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
return -1;
#else
eval_t *t, *swtch=NULL;
int swtchtype = 0; //warning about not being initialized before use
unsigned int switchcomparison = 0;
const dstatement32_t *fte_restrict st;
mfunction_t *fte_restrict newf;
int i;
@ -1324,6 +1357,7 @@ static int PR_ExecuteCode32 (progfuncs_t *fte_restrict progfuncs, int s, int *ft
float *fte_restrict glob = pr_globals;
float tmpf;
int tmpi;
eval_t *switchref = (eval_t*)glob;
#define OPA ((eval_t *)&glob[st->a])
#define OPB ((eval_t *)&glob[st->b])

View file

@ -662,17 +662,19 @@ void NPP_NQFlush(void)
{
if (cl->state == cs_spawned && ISQWCLIENT(cl))
{
#ifdef HEXEN2
char *h2finale = NULL;
char *h2title = NULL;
/*
if (cl->zquake_extensions & Z_EXT_SERVERTIME)
{
/* ClientReliableCheckBlock(cl, 6);
ClientReliableCheckBlock(cl, 6);
ClientReliableWrite_Byte(cl, svc_updatestatlong);
ClientReliableWrite_Byte(cl, STAT_TIME);
ClientReliableWrite_Long(cl, (int)(sv.world.physicstime * 1000));
cl->nextservertimeupdate = sv.world.physicstime+10;
*/ }
}
*/
if (progstype == PROG_H2)
{
/*hexen2 does something like this in the client, but we don't support those protocols, so translate to something usable*/
@ -699,6 +701,7 @@ void NPP_NQFlush(void)
ClientReliableWrite_String(cl, h2finale);
}
else
#endif
{
ClientReliableCheckBlock(cl, 16);
ClientReliableWrite_Byte(cl, svc_intermission);

File diff suppressed because it is too large Load diff

View file

@ -1940,7 +1940,6 @@ static qboolean Lua_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldw
return false; //always do legacy behaviour
}
void PR_SV_FillWorldGlobals(world_t *w);
static void Lua_SetupGlobals(world_t *world)
{
int flds;

View file

@ -47,8 +47,6 @@ oh, wait, ktx no longer supports those properly.
#define MAX_Q1QVM_EDICTS 768 //according to ktx at api version 12 (fte's protocols go to 2048)
#define MAPNAME_LEN 64
#define VMFSID_Q1QVM 57235 //a cookie
void PR_SV_FillWorldGlobals(world_t *w);
#if GAME_API_VERSION >= 13
@ -561,7 +559,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con
case G_GetEntityToken:
{
if (VM_OOB(arg[0], arg[1]))
if (VM_OOB(arg[0], arg[1]) || !arg[1])
return false;
if (q1qvmentstring)
{
@ -573,7 +571,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con
else
{
char *ret = VM_POINTER(arg[0]);
strcpy(ret, "");
*ret = '\0';
return false;
}
}

View file

@ -126,6 +126,7 @@ void PF_InitTempStrings(pubprogfuncs_t *prinst);
qboolean PR_LoadLua(void);
#endif
#ifdef VM_Q1
#define VMFSID_Q1QVM 57235 //the q1qvm zone tag that is freed when the module is purged.
struct client_s;
void Q1QVM_Shutdown(void);
qboolean PR_LoadQ1QVM(void);

View file

@ -77,7 +77,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
int filelen, filepos;
char *file;
char *modelnames[MAX_MODELS];
char *modelnames[MAX_PRECACHE_MODELS];
if (version != 667 && version != 5 && version != 6) //5 for NQ, 6 for ZQ/FQ
{
@ -241,7 +241,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
}
//model names are pointers to vm-accessible memory. as that memory is going away, we need to destroy and recreate, which requires preserving them.
for (i = 1; i < MAX_MODELS; i++)
for (i = 1; i < MAX_PRECACHE_MODELS; i++)
{
if (!sv.strings.model_precache[i])
{
@ -268,7 +268,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version)
}
//reload model names.
for (i = 1; i < MAX_MODELS; i++)
for (i = 1; i < MAX_PRECACHE_MODELS; i++)
{
if (!modelnames[i])
break;
@ -480,7 +480,7 @@ void LoadModelsAndSounds(vfsfile_t *f)
int i;
sv.strings.model_precache[0] = PR_AddString(svprogfuncs, "", 0, false);
for (i=1; i < MAX_MODELS; i++)
for (i=1; i < MAX_PRECACHE_MODELS; i++)
{
VFS_GETS(f, str, sizeof(str));
if (!*str)
@ -488,17 +488,17 @@ void LoadModelsAndSounds(vfsfile_t *f)
sv.strings.model_precache[i] = PR_AddString(svprogfuncs, str, 0, false);
}
if (i == MAX_MODELS)
if (i == MAX_PRECACHE_MODELS)
{
VFS_GETS(f, str, sizeof(str));
if (*str)
SV_Error("Too many model precaches in loadgame cache");
}
for (; i < MAX_MODELS; i++)
for (; i < MAX_PRECACHE_MODELS; i++)
sv.strings.model_precache[i] = NULL;
// sv.sound_precache[0] = PR_AddString(svprogfuncs, "", 0);
for (i=1; i < MAX_SOUNDS; i++)
for (i=1; i < MAX_PRECACHE_SOUNDS; i++)
{
VFS_GETS(f, str, sizeof(str));
if (!*str)
@ -506,13 +506,13 @@ void LoadModelsAndSounds(vfsfile_t *f)
// sv.sound_precache[i] = PR_AddString(svprogfuncs, str, 0);
}
if (i == MAX_SOUNDS)
if (i == MAX_PRECACHE_SOUNDS)
{
VFS_GETS(f, str, sizeof(str));
if (*str)
SV_Error("Too many sound precaches in loadgame cache");
}
for (; i < MAX_SOUNDS; i++)
for (; i < MAX_PRECACHE_SOUNDS; i++)
*sv.strings.sound_precache[i] = 0;
}
@ -944,7 +944,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
VFS_PRINTF (f, "%s\n", sv.strings.lightstyles[i]?sv.strings.lightstyles[i]:"");
}
for (i=1 ; i<MAX_MODELS ; i++)
for (i=1 ; i<MAX_PRECACHE_MODELS ; i++)
{
if (sv.strings.model_precache[i] && *sv.strings.model_precache[i])
VFS_PRINTF (f, "%s\n", sv.strings.model_precache[i]);
@ -952,7 +952,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
break;
}
VFS_PRINTF (f,"\n");
for (i=1 ; i<MAX_SOUNDS ; i++)
for (i=1 ; i<MAX_PRECACHE_SOUNDS ; i++)
{
if (*sv.strings.sound_precache[i])
VFS_PRINTF (f, "%s\n", sv.strings.sound_precache[i]);

View file

@ -134,9 +134,9 @@ typedef struct
#endif
struct {
const char *vw_model_precache[32];
const char *model_precache[MAX_MODELS]; // NULL terminated
const char *model_precache[MAX_PRECACHE_MODELS]; // NULL terminated
char particle_precache[MAX_SSPARTICLESPRE][MAX_QPATH]; // NULL terminated
char sound_precache[MAX_SOUNDS][MAX_QPATH]; // NULL terminated
char sound_precache[MAX_PRECACHE_SOUNDS][MAX_QPATH]; // NULL terminated
const char *lightstyles[MAX_LIGHTSTYLES];
vec3_t lightstylecolours[MAX_LIGHTSTYLES];
};
@ -148,7 +148,7 @@ typedef struct
int spawned_client_slots; //number of PLAYER slots which are active (ie: putclientinserver was called)
int spawned_observer_slots;
model_t *models[MAX_MODELS];
model_t *models[MAX_PRECACHE_MODELS];
qbyte *pvs, *phs; // fully expanded and decompressed
struct client_s *skipbprintclient; //SV_BroadcastPrint skips this client
@ -949,7 +949,7 @@ extern client_t *host_client;
extern edict_t *sv_player;
extern char localmodels[MAX_MODELS][5]; // inline model names for precache
//extern char localmodels[MAX_MODELS][5]; // inline model names for precache
extern char localinfo[MAX_LOCALINFO_STRING+1];
@ -1094,7 +1094,6 @@ trace_t WPhys_Trace_Toss (world_t *w, wedict_t *ent, wedict_t *ignore);
void SV_ProgStartFrame (void);
void WPhys_RunEntity (world_t *w, wedict_t *ent);
qboolean WPhys_RunThink (world_t *w, wedict_t *ent);
void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *initial_origin, float *initial_angle); /*here for player movement to do movechains too*/
//
// sv_send.c
@ -1399,8 +1398,6 @@ void SV_FlushLevelCache(void);
int SV_RateForClient(client_t *cl);
qboolean TransformedNativeTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace, vec3_t origin, vec3_t angles);
void SVVC_Frame (qboolean enabled);
void SV_CalcPHS (void);

View file

@ -392,10 +392,10 @@ static void SV_MapList_f(void)
COM_EnumerateFiles("maps/*.hmp", ShowMapList, NULL);
}
static void gtcallback(struct cvar_s *var, char *oldvalue)
{
Con_Printf("g_gametype changed\n");
}
//static void gtcallback(struct cvar_s *var, char *oldvalue)
//{
// Con_Printf("g_gametype changed\n");
//}
/*
======================
@ -624,7 +624,7 @@ void SV_Map_f (void)
Cvar_ForceSet(gametype, level);
gametype = Cvar_Get("g_gametype", "", CVAR_LATCH|CVAR_SERVERINFO, "Q3 compatability");
gametype->callback = gtcallback;
// gametype->callback = gtcallback;
if (q3singleplayer)
Cvar_ForceSet(gametype, "2");//singleplayer
else if (gametype->value == 2)
@ -1731,14 +1731,14 @@ static void SV_Status_f (void)
{
int count = 0;
Con_Printf("entities : %i/%i (mem: %i/%i)\n", sv.world.num_edicts, sv.world.max_edicts, sv.world.progs->stringtablesize, sv.world.progs->stringtablemaxsize);
for (count = 1; count < MAX_MODELS; count++)
for (count = 1; count < MAX_PRECACHE_MODELS; count++)
if (!sv.strings.model_precache[count])
break;
Con_Printf("models : %i/%i\n", count, MAX_MODELS);
for (count = 1; count < MAX_SOUNDS; count++)
Con_Printf("models : %i/%i\n", count, MAX_PRECACHE_MODELS);
for (count = 1; count < MAX_PRECACHE_SOUNDS; count++)
if (!*sv.strings.sound_precache[count])
break;
Con_Printf("sounds : %i/%i\n", count, MAX_SOUNDS);
Con_Printf("sounds : %i/%i\n", count, MAX_PRECACHE_SOUNDS);
}
Con_Printf("gamedir : %s\n", FS_GetGamedir(true));
if (sv.csqcdebug)

View file

@ -1238,7 +1238,13 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
// Con_Printf("Gen sequence %i\n", sequence);
MSG_WriteFloat(msg, sv.world.physicstime);
for(j = 0; j < client->sentents.num_entities; j++)
if (client->pendingentbits[0] & UF_REMOVE)
{
SV_EmitDeltaEntIndex(msg, 0, true, true);
resendbits[outno] = UF_REMOVE;
resendnum[outno++] = 0;
}
for(j = 1; j < client->sentents.num_entities; j++)
{
bits = client->pendingentbits[j];
if (!(bits & ~UF_RESET2)) //skip while there's nothing to send (skip reset2 if there's no other changes, its only to reduce chances of the client getting 'new' entities containing just an origin)*/
@ -2019,7 +2025,7 @@ qboolean Cull_Traceline(pvscamera_t *cameras, edict_t *seen)
for (c = 0; c < cameras->numents; c++)
{
tr.fraction = 1;
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, 0, NULL, cameras->org[c], seen->v->origin, vec3_origin, vec3_origin, FTECONTENTS_SOLID, &tr))
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, 0, NULL, cameras->org[c], seen->v->origin, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &tr))
return false; //wasn't blocked
}
@ -2033,7 +2039,7 @@ qboolean Cull_Traceline(pvscamera_t *cameras, edict_t *seen)
end[2] = seen->v->origin[2] + ((i&4)?seen->v->mins[2]+0.1:seen->v->maxs[2]);
tr.fraction = 1;
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, 0, NULL, cameras->org[c], end, vec3_origin, vec3_origin, FTECONTENTS_SOLID, &tr))
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, 0, NULL, cameras->org[c], end, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &tr))
return false; //this trace went through, so don't cull
}
}
@ -2898,7 +2904,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
else if (ent->v->solid == SOLID_BBOX || ent->v->solid == SOLID_SLIDEBOX || ent->v->skin < 0)
{
unsigned int mdl = ent->v->modelindex;
if (mdl < MAX_MODELS && sv.models[mdl] && sv.models[mdl]->type == mod_brush)
if (mdl < MAX_PRECACHE_MODELS && sv.models[mdl] && sv.models[mdl]->type == mod_brush)
state->solid = ES_SOLID_BSP;
else
{

View file

@ -31,8 +31,6 @@ server_t sv; // local server
entity_state_t *sv_staticentities;
int sv_max_staticentities;
char localmodels[MAX_MODELS][5]; // inline model names for precache
char localinfo[MAX_LOCALINFO_STRING+1]; // local game info
extern cvar_t skill, sv_loadentfiles;
@ -57,12 +55,12 @@ int SV_ModelIndex (const char *name)
if (!name || !name[0])
return 0;
for (i=1 ; i<MAX_MODELS && sv.strings.model_precache[i] ; i++)
for (i=1 ; i<MAX_PRECACHE_MODELS && sv.strings.model_precache[i] ; i++)
if (!strcmp(sv.strings.model_precache[i], name))
return i;
if (i==MAX_MODELS || !sv.strings.model_precache[i])
if (i==MAX_PRECACHE_MODELS || !sv.strings.model_precache[i])
{
if (i!=MAX_MODELS)
if (i!=MAX_PRECACHE_MODELS)
{
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
@ -98,10 +96,10 @@ int SV_SafeModelIndex (char *name)
if (!name || !name[0])
return 0;
for (i=1 ; i<MAX_MODELS && sv.strings.model_precache[i] ; i++)
for (i=1 ; i<MAX_PRECACHE_MODELS && sv.strings.model_precache[i] ; i++)
if (!strcmp(sv.strings.model_precache[i], name))
return i;
if (i==MAX_MODELS || !sv.strings.model_precache[i])
if (i==MAX_PRECACHE_MODELS || !sv.strings.model_precache[i])
{
return 0;
}
@ -817,7 +815,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
Z_Free(svs.clients[i].spawninfo);
svs.clients[i].spawninfo = NULL;
}
#ifdef HEXEN2
T_FreeStrings();
#endif
}
for (i = 0; i < svs.allocated_client_slots; i++)
@ -1093,14 +1093,25 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
{
int subs;
strcpy(sv.strings.sound_precache[0], "");
sv.strings.model_precache[0] = "";
sv.strings.model_precache[1] = sv.modelname; //the qvm doesn't have access to this array
for (i=1 ; i<sv.world.worldmodel->numsubmodels ; i++)
subs = sv.world.worldmodel->numsubmodels;
if (subs > MAX_PRECACHE_MODELS-2)
{
sv.strings.model_precache[1+i] = localmodels[i];
sv.models[i+1] = Mod_ForName (localmodels[i], MLV_WARN);
Con_Printf("Warning: worldmodel has too many submodels\n");
subs = MAX_PRECACHE_MODELS-2;
}
sv.strings.model_precache[1] = sv.modelname; //the qvm doesn't have access to this array
for (i=1 ; i<subs ; i++)
{
char *z, *s = va("*%u", i);
z = Z_TagMalloc(strlen(s)+1, VMFSID_Q1QVM);
strcpy(z, s);
sv.strings.model_precache[1+i] = z;
sv.models[i+1] = Mod_ForName (z, MLV_WARN);
}
//check player/eyes models for hacks
@ -1115,14 +1126,22 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
#endif
)
{
int subs;
strcpy(sv.strings.sound_precache[0], "");
sv.strings.model_precache[0] = "";
sv.strings.model_precache[1] = PR_AddString(svprogfuncs, sv.modelname, 0, false);
for (i=1 ; i<sv.world.worldmodel->numsubmodels ; i++)
subs = sv.world.worldmodel->numsubmodels;
if (subs > MAX_PRECACHE_MODELS-2)
{
sv.strings.model_precache[1+i] = PR_AddString(svprogfuncs, localmodels[i], 0, false);
sv.models[i+1] = Mod_ForName (localmodels[i], MLV_WARN);
Con_Printf("Warning: worldmodel has too many submodels\n");
subs = MAX_PRECACHE_MODELS-2;
}
for (i=1 ; i<subs ; i++)
{
sv.strings.model_precache[1+i] = PR_AddString(svprogfuncs, va("*%u", i), 0, false);
sv.models[i+1] = Mod_ForName (sv.strings.model_precache[1+i], MLV_WARN);
}
//check player/eyes models for hacks
@ -1132,6 +1151,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
#ifdef Q2SERVER
else if (svs.gametype == GT_QUAKE2)
{
int subs;
extern int map_checksum;
extern cvar_t sv_airaccelerate;
@ -1148,11 +1168,18 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
else
strcpy(sv.strings.configstring[Q2CS_MAPCHECKSUM], "0");
subs = sv.world.worldmodel->numsubmodels;
if (subs > Q2MAX_MODELS-2)
{
Con_Printf("Warning: worldmodel has too many submodels\n");
subs = Q2MAX_MODELS-2;
}
strcpy(sv.strings.configstring[Q2CS_MODELS+1], sv.modelname);
for (i=1; i<sv.world.worldmodel->numsubmodels; i++)
{
strcpy(sv.strings.configstring[Q2CS_MODELS+1+i], localmodels[i]);
sv.models[i+1] = Mod_ForName (localmodels[i], MLV_WARN);
Q_snprintfz(sv.strings.configstring[Q2CS_MODELS+1+i], sizeof(sv.strings.configstring[Q2CS_MODELS+1+i]), "*%u", i);
sv.models[i+1] = Mod_ForName (sv.strings.configstring[Q2CS_MODELS+1+i], MLV_WARN);
}
}
#endif
@ -1480,9 +1507,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
val = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "message", NULL);
if (val)
{
#ifdef HEXEN2
if (progstype == PROG_H2)
snprintf(sv.mapname, sizeof(sv.mapname), "%s", T_GetString(val->_float-1));
else
#endif
snprintf(sv.mapname, sizeof(sv.mapname), "%s", PR_GetString(svprogfuncs, val->string));
}
else

View file

@ -275,7 +275,9 @@ void SV_Shutdown (void)
Z_Free(lp);
}
#ifdef HEXEN2
T_FreeStrings();
#endif
SV_GibFilterPurge();
@ -1745,7 +1747,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
//you need to reconnect for this to update, of course. so make sure its not *too* low...
client->max_net_ents = bound(512, pr_maxedicts.ival, MAX_EDICTS);
client->maxmodels = MAX_MODELS; //protocol limited to 14 bits.
client->maxmodels = MAX_PRECACHE_MODELS; //protocol limited to 14 bits.
}
else if (ISQWCLIENT(client)) //readd?
{
@ -1757,7 +1759,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
client->max_net_ents += 1024;
if (client->fteprotocolextensions & PEXT_MODELDBL)
client->maxmodels = MAX_MODELS;
client->maxmodels = MAX_PRECACHE_MODELS;
}
else if (ISDPCLIENT(client))
{
@ -4546,9 +4548,6 @@ void SV_InitLocal (void)
SV_MVDInit();
for (i=0 ; i<MAX_MODELS ; i++)
sprintf (localmodels[i], "*%i", i);
Info_SetValueForStarKey (svs.info, "*version", version_string(), MAX_SERVERINFO_STRING);
Info_SetValueForStarKey (svs.info, "*z_ext", va("%i", SUPPORTED_Z_EXTENSIONS), MAX_SERVERINFO_STRING);
@ -5034,11 +5033,13 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
else
cl->drate = cl->rate; //0 disables the downloading check
#ifdef HEXEN2
val = Info_ValueForKey (cl->userinfo, "cl_playerclass");
if (val)
{
PRH2_SetPlayerClass(cl, atoi(val), false);
}
#endif
// msg command
val = Info_ValueForKey (cl->userinfo, "msg");

View file

@ -1331,7 +1331,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
if (trace.allsolid)
{
if (progstype != PROG_H2)
trace.fraction = 0;
trace.fraction = 0; //traces that start in solid report a fraction of 0. this is to prevent things from dropping out of the world completely. at least this way they ought to still be shootable etc
#pragma warningmsg("The following line might help boost framerates a lot in rmq, not sure if they violate expected behaviour in other mods though - check that they're safe.")
VectorNegate(gravitydir, trace.plane.normal);
@ -1976,6 +1976,7 @@ static void WPhys_WalkMove (world_t *w, wedict_t *ent, const float *gravitydir)
}
#endif
#ifdef HEXEN2
void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *initial_origin, float *initial_angle)
{
qboolean callfunc;
@ -2006,6 +2007,7 @@ void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *init
}
}
}
#endif
/*
================
@ -2015,8 +2017,10 @@ SV_RunEntity
*/
void WPhys_RunEntity (world_t *w, wedict_t *ent)
{
#ifdef HEXEN2
wedict_t *movechain;
vec3_t initial_origin = {0},initial_angle = {0}; // warning: initial_?[?] may be used uninitialized in this function
#endif
const float *gravitydir;
#ifndef CLIENTONLY
@ -2071,13 +2075,14 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
}
#ifdef HEXEN2
movechain = PROG_TO_WEDICT(w->progs, ent->xv->movechain);
if (movechain != w->edicts)
{
VectorCopy(ent->v->origin,initial_origin);
VectorCopy(ent->v->angles,initial_angle);
}
#endif
switch ( (int)ent->v->movetype)
{
@ -2140,10 +2145,10 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
break;
}
#ifdef HEXEN2
if (movechain != w->edicts)
{
WPhys_MoveChain(w, ent, movechain, initial_origin, initial_angle);
}
#endif
#ifndef CLIENTONLY
if (svent)

View file

@ -995,15 +995,15 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, const cha
return;
else
{
for (sound_num=1 ; sound_num<MAX_SOUNDS
for (sound_num=1 ; sound_num<MAX_PRECACHE_SOUNDS
&& *sv.strings.sound_precache[sound_num] ; sound_num++)
if (!strcmp(sample, sv.strings.sound_precache[sound_num]))
break;
}
if ( sound_num == MAX_SOUNDS || !*sv.strings.sound_precache[sound_num] )
if ( sound_num == MAX_PRECACHE_SOUNDS || !*sv.strings.sound_precache[sound_num] )
{
if (sound_num < MAX_SOUNDS)
if (sound_num < MAX_PRECACHE_SOUNDS)
{
Con_Printf("WARNING: SV_StartSound: sound %s not precached\n", sample);
//late precache it. use multicast to ensure that its sent NOW (and to all). normal reliables would mean it would arrive after the svc_sound
@ -1187,7 +1187,7 @@ void SV_FindModelNumbers (void)
sv_supernailmodel = -1;
sv_playermodel = -1;
for (i=0 ; i<MAX_MODELS ; i++)
for (i=0 ; i<MAX_PRECACHE_MODELS ; i++)
{
if (!sv.strings.model_precache[i])
break;
@ -1750,7 +1750,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
statsi[STAT_WEAPON] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel));
if (client->fteprotocolextensions & PEXT_MODELDBL)
{
if ((unsigned)statsi[STAT_WEAPON] >= MAX_MODELS)
if ((unsigned)statsi[STAT_WEAPON] >= MAX_PRECACHE_MODELS)
statsi[STAT_WEAPON] = 0;
}
else

View file

@ -983,7 +983,7 @@ void SV_SendClientPrespawnInfo(client_t *client)
int maxclientsupportedsounds = 256;
#ifdef PEXT_SOUNDDBL
if (client->fteprotocolextensions & PEXT_SOUNDDBL)
maxclientsupportedsounds = MAX_SOUNDS;
maxclientsupportedsounds = MAX_PRECACHE_SOUNDS;
#endif
started = false;
@ -5932,6 +5932,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
pmove.physents[0].model = sv.world.worldmodel;
pmove.cmd = *ucmd;
pmove.hullnum = SV_HullNumForPlayer(0, player_mins, player_maxs);
pmove.capsule = (sv_player->xv->geomtype == GEOMTYPE_CAPSULE);
movevars.entgravity = 0;
movevars.maxspeed = 0;
@ -6125,6 +6126,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
pmove.physents[0].model = sv.world.worldmodel;
pmove.cmd = *ucmd;
pmove.skipent = -1;
pmove.capsule = (sv_player->xv->geomtype == GEOMTYPE_CAPSULE);
movevars.entgravity = host_client->entgravity/movevars.gravity;
movevars.maxspeed = host_client->maxspeed;

View file

@ -1655,6 +1655,7 @@ extern cvar_t temp1;
pmove.physents[0].info = 0;
pmove.skipent = -1;
pmove.onladder = false;
pmove.capsule = false;
if (ed->v.flags & (1<<24))
{

View file

@ -707,7 +707,7 @@ static int VARGS SVQ2_AreaEdicts (vec3_t mins, vec3_t maxs, q2edict_t **list, in
static model_t *SVQ2_GetCModel(world_t *w, int modelindex)
{
if ((unsigned int)modelindex < MAX_MODELS)
if ((unsigned int)modelindex < MAX_PRECACHE_MODELS)
return sv.models[modelindex];
else
return NULL;

View file

@ -156,7 +156,7 @@ static void Q3G_UnlinkEntity(q3sharedEntity_t *ent)
static model_t *Q3G_GetCModel(unsigned int modelindex)
{
if ((unsigned int)modelindex < MAX_MODELS)
if ((unsigned int)modelindex < MAX_PRECACHE_MODELS)
{
if (!sv.models[modelindex])
{
@ -416,7 +416,7 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs
if (!maxs)
maxs = vec3_origin;
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, mins, maxs, contentmask, &tr);
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, mins, maxs, capsule, contentmask, &tr);
result->allsolid = tr.allsolid;
result->contents = tr.contents;
VectorCopy(tr.endpos, result->endpos);
@ -476,7 +476,6 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs
if (es->r.bmodel)
{
//FIXME, this is inefficient.
mod = Q3G_GetCModel(es->s.modelindex);
if (!mod)
continue;
@ -484,9 +483,11 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs
}
else
{
mod = CM_TempBoxModel(es->r.mins, es->r.maxs);
if (es->r.svFlags & SVF_CAPSULE)
mod = CM_TempBoxModel(es->r.mins, es->r.maxs);
else
mod = CM_TempBoxModel(es->r.mins, es->r.maxs);
tr = CM_TransformedBoxTrace(mod, start, end, mins, maxs, contentmask, es->r.currentOrigin, es->r.currentAngles);
// mod->funcs.Trace(mod, 0, 0, start, end, mins, maxs, &tr);
}
if (tr.fraction < result->fraction)
{

View file

@ -46,7 +46,8 @@ typedef struct
#ifdef Q2SERVER
q2edict_t *q2passedict;
#endif
int hullnum;
int hullnum;
qboolean capsule;
} moveclip_t;
/*
@ -119,6 +120,26 @@ hull_t *World_HullForBox (vec3_t mins, vec3_t maxs)
return &box_hull;
}
model_t mod_capsule;
qboolean World_BoxTrace(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace)
{
//bbox vs bbox (NYI)
//capsule vs bbox (NYI)
return false;
}
qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
{
//bbox vs capsule (NYI)
//capsule vs capsule (NYI)
return false;
}
model_t *World_CapsuleForBox(vec3_t mins, vec3_t maxs)
{
VectorCopy(mins, mod_capsule.mins);
VectorCopy(maxs, mod_capsule.maxs);
mod_capsule.funcs.NativeTrace = World_CapsuleTrace;
return &mod_capsule;
}
/*
===============================================================================
@ -910,7 +931,7 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
//wrapper function. Rotates the start and end positions around the angles if needed.
//qboolean TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_t *trace, vec3_t angles)
qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask)
qboolean World_TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask)
{
vec3_t start_l, end_l;
vec3_t axis[3];
@ -929,71 +950,23 @@ qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, v
return false;
}
// don't rotate non bsp ents. Too small to bother.
if (model && !model->needload)
{
VectorSubtract (start, origin, start_l);
VectorSubtract (end, origin, end_l);
if (angles[0] || angles[1] || angles[2])
{
AngleVectors (angles, axis[0], axis[1], axis[2]);
VectorNegate(axis[1], axis[1]);
result = model->funcs.NativeTrace (model, hulloverride, frame, axis, start_l, end_l, mins, maxs, hitcontentsmask, trace);
}
else
{
result = model->funcs.NativeTrace (model, hulloverride, frame, NULL, start_l, end_l, mins, maxs, hitcontentsmask, trace);
}
VectorAdd (trace->endpos, origin, trace->endpos);
}
else
{
hull_t *hull = &box_hull;
memset (trace, 0, sizeof(trace_t));
trace->fraction = 1;
trace->allsolid = true;
VectorSubtract (start, origin, start_l);
VectorSubtract (end, origin, end_l);
VectorCopy (end_l, trace->endpos);
result = Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, trace);
VectorAdd (trace->endpos, origin, trace->endpos);
}
return result;
}
qboolean TransformedNativeTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace, vec3_t origin, vec3_t angles)
{
vec3_t start_l, end_l;
vec3_t axis[3];
qboolean result;
memset (trace, 0, sizeof(trace_t));
trace->fraction = 1;
trace->allsolid = false;
trace->startsolid = false;
trace->inopen = true; //probably wrong...
VectorCopy (end, trace->endpos);
// don't rotate non bsp ents. Too small to bother.
if (model)
{
VectorSubtract (start, origin, start_l);
VectorSubtract (end, origin, end_l);
if (angles[0] || angles[1] || angles[2])
{
AngleVectors (angles, axis[0], axis[1], axis[2]);
VectorNegate(axis[1], axis[1]);
result = model->funcs.NativeTrace (model, hulloverride, frame, axis, start_l, end_l, mins, maxs, against, trace);
result = model->funcs.NativeTrace (model, hulloverride, frame, axis, start_l, end_l, mins, maxs, capsule, hitcontentsmask, trace);
}
else
{
result = model->funcs.NativeTrace (model, hulloverride, frame, NULL, start_l, end_l, mins, maxs, against, trace);
result = model->funcs.NativeTrace (model, hulloverride, frame, NULL, start_l, end_l, mins, maxs, capsule, hitcontentsmask, trace);
}
VectorAdd (trace->endpos, origin, trace->endpos);
}
else
@ -1022,7 +995,7 @@ Handles selection or creation of a clipping hull, and offseting (and
eventually rotation) of the end points
==================
*/
static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel, unsigned int hitcontentsmask) //hullnum overrides min/max for q1 style bsps
static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel, qboolean capsule, unsigned int hitcontentsmask) //hullnum overrides min/max for q1 style bsps
{
trace_t trace;
model_t *model;
@ -1041,19 +1014,23 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
else
model = NULL;
if (!model)
if (!model || model->needload)
{
vec3_t boxmins, boxmaxs;
model = NULL;
VectorSubtract (ent->v->mins, maxs, boxmins);
VectorSubtract (ent->v->maxs, mins, boxmaxs);
World_HullForBox(boxmins, boxmaxs);
if (ent->xv->geomtype == GEOMTYPE_CAPSULE && !hitmodel)
model = World_CapsuleForBox(boxmins, boxmaxs);
else
World_HullForBox(boxmins, boxmaxs);
}
// trace a line through the apropriate clipping hull
if (ent->v->solid == SOLID_PORTAL)
{
//solid_portal cares only about origins and as such has no mins/max
TransformedTrace(model, 0, ent->v->frame, start, end, vec3_origin, vec3_origin, &trace, eorg, ent->v->angles, hitcontentsmask);
World_TransformedTrace(model, 0, ent->v->frame, start, end, vec3_origin, vec3_origin, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
if (trace.startsolid) //portals should not block traces. this prevents infinite looping
trace.startsolid = false;
hitmodel = false;
@ -1061,24 +1038,24 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
else if (ent->v->solid != SOLID_BSP)
{
ent->v->angles[0]*=-1; //carmack made bsp models rotate wrongly.
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, eorg, ent->v->angles, hitcontentsmask);
World_TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
ent->v->angles[0]*=-1;
}
else
{
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, eorg, ent->v->angles, hitcontentsmask);
World_TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
}
// if using hitmodel, we know it hit the bounding box, so try a proper trace now.
if (hitmodel && trace.fraction != 1 && ent->v->solid != SOLID_BSP && mdlidx != 0)
if (hitmodel && trace.fraction != 1 && !model)
{
//okay, we hit the bbox
model = w->Get_CModel(w, mdlidx);
if (model && model->funcs.NativeTrace)
if (model && model->funcs.NativeTrace && !model->needload)
{
//do the second trace
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, eorg, ent->v->angles, hitcontentsmask);
//do the second trace, using the actual mesh.
World_TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
}
}
@ -1092,16 +1069,13 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
static trace_t WorldQ2_ClipMoveToEntity (world_t *w, q2edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, unsigned int hitcontentsmask)
{
trace_t trace;
model_t *model;
model_t *model = NULL;
// get the clipping hull
if (ent->s.solid == Q2SOLID_BSP)
{
model = w->Get_CModel(w, ent->s.modelindex);
if (!model || model->type != mod_brush)
SV_Error("SOLID_BSP with non bsp model");
}
else
if (!model || model->type != mod_brush || model->needload)
{
vec3_t boxmins, boxmaxs;
VectorSubtract (ent->mins, maxs, boxmins);
@ -1111,7 +1085,7 @@ static trace_t WorldQ2_ClipMoveToEntity (world_t *w, q2edict_t *ent, vec3_t star
}
// trace a line through the apropriate clipping hull
TransformedTrace(model, 0, 0, start, end, mins, maxs, &trace, ent->s.origin, ent->s.angles, hitcontentsmask);
World_TransformedTrace(model, 0, 0, start, end, mins, maxs, false, &trace, ent->s.origin, ent->s.angles, hitcontentsmask);
// did we clip the move?
if (trace.fraction < 1 || trace.startsolid )
@ -1541,9 +1515,9 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip)
}
if ((int)touch->v->flags & FL_MONSTER)
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->hitcontentsmask);
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
else
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->hitcontentsmask);
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
if (trace.allsolid || trace.startsolid ||
trace.fraction < clip->trace.fraction)
{
@ -1648,9 +1622,9 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip)
}
if ((int)touch->v->flags & FL_MONSTER)
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->hitcontentsmask);
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
else
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->hitcontentsmask);
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
if (trace.fraction < clip->trace.fraction)
{
@ -1841,16 +1815,17 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
clip.hitcontentsmask = MASK_BOXSOLID; /*impacts playerclip*/
else
clip.hitcontentsmask = MASK_POINTSOLID; /*ignores playerclip but hits everything else*/
clip.capsule = (passedict->xv->geomtype == GEOMTYPE_CAPSULE);
if (type & MOVE_ONLYENT)
{
if (!passedict)
passedict = w->edicts;
return World_ClipMoveToEntity (w, passedict, passedict->v->origin, start, mins, maxs, end, hullnum, clip.type & MOVE_HITMODEL, clip.hitcontentsmask);
return World_ClipMoveToEntity (w, passedict, passedict->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
}
// clip to world
clip.trace = World_ClipMoveToEntity (w, w->edicts, w->edicts->v->origin, start, mins, maxs, end, hullnum, false, clip.hitcontentsmask);
clip.trace = World_ClipMoveToEntity (w, w->edicts, w->edicts->v->origin, start, mins, maxs, end, hullnum, false, clip.capsule, clip.hitcontentsmask);
clip.start = start;
clip.end = end;
@ -1973,7 +1948,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
continue; // don't clip against owner
}
trace = World_ClipMoveToEntity (w, touch, lp, clip.start, clip.mins, clip.maxs, clip.end, clip.hullnum, clip.type & MOVE_HITMODEL, clip.hitcontentsmask);
trace = World_ClipMoveToEntity (w, touch, lp, clip.start, clip.mins, clip.maxs, clip.end, clip.hullnum, clip.type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction)
{
@ -2011,7 +1986,7 @@ trace_t WorldQ2_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t
memset ( &clip, 0, sizeof ( moveclip_t ) );
// clip to world
w->worldmodel->funcs.NativeTrace(w->worldmodel, 0, 0, NULL, start, end, mins, maxs, hitcontentsmask, &clip.trace);
w->worldmodel->funcs.NativeTrace(w->worldmodel, 0, 0, NULL, start, end, mins, maxs, false, hitcontentsmask, &clip.trace);
clip.trace.ent = ge->edicts;
if (clip.trace.fraction == 0)