diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 1f599b50e..9fa3e02a2 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -2108,10 +2108,9 @@ guess_pm_type: state->pm_type = PM_DEAD; else state->pm_type = PM_NORMAL; - - TP_ParsePlayerInfo(oldstate, state, info); } + TP_ParsePlayerInfo(oldstate, state, info); } void CL_ParseClientPersist(void) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 2d6d82f71..7dd655dad 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -814,7 +814,7 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) memset(&tr, 0, sizeof(tr)); tr.fraction = 1; - cl.worldmodel->hulls->funcs.RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &tr); + cl.worldmodel->funcs.Trace(cl.worldmodel, 0, 0, start, end, vec3_origin, vec3_origin, &tr); start[2]-=16; if (tr.fraction == 1) { diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index b9888a8cb..099ba7ebf 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -200,7 +200,7 @@ void CL_InitTEnts (void) int i; for (i = 0; i < sizeof(tentsfx)/sizeof(tentsfx[0]); i++) { - if (COM_FCheckExists(tentsfx[i].efname)) + if (COM_FCheckExists(va("sound/%s", tentsfx[i].efname))) *tentsfx[i].sfx = S_PrecacheSound (tentsfx[i].efname); else *tentsfx[i].sfx = NULL; diff --git a/engine/client/keys.c b/engine/client/keys.c index 9100f7178..92474db57 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -643,12 +643,11 @@ void Key_Message (int key) if (key == K_ENTER) { - if (chat_team) - Cbuf_AddText ("say_team ", RESTRICT_LOCAL); - else - Cbuf_AddText ("say ", RESTRICT_LOCAL); - Cbuf_AddText(chat_buffer, RESTRICT_LOCAL); - Cbuf_AddText("\n", RESTRICT_LOCAL); + if (chat_buffer[0]) + { //send it straight into the command. + Cmd_TokenizeString(va("%s %s", chat_team?"say_team":"say", chat_buffer), true, false); + CL_Say(chat_team, ""); + } key_dest = key_game; chat_bufferlen = 0; diff --git a/engine/client/merged.h b/engine/client/merged.h index 2f5475d7f..78af6239d 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -7,7 +7,7 @@ struct texture_s; #if defined(SERVERONLY) #define qrenderer QR_NONE -#define FNC(n) (n) +#define FNC(n) (n) //FNC is defined as 'pointer if client build, direct if dedicated server' #else #define FNC(n) (*n) extern r_qrenderer_t qrenderer; @@ -102,8 +102,8 @@ extern qbyte *FNC(Mod_Q1LeafPVS) (struct mleaf_s *leaf, struct model_s *mode extern void FNC(Mod_NowLoadExternal) (void); extern void FNC(Mod_Think) (void); -extern qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms); -extern int (*Mod_TagNumForName) (struct model_s *model, char *name); +extern qboolean FNC(Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms); +extern int FNC(Mod_TagNumForName) (struct model_s *model, char *name); #undef FNC diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index f79065392..fcddd5367 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -354,7 +354,7 @@ trace_t CL_Move(vec3_t v1, vec3_t mins, vec3_t maxs, vec3_t v2, float nomonsters memset(&trace, 0, sizeof(trace)); trace.fraction = 1; - cl.worldmodel->hulls->funcs.RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, v1, v2, &trace); + cl.worldmodel->funcs.Trace(cl.worldmodel, 0, 0, v1, v2, vec3_origin, vec3_origin, &trace); //why use trace.endpos instead? //so that if we hit a wall early, we don't have a box covering the whole world because of a shotgun trace. diff --git a/engine/client/r_part.c b/engine/client/r_part.c index dbe2dd4a5..119fa954e 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -2779,7 +2779,7 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) memset (&trace, 0, sizeof(trace)); VectorSubtract(start, pe->origin, ts); VectorSubtract(end, pe->origin, te); - if (!hull->funcs.RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, ts, te, &trace)) + if (!pe->model->funcs.Trace(pe->model, 0, 0, ts, te, vec3_origin, vec3_origin, &trace)) { VectorSubtract(trace.endpos, ts, delta); len = Length(delta); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 5f40d6b45..5941bfa0e 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -2894,8 +2894,16 @@ void TP_StatChanged (int stat, int value) if (i & (IT_KEY1|IT_KEY2)) { if (cl.teamfortress && !cl.spectator) + { ExecTookTrigger (tp_name_flag.string, it_flag, - cl.frames[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[SP]].origin); + cl.frames[cl.validsequence&UPDATE_MASK].playerstate[cl.playernum[SP]].origin); + } + } + + if (!cl.spectator && cl.teamfortress && ~value & vars.items & (IT_KEY1|IT_KEY2)) + { + vars.lastdrop_time = realtime; + strcpy (vars.lastdroploc, Macro_Location()); } vars.olditems = vars.items; @@ -3133,7 +3141,7 @@ qboolean TP_SuppressMessage(char *buf) { return false; } -static void CL_Say (qboolean team, char *extra) +void CL_Say (qboolean team, char *extra) { extern cvar_t cl_fakename; char text[2048], sendtext[2048], *s; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 90d4a103c..41310e3e4 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -43,6 +43,7 @@ void SWMod_LoadLighting (lump_t *l); void Q2BSP_SetHullFuncs(hull_t *hull); +qboolean CM_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace); qbyte areabits[MAX_Q2MAP_AREAS/8]; @@ -3594,6 +3595,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode; loadmodel->funcs.MarkLights = Q2BSP_MarkLights; #endif + loadmodel->funcs.Trace = CM_Trace; #ifndef SERVERONLY //light grid info @@ -3670,6 +3672,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned loadmodel->funcs.MarkLights = NULL; loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.LeafForPoint = CM_ModelPointLeafnum; + loadmodel->funcs.Trace = CM_Trace; break; #if defined(RGLQUAKE) @@ -3707,6 +3710,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned loadmodel->funcs.MarkLights = Q2BSP_MarkLights; loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.LeafForPoint = CM_ModelPointLeafnum; + loadmodel->funcs.Trace = CM_Trace; break; #endif #if defined(SWQUAKE) @@ -3745,6 +3749,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned loadmodel->funcs.MarkLights = Q2BSP_MarkLights; loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.LeafForPoint = CM_ModelPointLeafnum; + loadmodel->funcs.Trace = CM_Trace; break; #endif default: @@ -3770,8 +3775,6 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned - - loadmodel->numsubmodels = CM_NumInlineModels(); { model_t *mod = loadmodel; @@ -4984,6 +4987,11 @@ trace_t CM_BoxTrace (vec3_t start, vec3_t end, return trace_trace; } +qboolean CM_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +{ + *trace = CM_BoxTrace(start, end, mins, maxs, model->hulls[0].firstclipnode, MASK_PLAYERSOLID); + return trace->fraction != 1; +} /* ================== @@ -5498,7 +5506,6 @@ int Q2BSP_HullPointContents(hull_t *hull, vec3_t p) } void Q2BSP_SetHullFuncs(hull_t *hull) { - hull->funcs.RecursiveHullCheck = Q2BSP_RecursiveHullCheck; hull->funcs.HullPointContents = Q2BSP_HullPointContents; } diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index d28c912f8..4e2b9fbb1 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -148,7 +148,7 @@ LINE TESTING IN HULLS vec3_t trace_extents; -qboolean PM_TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_t *trace, vec3_t origin, vec3_t angles) +qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, trace_t *trace, vec3_t origin, vec3_t angles) { vec3_t start_l, end_l; vec3_t a; @@ -161,14 +161,8 @@ qboolean PM_TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_ VectorSubtract (start, origin, start_l); VectorSubtract (end, origin, end_l); - if (!player_mins[2]) //hmm.. hull bigger than player? Or is this hexen2? - { - start_l[2] -= hull->clip_mins[2]+0.1; - end_l[2] -= hull->clip_mins[2]+0.1; - } - // rotate start and end into the models frame of reference - if (hull != &box_hull && + if (model && (angles[0] || angles[1] || angles[2]) ) rotated = true; else @@ -189,7 +183,11 @@ qboolean PM_TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_ end_l[2] = DotProduct (temp, up); } // sweep the box through the model - result = hull->funcs.RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + + if (model) + result = model->funcs.Trace(model, 0, 0, start_l, end_l, player_mins, player_maxs, trace); + else + result = Q1BSP_RecursiveHullCheck (&box_hull, box_hull.firstclipnode, 0, 1, start_l, end_l, trace); if (rotated && trace->fraction != 1.0) { @@ -209,8 +207,6 @@ qboolean PM_TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_ trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]); trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]); trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]); -// if (!player_mins[2]) //hmm.. hull bigger than player? Or is this hexen2? -// trace->endpos[2] += hull->clip_mins[2]+0.1; return result; } @@ -287,41 +283,9 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end) { pe = &pmove.physents[i]; // get the clipping hull - if (pe->model) - { - hull = &pmove.physents[i].model->hulls[pmove.hullnum]; - if (!hull->available || !hull->clipnodes || !hull->planes) - hull = &pmove.physents[i].model->hulls[1]; //fallback - } - else - { - VectorSubtract (pe->mins, player_maxs, mins); - VectorSubtract (pe->maxs, player_mins, maxs); - hull = PM_HullForBox (mins, maxs); - } - - // fill in a default trace - memset (&trace, 0, sizeof(trace_t)); - trace.fraction = 1; - trace.allsolid = true; -// trace.startsolid = true; - VectorCopy (end, trace.endpos); // trace a line through the apropriate clipping hull -#ifdef Q2BSPS - if (pmove.physents[i].model && (pmove.physents[i].model->fromgame == fg_quake2 || pmove.physents[i].model->fromgame == fg_quake3)) - { - trace_t tr; - tr = CM_TransformedBoxTrace (start, end, player_mins, player_maxs, pmove.physents[i].model->hulls[0].firstclipnode, MASK_PLAYERSOLID, pe->origin, pe->angles); - trace.startsolid = tr.startsolid; - trace.allsolid = tr.allsolid; - trace.fraction = tr.fraction; - memcpy(&trace.plane, &tr.plane, sizeof(tr.plane)); - VectorCopy(tr.endpos, trace.endpos); - } - else -#endif - PM_TransformedHullCheck (hull, start, end, &trace, pe->origin, pe->angles); + PM_TransformedHullCheck (pe->model, start, end, &trace, pe->origin, pe->angles); if (trace.allsolid) trace.startsolid = true; diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index d5bfc1f19..b28e014d9 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -204,10 +204,70 @@ int Q1BSP_HullPointContents(hull_t *hull, vec3_t p) void Q1BSP_SetHullFuncs(hull_t *hull) { - hull->funcs.RecursiveHullCheck = Q1BSP_RecursiveHullCheck; hull->funcs.HullPointContents = Q1BSP_HullPointContents; } +qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +{ + hull_t *hull; + vec3_t size; + vec3_t start_l, end_l; + vec3_t offset; + + memset (trace, 0, sizeof(trace_t)); + trace->fraction = 1; + trace->allsolid = true; + + VectorSubtract (maxs, mins, size); + if (forcehullnum >= 1 && forcehullnum <= MAX_MAP_HULLSM && model->hulls[forcehullnum-1].available) + hull = &model->hulls[forcehullnum-1]; + else + { + if (model->hulls[5].available) + { //choose based on hexen2 sizes. + + if (size[0] < 3) // Point + hull = &model->hulls[0]; + else if (size[0] <= 32 && size[2] <= 28) // Half Player + hull = &model->hulls[3]; + else if (size[0] <= 32) // Full Player + hull = &model->hulls[1]; + else // Golumn + hull = &model->hulls[5]; + } + else + { + if (size[0] < 3 || !model->hulls[1].available) + hull = &model->hulls[0]; + else if (size[0] <= 32) + { + if (size[2] < 54 && model->hulls[3].available) + hull = &model->hulls[3]; // 32x32x36 (half-life's crouch) + else + hull = &model->hulls[1]; + } + else + hull = &model->hulls[2]; + } + } + +// calculate an offset value to center the origin + VectorSubtract (hull->clip_mins, mins, offset); + VectorSubtract(start, offset, start_l); + VectorSubtract(end, offset, end_l); + Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + if (trace->fraction == 1) + { + VectorCopy (end, trace->endpos); + } + else + { + VectorAdd (trace->endpos, offset, trace->endpos); + } + + return trace->fraction != 1; +} + /* Physics functions (common) diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index b33ef23c1..714372324 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1,5 +1,5 @@ #include "quakedef.h" -#ifdef RGLQUAKE +#if defined(RGLQUAKE) || defined(SERVERONLY) #include "glquake.h" #include "shader.h" #include "hash.h" @@ -10,6 +10,8 @@ #define MAX_BONES 256 +static model_t *loadmodel; + //FIXME typedef struct { @@ -75,14 +77,18 @@ typedef struct { int ofs_trineighbours; int numskins; +#ifndef SERVERONLY int ofsskins; +#endif qboolean sharesverts; //used with models with two shaders using the same vertex. int numverts; +#ifndef SERVERONLY int ofs_st_array; +#endif int groups; int groupofs; @@ -113,7 +119,9 @@ typedef struct { typedef struct { int ofsverts; +#ifndef SERVERONLY int ofsnormals; +#endif vec3_t scale; vec3_t scale_origin; @@ -135,6 +143,7 @@ typedef struct { //we can't be bothered with animating skins. //We'll load up to four of them but after that you're on your own +#ifndef SERVERONLY typedef struct { int skinwidth; int skinheight; @@ -159,7 +168,141 @@ typedef struct { int skinnum; bucket_t bucket; } galiascolourmapped_t; +#endif + +static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, float bonepose[MAX_BONES][12]); +static void R_TransformVerticies(float bonepose[MAX_BONES][12], galisskeletaltransforms_t *weights, int numweights, float *xyzout); + +void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) +{ +#ifndef SERVERONLY + //we've got to have this bit + if (!strcmp(loadmodel->name, "progs/player.mdl") || + !strcmp(loadmodel->name, "progs/eyes.mdl")) + { + unsigned short crc; + qbyte *p; + int len; + char st[40]; + + CRC_Init(&crc); + for (len = buffersize, p = buffer; len; len--, p++) + CRC_ProcessByte(&crc, *p); + + sprintf(st, "%d", (int) crc); + Info_SetValueForKey (cls.userinfo, + !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, + st, MAX_INFO_STRING); + + if (cls.state >= ca_connected) + { + CL_SendClientCommand(true, "setinfo %s %d", + !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, + (int)crc); + } + } +#endif +} +#include +qboolean GLMod_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +{ + galiasinfo_t *mod = Mod_Extradata(model); + galiasgroup_t *group; + galiaspose_t *pose; + int i; + + float *p1, *p2, *p3; + vec3_t edge1, edge2, edge3; + vec3_t normal; + vec3_t edgenormal; + + float planedist; + float diststart, distend; + + float frac; + float temp; + + vec3_t impactpoint; + + float *posedata; + int *indexes; + + while(mod) + { + indexes = (int*)((char*)mod + mod->ofs_indexes); + group = (galiasgroup_t*)((char*)mod + mod->groupofs); + pose = (galiaspose_t*)((char*)&group[0] + group[0].poseofs); + posedata = (float*)((char*)pose + pose->ofsverts); + if (group->isskeletal && !mod->sharesverts) + { + float bonepose[MAX_BONES][12]; + posedata = alloca(mod->numverts*sizeof(vec3_t)); + frac = 1; + R_LerpBones(&frac, (float**)posedata, 1, (galiasbone_t*)((char*)mod + mod->ofsbones), mod->numbones, bonepose); + R_TransformVerticies(bonepose, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata); + } + + for (i = 0; i < mod->numindexes; i+=3) + { + p1 = posedata + 3*indexes[i+0]; + p2 = posedata + 3*indexes[i+1]; + p3 = posedata + 3*indexes[i+2]; + + VectorSubtract(p1, p2, edge1); + VectorSubtract(p3, p2, edge2); + CrossProduct(edge1, edge2, normal); + + planedist = DotProduct(p1, normal); + diststart = DotProduct(start, normal); + if (diststart <= planedist) + continue; //start on back side. + distend = DotProduct(end, normal); + if (distend >= planedist) + continue; //end on front side (as must start - doesn't cross). + + frac = (diststart - planedist) / (diststart-distend); + + if (frac >= trace->fraction) //already found one closer. + continue; + + impactpoint[0] = start[0] + frac*(end[0] - start[0]); + impactpoint[1] = start[1] + frac*(end[1] - start[1]); + impactpoint[2] = start[2] + frac*(end[2] - start[2]); + + temp = DotProduct(impactpoint, normal)-planedist; + + CrossProduct(edge1, normal, edgenormal); + temp = DotProduct(impactpoint, edgenormal)-DotProduct(p2, edgenormal); + if (DotProduct(impactpoint, edgenormal) > DotProduct(p2, edgenormal)) + continue; + + CrossProduct(normal, edge2, edgenormal); + if (DotProduct(impactpoint, edgenormal) > DotProduct(p3, edgenormal)) + continue; + + VectorSubtract(p1, p3, edge3); + CrossProduct(normal, edge3, edgenormal); + if (DotProduct(impactpoint, edgenormal) > DotProduct(p1, edgenormal)) + continue; + + trace->fraction = frac; + VectorCopy(impactpoint, trace->endpos); + VectorCopy(normal, trace->plane.normal); + } + + if (mod->nextsurf) + mod = (galiasinfo_t*)((char*)mod + mod->nextsurf); + else + mod = NULL; + } + + trace->allsolid = false; + + return trace->fraction != 1; +} + +#ifndef SERVERONLY static hashtable_t skincolourmapped; static vec3_t shadevector; @@ -288,17 +431,12 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float } } } - +#endif #ifdef SKELETALMODELS -static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, galisskeletaltransforms_t *weights, int numweights) +static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, float bonepose[MAX_BONES][12]) { - float bonepose[MAX_BONES][12]; - float *outhead; - galisskeletaltransforms_t *v; - int i, k, b; - float *out, *matrix, m[12]; - + float *matrix, m[12]; // vertex weighted skeletal // interpolate matrices and concatenate them to their parents @@ -319,10 +457,35 @@ static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int po for (k = 0;k < 12;k++) //parentless bonepose[i][k] = m[k]; } +} +static void R_TransformVerticies(float bonepose[MAX_BONES][12], galisskeletaltransforms_t *weights, int numweights, float *xyzout) +{ + int i; + float *out, *matrix; + + galisskeletaltransforms_t *v = weights; + for (i = 0;i < numweights;i++, v++) + { + out = xyzout + v->vertexindex * 3; + matrix = bonepose[v->boneindex]; + // FIXME: this can very easily be optimized with SSE or 3DNow + out[0] += v->org[0] * matrix[0] + v->org[1] * matrix[1] + v->org[2] * matrix[ 2] + v->org[3] * matrix[ 3]; + out[1] += v->org[0] * matrix[4] + v->org[1] * matrix[5] + v->org[2] * matrix[ 6] + v->org[3] * matrix[ 7]; + out[2] += v->org[0] * matrix[8] + v->org[1] * matrix[9] + v->org[2] * matrix[10] + v->org[3] * matrix[11]; + } +} +#ifndef SERVERONLY +static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, galisskeletaltransforms_t *weights, int numweights) +{ + float bonepose[MAX_BONES][12]; + + int i, k; + float *matrix, m[12]; + + R_LerpBones(plerp, pose, poses, bones, bonecount, bonepose); - outhead = (float*)mesh->xyz_array; // blend the vertex bone weights - memset(outhead, 0, mesh->numvertexes * sizeof(mesh->xyz_array[0])); +// memset(outhead, 0, mesh->numvertexes * sizeof(mesh->xyz_array[0])); for (i = 0; i < mesh->numvertexes; i++) { @@ -342,19 +505,12 @@ static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int po */ } - v = weights; - for (i = 0;i < numweights;i++, v++) - { - out = outhead + v->vertexindex * 3; - matrix = bonepose[v->boneindex]; - // FIXME: this can very easily be optimized with SSE or 3DNow - out[0] += v->org[0] * matrix[0] + v->org[1] * matrix[1] + v->org[2] * matrix[ 2] + v->org[3] * matrix[ 3]; - out[1] += v->org[0] * matrix[4] + v->org[1] * matrix[5] + v->org[2] * matrix[ 6] + v->org[3] * matrix[ 7]; - out[2] += v->org[0] * matrix[8] + v->org[1] * matrix[9] + v->org[2] * matrix[10] + v->org[3] * matrix[11]; - } + R_TransformVerticies(bonepose, weights, numweights, (float*)mesh->xyz_array); } #endif +#endif +#ifndef SERVERONLY static void R_GAliasAddDlights(mesh_t *mesh, vec3_t org, vec3_t angles) { int l, v; @@ -486,14 +642,14 @@ static qboolean R_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int frame1, i if (inf->sharesverts) return false; //don't generate the new vertex positions. We still have them all. - +#ifndef SERVERONLY mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); mesh->lmst_array = NULL; mesh->colors_array = tempColours; - mesh->xyz_array = tempVertexCoords; mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); - mesh->normals_array = tempNormals; +#endif + mesh->xyz_array = tempVertexCoords; g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); @@ -2061,8 +2217,6 @@ void GL_ParseQ3SkinFile(char *out, char *surfname, char *modelname, int skinnum) } } -static model_t *loadmodel; - void GL_LoadSkinFile(galiastexnum_t *texnum, char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette) { char shadername[MAX_QPATH]; @@ -2073,6 +2227,8 @@ void GL_LoadSkinFile(galiastexnum_t *texnum, char *surfacename, int skinnumber, texnum->base = Mod_LoadHiResTexture(shadername, "models", true, true, true); } +#endif //SERVERONLY + //Q1 model loading #if 1 @@ -2108,16 +2264,18 @@ static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) verts = (vec3_t *)(pose+1); normals = &verts[galias->numverts]; pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY pose->ofsnormals = (char *)normals - (char *)pose; +#endif for (j = 0; j < pq1inmodel->numverts; j++) { verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; - +#ifndef SERVERONLY VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); - +#endif if (seamremaps[j] != j) { VectorCopy(verts[j], verts[seamremaps[j]]); @@ -2149,7 +2307,9 @@ static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) for (k = 0; k < frame->numposes; k++) { pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY pose->ofsnormals = (char *)normals - (char *)pose; +#endif pinframe = (dtrivertx_t *)((char *)pinframe + sizeof(daliasframe_t)); for (j = 0; j < pq1inmodel->numverts; j++) @@ -2157,8 +2317,9 @@ static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; - +#ifndef SERVERONLY VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); +#endif if (seamremaps[j] != j) { VectorCopy(verts[j], verts[seamremaps[j]]); @@ -2184,6 +2345,37 @@ static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) return pframetype; } +#ifdef SERVERONLY //greatly reduced version of Q1_LoadSkins (too many #ifdefs +static void *Q1_LoadSkins (daliasskintype_t *pskintype, qboolean alpha) +{ + int i; + int s; + int *count; + float *intervals; + qbyte *data; + + s = pq1inmodel->skinwidth*pq1inmodel->skinheight; + for (i = 0; i < pq1inmodel->numskins; i++) + { + switch(LittleLong(pskintype->type)) + { + case ALIAS_SKIN_SINGLE: + pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s); + break; + + default: + count = (int *)(pskintype+1); + intervals = (float *)(count+1); + data = (qbyte *)(intervals + LittleLong(*count)); + data += s*LittleLong(*count); + pskintype = (daliasskintype_t *)data; + break; + } + } + galias->numskins=pq1inmodel->numskins; + return pskintype; +} +#else static void *Q1_LoadSkins (daliasskintype_t *pskintype, qboolean alpha) { extern int gl_bumpmappingpossible; @@ -2343,13 +2535,17 @@ static void *Q1_LoadSkins (daliasskintype_t *pskintype, qboolean alpha) galias->numskins=pq1inmodel->numskins; return pskintype; } +#endif void GL_LoadQ1Model (model_t *mod, void *buffer) { +#ifndef SERVERONLY vec2_t *st_array; + int j; +#endif int hunkstart, hunkend, hunktotal; int version; - int i, j, onseams; + int i, onseams; dstvert_t *pinstverts; dtriangle_t *pintriangles; int *seamremap; @@ -2359,31 +2555,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) loadmodel=mod; - //we've got to have this bit - if (!strcmp(loadmodel->name, "progs/player.mdl") || - !strcmp(loadmodel->name, "progs/eyes.mdl")) - { - unsigned short crc; - qbyte *p; - int len; - char st[40]; - - CRC_Init(&crc); - for (len = com_filesize, p = buffer; len; len--, p++) - CRC_ProcessByte(&crc, *p); - - sprintf(st, "%d", (int) crc); - Info_SetValueForKey (cls.userinfo, - !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, - st, MAX_INFO_STRING); - - if (cls.state >= ca_connected) - { - CL_SendClientCommand(true, "setinfo %s %d", - !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, - (int)crc); - } - } + Mod_DoCRC(loadmodel, buffer, com_filesize); hunkstart = Hunk_LowMark (); @@ -2409,12 +2581,16 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) mod->flags = pq1inmodel->flags; size = sizeof(galiasinfo_t) - + pq1inmodel->numframes*sizeof(galiasgroup_t) - + pq1inmodel->numskins*sizeof(galiasskin_t); +#ifndef SERVERONLY + + pq1inmodel->numskins*sizeof(galiasskin_t) +#endif + + pq1inmodel->numframes*sizeof(galiasgroup_t); galias = Hunk_Alloc(size); galias->groupofs = sizeof(*galias); +#ifndef SERVERONLY galias->ofsskins = sizeof(*galias)+pq1inmodel->numframes*sizeof(galiasgroup_t); +#endif galias->nextsurf = 0; //skins @@ -2438,7 +2614,9 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) seamremap = BZ_Malloc(sizeof(int)*pq1inmodel->numverts); galias->numverts = pq1inmodel->numverts+onseams; + //st +#ifndef SERVERONLY st_array = Hunk_Alloc(sizeof(*st_array)*(pq1inmodel->numverts+onseams)); galias->ofs_st_array = (char *)st_array - (char *)galias; for (j=pq1inmodel->numverts,i = 0; i < pq1inmodel->numverts; i++) @@ -2456,6 +2634,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) else seamremap[i] = i; } +#endif //trianglelists; pintriangles = (dtriangle_t *)&pinstverts[pq1inmodel->numverts]; @@ -2482,7 +2661,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) //frames Q1_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap); BZ_Free(seamremap); - +#ifndef SERVERONLY if (r_shadows.value) { int *neighbours; @@ -2490,7 +2669,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) galias->ofs_trineighbours = (qbyte *)neighbours - (qbyte *)galias; R_BuildTriangleNeighbours(neighbours, indexes, pq1inmodel->numtris); } - +#endif VectorCopy (pq1inmodel->scale_origin, mod->mins); VectorMA (mod->mins, 255, pq1inmodel->scale, mod->maxs); // @@ -2511,6 +2690,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) Hunk_FreeToLowMark (hunkstart); + mod->funcs.Trace = GLMod_Trace; } #endif @@ -2554,10 +2734,10 @@ extern vec3_t bytedirs[Q2NUMVERTEXNORMALS]; static void Q2_LoadSkins(char *skins) { +#ifndef SERVERONLY int i; galiastexnum_t *texnums; galiasskin_t *outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); - galias->numskins = pq2inmodel->num_skins; for (i = 0; i < pq2inmodel->num_skins; i++, outskin++) { @@ -2573,15 +2753,22 @@ static void Q2_LoadSkins(char *skins) skins += MD2MAX_SKINNAME; } +#endif + galias->numskins = pq2inmodel->num_skins; } #define MD2_MAX_TRIANGLES 4096 void GL_LoadQ2Model (model_t *mod, void *buffer) { +#ifndef SERVERONLY + dmd2stvert_t *pinstverts; + vec2_t *st_array; + vec3_t *normals; +#endif + int hunkstart, hunkend, hunktotal; int version; int i, j; - dmd2stvert_t *pinstverts; dmd2triangle_t *pintri; index_t *indexes; int numindexes; @@ -2594,8 +2781,6 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) dmd2aliasframe_t *pinframe; int framesize; vec3_t *verts; - vec3_t *normals; - vec2_t *st_array; int indremap[MD2_MAX_TRIANGLES*3]; unsigned short ptempindex[MD2_MAX_TRIANGLES*3], ptempstindex[MD2_MAX_TRIANGLES*3]; @@ -2607,6 +2792,8 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) loadmodel=mod; + Mod_DoCRC(mod, buffer, com_filesize); + hunkstart = Hunk_LowMark (); pq2inmodel = (md2_t *)buffer; @@ -2632,12 +2819,16 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) loadmodel->numframes = pq2inmodel->num_frames; size = sizeof(galiasinfo_t) - + pq2inmodel->num_frames*sizeof(galiasgroup_t) - + pq2inmodel->num_skins*sizeof(galiasskin_t); +#ifndef SERVERONLY + + pq2inmodel->num_skins*sizeof(galiasskin_t) +#endif + + pq2inmodel->num_frames*sizeof(galiasgroup_t); galias = Hunk_Alloc(size); galias->groupofs = sizeof(*galias); +#ifndef SERVERONLY galias->ofsskins = sizeof(*galias)+pq2inmodel->num_frames*sizeof(galiasgroup_t); +#endif galias->nextsurf = 0; //skins @@ -2704,6 +2895,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) } // s and t vertices +#ifndef SERVERONLY pinstverts = ( dmd2stvert_t * ) ( ( qbyte * )pq2inmodel + LittleLong (pq2inmodel->ofs_st) ); st_array = Hunk_Alloc(sizeof(*st_array)*(numverts)); galias->ofs_st_array = (char *)st_array - (char *)galias; @@ -2713,6 +2905,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) st_array[indexes[j]][0] = (float)(((double)LittleShort (pinstverts[ptempstindex[indremap[j]]].s) + 0.5f) /pq2inmodel->skinwidth); st_array[indexes[j]][1] = (float)(((double)LittleShort (pinstverts[ptempstindex[indremap[j]]].t) + 0.5f) /pq2inmodel->skinheight); } +#endif //frames ClearBounds ( mod->mins, mod->maxs ); @@ -2721,15 +2914,21 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) framesize = LittleLong (pq2inmodel->framesize); for (i=0 ; inum_frames ; i++) { - pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*2*numverts); + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*numverts +#ifndef SERVERONLY + + sizeof(vec3_t)*numverts +#endif + ); poutframe->poseofs = (char *)pose - (char *)poutframe; poutframe->numposes = 1; galias->groups++; verts = (vec3_t *)(pose+1); - normals = &verts[galias->numverts]; pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + normals = &verts[galias->numverts]; pose->ofsnormals = (char *)normals - (char *)pose; +#endif pinframe = ( dmd2aliasframe_t * )( ( qbyte * )pq2inmodel + LittleLong (pq2inmodel->ofs_frames) + i * framesize ); @@ -2746,7 +2945,9 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) verts[indexes[j]][0] = pose->scale_origin[0]+pose->scale[0]*pinframe->verts[ptempindex[indremap[j]]].v[0]; verts[indexes[j]][1] = pose->scale_origin[1]+pose->scale[1]*pinframe->verts[ptempindex[indremap[j]]].v[1]; verts[indexes[j]][2] = pose->scale_origin[2]+pose->scale[2]*pinframe->verts[ptempindex[indremap[j]]].v[2]; +#ifndef SERVERONLY VectorCopy(bytedirs[pinframe->verts[ptempindex[indremap[j]]].lightnormalindex], normals[indexes[j]]); +#endif } // Mod_AliasCalculateVertexNormals ( numindexes, poutindex, numverts, poutvertex, qfalse ); @@ -2767,7 +2968,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) - +#ifndef SERVERONLY if (r_shadows.value) { int *neighbours; @@ -2775,7 +2976,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) galias->ofs_trineighbours = (qbyte *)neighbours - (qbyte *)galias; R_BuildTriangleNeighbours(neighbours, indexes, pq2inmodel->num_tris); } - +#endif /* VectorCopy (pq2inmodel->scale_origin, mod->mins); VectorMA (mod->mins, 255, pq2inmodel->scale, mod->maxs); @@ -2798,6 +2999,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) Hunk_FreeToLowMark (hunkstart); + mod->funcs.Trace = GLMod_Trace; } #endif @@ -2825,8 +3027,11 @@ typedef struct { - +#ifndef SERVERONLY qboolean GLMod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) +#else +qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) +#endif { galiasinfo_t *inf; @@ -2981,7 +3186,11 @@ qboolean GLMod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float return false; } +#ifndef SERVERONLY int GLMod_TagNumForName(model_t *model, char *name) +#else +int Mod_TagNumForName(model_t *model, char *name) +#endif { int i; galiasinfo_t *inf; @@ -3096,6 +3305,15 @@ typedef struct { void GL_LoadQ3Model(model_t *mod, void *buffer) { +#ifndef SERVERONLY + galiasskin_t *skin; + galiastexnum_t *texnum; + float lat, lng; + md3St_t *inst; + vec3_t *normals; + vec2_t *st_array; + md3Shader_t *inshader; +#endif int hunkstart, hunkend, hunktotal; // int version; int s, i, j, d; @@ -3109,19 +3327,10 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) galiasinfo_t *parent, *root; galiasgroup_t *group; - galiasskin_t *skin; - galiastexnum_t *texnum; - vec3_t *verts; - vec3_t *normals; - vec2_t *st_array; - float lat, lng; - - md3St_t *inst; md3Triangle_t *intris; md3XyzNormal_t *invert; - md3Shader_t *inshader; int size; @@ -3132,6 +3341,8 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) loadmodel=mod; + Mod_DoCRC(mod, buffer, com_filesize); + hunkstart = Hunk_LowMark (); header = buffer; @@ -3163,15 +3374,16 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) root = galias; parent = galias; +#ifndef SERVERONLY st_array = Hunk_Alloc(sizeof(vec2_t)*galias->numindexes); galias->ofs_st_array = (qbyte*)st_array - (qbyte*)galias; - inst = (md3St_t*)((qbyte*)surf + surf->ofsSt); for (i = 0; i < galias->numverts; i++) { st_array[i][0] = inst[i].s; st_array[i][1] = inst[i].t; } +#endif indexes = Hunk_Alloc(sizeof(*indexes)*galias->numindexes); galias->ofs_indexes = (qbyte*)indexes - (qbyte*)galias; @@ -3187,21 +3399,28 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) invert = (md3XyzNormal_t *)((qbyte*)surf + surf->ofsXyzNormals); for (i = 0; i < surf->numFrames; i++) { - pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*2*surf->numVerts); - normals = (vec3_t*)(pose+1); - verts = normals + surf->numVerts; + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*surf->numVerts +#ifndef SERVERONLY + + sizeof(vec3_t)*surf->numVerts +#endif + ); - pose->ofsnormals = (qbyte*)normals - (qbyte*)pose; + verts = (vec3_t*)(pose+1); pose->ofsverts = (qbyte*)verts - (qbyte*)pose; +#ifndef SERVERONLY + normals = verts + surf->numVerts; + pose->ofsnormals = (qbyte*)normals - (qbyte*)pose; +#endif for (j = 0; j < surf->numVerts; j++) { +#ifndef SERVERONLY lat = (float)invert[j].latlong[0] * (2 * M_PI)*(1.0 / 255.0); lng = (float)invert[j].latlong[1] * (2 * M_PI)*(1.0 / 255.0); normals[j][0] = cos ( lng ) * sin ( lat ); normals[j][1] = sin ( lng ) * sin ( lat ); normals[j][2] = cos ( lat ); - +#endif for (d = 0; d < 3; d++) { verts[j][d] = invert[j].xyz[d]/64.0f; @@ -3228,6 +3447,7 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) invert += surf->numVerts; } +#ifndef SERVERONLY if (surf->numShaders) { #ifndef Q3SHADERS @@ -3309,12 +3529,13 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) texnum++; } } +#endif VectorCopy(min, loadmodel->mins); VectorCopy(max, loadmodel->maxs); - +#ifndef SERVERONLY if (r_shadows.value) { int *neighbours; @@ -3322,6 +3543,7 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) galias->ofs_trineighbours = (qbyte *)neighbours - (qbyte *)galias; R_BuildTriangleNeighbours(neighbours, indexes, surf->numTriangles); } +#endif surf = (md3Surface_t *)((qbyte *)surf + surf->ofsEnd); } @@ -3356,6 +3578,8 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) memcpy (mod->cache.data, root, hunktotal); Hunk_FreeToLowMark (hunkstart); + + mod->funcs.Trace = GLMod_Trace; } #endif @@ -3421,7 +3645,14 @@ typedef struct zymvertex_s //but only one set of transforms are ever generated. void GLMod_LoadZymoticModel(model_t *mod, void *buffer) { - int i, j; +#ifndef SERVERONLY + galiasskin_t *skin; + galiastexnum_t *texnum; + int skinfiles; + int j; +#endif + + int i; int hunkstart, hunkend, hunktotal; zymtype1header_t *header; @@ -3430,9 +3661,6 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) galisskeletaltransforms_t *transforms; zymvertex_t *intrans; - galiasskin_t *skin; - galiastexnum_t *texnum; - galiasbone_t *bone; zymbone_t *inbone; int v; @@ -3452,11 +3680,11 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) char *surfname; - int skinfiles; - loadmodel=mod; + Mod_DoCRC(mod, buffer, com_filesize); + hunkstart = Hunk_LowMark (); header = buffer; @@ -3563,17 +3791,23 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) stcoords[i][1] = 1-BigFloat(inst[i][1]); //hmm. upside down skin coords? } +#ifndef SERVERONLY skinfiles = GL_BuildSkinFileList(loadmodel->name); if (skinfiles < 1) skinfiles = 1; +#endif for (i = 0; i < header->numsurfaces; i++, surfname+=32) { - root[i].ofs_st_array = (char*)stcoords - (char*)&root[i]; - root[i].groups = header->numscenes; root[i].groupofs = (char*)grp - (char*)&root[i]; +#ifdef SERVERONLY + root[i].numskins = 1; +#else + root[i].ofs_st_array = (char*)stcoords - (char*)&root[i]; + root[i].numskins = skinfiles; + skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(galiastexnum_t))*skinfiles); texnum = (galiastexnum_t*)(skin+skinfiles); for (j = 0; j < skinfiles; j++, texnum++) @@ -3583,8 +3817,9 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) GL_LoadSkinFile(texnum, surfname, j, NULL, 0, 0, NULL); } - root[i].numskins = j; + root[i].ofsskins = (char *)skin - (char *)&root[i]; +#endif } @@ -3634,6 +3869,9 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) memcpy (mod->cache.data, root, hunktotal); Hunk_FreeToLowMark (hunkstart); + + + mod->funcs.Trace = GLMod_Trace; } #endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 3eca31e8a..744ac513c 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -2528,6 +2528,7 @@ void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); void Q1BSP_FatPVS (vec3_t org, qboolean add); qboolean Q1BSP_EdictInFatPVS(struct edict_s *ent); void Q1BSP_FindTouchedLeafs(struct edict_s *ent); +qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace); void GLQ1BSP_LightPointValues(vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); @@ -2650,6 +2651,7 @@ void GLMod_LoadBrushModel (model_t *mod, void *buffer) mod->funcs.LightPointValues = GLQ1BSP_LightPointValues; mod->funcs.StainNode = Q1BSP_StainNode; mod->funcs.MarkLights = Q1BSP_MarkLights; + mod->funcs.Trace = Q1BSP_Trace; mod->funcs.LeafForPoint = GLMod_LeafForPoint; mod->funcs.LeafPVS = GLMod_LeafnumPVS; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 7c24ee4b0..b5aa2230e 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -29,11 +29,13 @@ struct trace_s; struct edict_s; typedef struct { - qboolean (*RecursiveHullCheck) (struct hull_s *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); +// qboolean (*RecursiveHullCheck) (struct hull_s *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); int (*HullPointContents) (struct hull_s *hull, vec3_t p); //return FTE contents } hullfuncs_t; typedef struct { + qboolean (*Trace) (struct model_s *model, int hulloverride, int frame, vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, struct trace_s *trace); + void (*FatPVS) (vec3_t org, qboolean add); qboolean (*EdictInFatPVS) (struct edict_s *edict); void (*FindTouchedLeafs_Q1) (struct edict_s *ent); //edict system as opposed to q2 game dll system. diff --git a/engine/gl/ltface.c b/engine/gl/ltface.c index f20bf11ac..64f073465 100644 --- a/engine/gl/ltface.c +++ b/engine/gl/ltface.c @@ -66,9 +66,9 @@ vec_t CastRay (vec3_t p1, vec3_t p2) hull = &lightmodel->hulls[0]; memset (&trace, 0, sizeof(trace)); - if (!hull->funcs.RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, p1, p2, &trace)) - return -1; - + if (!lightmodel->funcs.Trace (lightmodel, 0, 0, p1, p2, vec3_origin, vec3_origin, &trace)) + return -1; + VectorSubtract(p1, p2, move); return VectorLength(move); } diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index ce3e204a1..9ff46086c 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -2191,7 +2191,7 @@ pbool PR_TestRecompile(progfuncs_t *progfuncs) return true; return false; } - +/* #ifdef _DEBUG //this is for debugging. //I'm using this to detect incorrect string types while converting 32bit string pointers with bias to bound indexes. @@ -2225,7 +2225,7 @@ void PR_TestForWierdness(progfuncs_t *progfuncs) } } #endif - +*/ char *decode(int complen, int len, int method, char *info, char *buffer); /* =============== diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index a561db74c..9b081872f 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -245,12 +245,11 @@ int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum) pr_depth--; PR_StackTrace (progfuncs); - printf ("stack overflow on call to %s\n", f->s_name); + printf ("stack overflow on call to %s\n", progfuncs->stringtable+f->s_name); //comment this out if you want the progs to try to continue anyway (could cause infinate loops) - Abort("Stack Overflow\n"); - PR_AbortStack(progfuncs); + Abort("Stack Overflow in %s\n", progfuncs->stringtable+f->s_name); return pr_xstatement; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index ebc10c804..a24a139a2 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -798,7 +798,7 @@ void PR_BreakPoint_f(void) Con_Printf("Breakpoint has been cleared\n"); } - +/* #ifdef _DEBUG void QCLibTest(void) { @@ -811,7 +811,7 @@ void QCLibTest(void) PR_TestForWierdness(svprogfuncs); } #endif - +*/ typedef char char32[32]; char32 sv_addonname[MAXADDONS]; void PR_Init(void) @@ -821,9 +821,11 @@ void PR_Init(void) Cmd_AddCommand ("decompile", PR_Decompile_f); Cmd_AddCommand ("compile", PR_Compile_f); Cmd_AddCommand ("applycompile", PR_ApplyCompilation_f); +/* #ifdef _DEBUG Cmd_AddCommand ("svtestprogs", QCLibTest); #endif +*/ Cvar_Register(&pr_maxedicts, cvargroup_progs); Cvar_Register(&pr_imitatemvdsv, cvargroup_progs); Cvar_Register(&pr_fixbrokenqccarrays, cvargroup_progs); @@ -3713,6 +3715,7 @@ void PF_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals) end[2] -= 512; VectorCopy (ent->v->origin, start); + start[2] += 1; trace = SV_Move (start, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); if (trace.fraction == 1 || trace.allsolid) @@ -8644,11 +8647,18 @@ void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) if (tagentity != sv.edicts && tagname && tagname[0]) { modelindex = (int)tagentity->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS && sv.model_precache[modelindex]) + if (modelindex > 0 && modelindex < MAX_MODELS) { - tagidx = SV_TagForName(modelindex, tagname); - if (tagidx == 0) - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), sv.models[modelindex]->name); + if (!sv.models[modelindex]) + sv.models[modelindex] = Mod_ForName(sv.model_precache[modelindex], false); + if (sv.models[modelindex]) + { + tagidx = SV_TagForName(modelindex, tagname); + if (tagidx == 0) + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), sv.models[modelindex]->name); + } + else + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): Couldn't load model %s\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, sv.modelname[modelindex]); } else Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity)); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 405c0b2f7..07daa083d 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2620,11 +2620,11 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore { if (ent->v->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, client->edict)) state->dpflags |= RENDER_VIEWMODEL; -// else -// { //noone else sees it. -// pack->num_entities--; -// continue; -// } + else + { //noone else sees it. + pack->num_entities--; + continue; + } } if (ent->v->exteriormodeltoclient) { diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index cf06d6c3a..a4d8dcf02 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1641,7 +1641,7 @@ client_t *SVC_DirectConnect(void) newcl->netchan.compress = false; newcl->protocol = protocol; -#ifdef NQNET +#ifdef NQPROT newcl->netchan.isnqprotocol = ISNQCLIENT(newcl); #endif diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 80dfe5466..cc0523e6e 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -1031,6 +1031,7 @@ void SV_Physics_Toss (edict_t *ent) VectorCopy(ent->v->origin, temporg); VectorCopy(temporg, ent->v->origin); trace = SV_PushEntity (ent, move); + if (trace.allsolid) trace.fraction = 0; if (trace.fraction == 1) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index dd9b760ca..3194cbd1b 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -3575,10 +3575,9 @@ void AddLinksToPmove ( areanode_t *node ) int pl; int i; physent_t *pe; - float os, omt; - hull_t *hull; -vec3_t offset; + model_t *model; + pl = EDICT_TO_PROG(svprogfuncs, sv_player); // touch linked edicts @@ -3648,17 +3647,10 @@ vec3_t offset; if (!((int)sv_player->v->dimension_hit & (int)check->v->dimension_solid)) continue; -// check->v->model = "a"; - os = check->v->solid; - omt = check->v->movetype; - check->v->solid = SOLID_BSP; - check->v->movetype = MOVETYPE_PUSH; - hull = SV_HullForEntity (check, 0, sv_player->v->mins, sv_player->v->maxs, offset); - check->v->movetype = omt; - check->v->solid = os; - + model = sv.models[(int)check->v->modelindex]; + if (model) // test the point - if ( hull->funcs.HullPointContents (hull, sv_player->v->origin) == FTECONTENTS_SOLID ) + if ( model->hulls[0].funcs.HullPointContents (&model->hulls[0], sv_player->v->origin) == FTECONTENTS_SOLID ) sv_player->v->fteflags = (int)sv_player->v->fteflags | FF_LADDER; //touch that ladder! } } diff --git a/engine/server/svmodel.c b/engine/server/svmodel.c index ca2019e62..fb79f8d7f 100644 --- a/engine/server/svmodel.c +++ b/engine/server/svmodel.c @@ -282,6 +282,26 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash) Mod_LoadBrushModel (mod, buf); break; + + case IDPOLYHEADER: + GL_LoadQ1Model(mod, buf); + break; +#ifdef MD2MODELS + case MD2IDALIASHEADER: + GL_LoadQ2Model(mod, buf); + break; +#endif +#ifdef MD3MODELS + case MD3_IDENT: + GL_LoadQ3Model (mod, buf); + break; +#endif +#ifdef ZYMOTICMODELS + case (('O'<<24)+('M'<<16)+('Y'<<8)+'Z'): + GLMod_LoadZymoticModel(mod, buf); + break; +#endif + default: if (crash) SV_Error ("Mod_NumForName: %s: format not recognised", mod->name); @@ -1319,5 +1339,28 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) } } } + + + +void *Mod_Extradata (model_t *mod) +{ + void *r; + + r = Cache_Check (&mod->cache); + if (r) + return r; + + Mod_LoadModel (mod, true); + + if (!mod->cache.data) + Sys_Error ("Mod_Extradata: caching failed"); + return mod->cache.data; +} + + + + + + #endif diff --git a/engine/server/world.c b/engine/server/world.c index 13fe5ea7c..f952fe422 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -119,150 +119,6 @@ hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs) return &box_hull; } - - -/* -================ -SV_HullForEntity - -Returns a hull that can be used for testing or clipping an object of mins/maxs -size. -Offset is filled in to contain the adjustment that must be added to the -testing object's origin to get a point to use with the returned hull. -================ -*/ -hull_t *SV_HullForEntity (edict_t *ent, int hullnum, vec3_t mins, vec3_t maxs, vec3_t offset) -{ - model_t *model; - vec3_t size; - vec3_t hullmins, hullmaxs; - hull_t *hull; - -// decide which clipping hull to use, based on the size - if (ent->v->solid == SOLID_BSP) - { // explicit hulls in the BSP model - if (ent->v->movetype != MOVETYPE_PUSH) - SV_Error ("SOLID_BSP without MOVETYPE_PUSH (%s)", ent->v->classname + svprogfuncs->stringtable); - - model = sv.models[ (int)ent->v->modelindex ]; - - if (!model || model->type != mod_brush) - SV_Error ("SOLID_BSP with a non bsp model"); - - VectorSubtract (maxs, mins, size); - if (hullnum >= 1 && hullnum <= MAX_MAP_HULLSM && model->hulls[hullnum-1].available) - hull = &model->hulls[hullnum-1]; - else - { - if (model->hulls[5].available) - { - if (size[0] < 3) // Point - hull = &model->hulls[0]; - else if (size[0] <= 32 && size[2] <= 28) // Half Player - hull = &model->hulls[3]; - else if (size[0] <= 32) // Full Player - hull = &model->hulls[1]; - else // Golumn - hull = &model->hulls[5]; - } - else - { - if (size[0] < 3 || !model->hulls[1].available) - hull = &model->hulls[0]; - else if (size[0] <= 32) - { - if (size[2] < 54 && model->hulls[3].available) - hull = &model->hulls[3]; // 32x32x36 - else - hull = &model->hulls[1]; - } - else - hull = &model->hulls[2]; - } - } - -// calculate an offset value to center the origin - VectorSubtract (hull->clip_mins, mins, offset); - VectorAdd (offset, ent->v->origin, offset); - } - else - { // create a temp hull from bounding box sizes - - VectorSubtract (ent->v->mins, maxs, hullmins); - VectorSubtract (ent->v->maxs, mins, hullmaxs); - hull = SV_HullForBox (hullmins, hullmaxs); - - VectorCopy (ent->v->origin, offset); - } - - - return hull; -} -#ifdef Q2SERVER -hull_t *SVQ2_HullForEntity (q2edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) -{ - model_t *model; - vec3_t size; - vec3_t hullmins, hullmaxs; - hull_t *hull; - -// decide which clipping hull to use, based on the size - if (ent->s.solid == Q2SOLID_BSP) - { // explicit hulls in the BSP model - model = sv.models[ (int)ent->s.modelindex ]; - - if (!model || model->type != mod_brush) - SV_Error ("SOLID_BSP with a non bsp model"); - - VectorSubtract (maxs, mins, size); - if (model->fromgame == fg_halflife) - { - if (size[0] < 3) - hull = &model->hulls[0]; // 0x0x0 - else if (size[0] <= 32) - { - if (size[2] < 54) // pick the nearest of 36 or 72 - hull = &model->hulls[3]; // 32x32x36 - else - hull = &model->hulls[1]; // 32x32x72 - } - else - hull = &model->hulls[2]; // 64x64x64 - } - else - { - if (size[0] < 3) - hull = &model->hulls[0]; - else if (size[0] <= 32) - { - if (size[2] < 54 && model->hulls[3].firstclipnode) // pick the nearest of 36 or 72 - hull = &model->hulls[3]; // 32x32x36 - else - hull = &model->hulls[1]; - } - else - hull = &model->hulls[2]; - } - -// calculate an offset value to center the origin - VectorSubtract (hull->clip_mins, mins, offset); - VectorAdd (offset, ent->s.origin, offset); - } - else - { // create a temp hull from bounding box sizes - - VectorSubtract (ent->mins, maxs, hullmins); - VectorSubtract (ent->maxs, mins, hullmaxs); - hull = SV_HullForBox (hullmins, hullmaxs); - - VectorCopy (ent->s.origin, offset); - } - - - return hull; -} -#endif - /* =============================================================================== @@ -1056,56 +912,88 @@ edict_t *SV_TestEntityPosition (edict_t *ent) return NULL; } +qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace); + //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 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) { + qboolean rotated; vec3_t start_l, end_l; vec3_t a; vec3_t forward, right, up; vec3_t temp; 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 (hull != &box_hull && (angles[0] || angles[1] || angles[2]) ) + if (model) { - AngleVectors (angles, forward, right, up); + rotated = (angles[0] || angles[1] || angles[2]); + if (rotated) + { + AngleVectors (angles, forward, right, up); - VectorCopy (start, temp); - start_l[0] = DotProduct (temp, forward); - start_l[1] = -DotProduct (temp, right); - start_l[2] = DotProduct (temp, up); + VectorSubtract (start, origin, temp); + start_l[0] = DotProduct (temp, forward); + start_l[1] = -DotProduct (temp, right); + start_l[2] = DotProduct (temp, up); - VectorCopy (end, temp); - end_l[0] = DotProduct (temp, forward); - end_l[1] = -DotProduct (temp, right); - end_l[2] = DotProduct (temp, up); + VectorSubtract (end, origin, temp); + end_l[0] = DotProduct (temp, forward); + end_l[1] = -DotProduct (temp, right); + end_l[2] = DotProduct (temp, up); + } + else + { + VectorSubtract (start, origin, start_l); + VectorSubtract (end, origin, end_l); + } + result = model->funcs.Trace (model, hulloverride, frame, start_l, end_l, mins, maxs, trace); + if (rotated) + { + // FIXME: figure out how to do this with existing angles + // VectorNegate (angles, a); + a[0] = -angles[0]; + a[1] = -angles[1]; + a[2] = -angles[2]; + AngleVectors (a, forward, right, up); - result = hull->funcs.RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + VectorCopy (trace->plane.normal, temp); + trace->plane.normal[0] = DotProduct (temp, forward); + trace->plane.normal[1] = -DotProduct (temp, right); + trace->plane.normal[2] = DotProduct (temp, up); - // FIXME: figure out how to do this with existing angles -// VectorNegate (angles, a); - a[0] = -angles[0]; - a[1] = -angles[1]; - a[2] = -angles[2]; - AngleVectors (a, forward, right, up); - - VectorCopy (trace->plane.normal, temp); - trace->plane.normal[0] = DotProduct (temp, forward); - trace->plane.normal[1] = -DotProduct (temp, right); - trace->plane.normal[2] = DotProduct (temp, up); - - trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]); - trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]); - trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]); + trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]); + trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]); + trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]); + } + VectorAdd (trace->endpos, origin, trace->endpos); } else - result = hull->funcs.RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start, end, trace); + { + hull_t *hull = &box_hull; + + memset (trace, 0, sizeof(trace_t)); + trace->fraction = 1; + trace->allsolid = true; + VectorCopy (end, trace->endpos); + + VectorSubtract (start, origin, start_l); + VectorSubtract (end, origin, end_l); + result = Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + VectorAdd (trace->endpos, origin, trace->endpos); + } return result; } - - /* ================== SV_ClipMoveToEntity @@ -1114,53 +1002,82 @@ Handles selection or creation of a clipping hull, and offseting (and eventually rotation) of the end points ================== */ -trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum) //hullnum overrides min/max for q1 style bsps +trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel) //hullnum overrides min/max for q1 style bsps { trace_t trace; - vec3_t offset; - vec3_t start_l, end_l; - hull_t *hull; - + model_t *model; +/* #ifdef Q2BSPS if (ent->v->solid == SOLID_BSP) if (sv.models[(int)ent->v->modelindex] && (sv.models[(int)ent->v->modelindex]->fromgame == fg_quake2 || sv.models[(int)ent->v->modelindex]->fromgame == fg_quake3)) { trace = CM_TransformedBoxTrace (start, end, mins, maxs, sv.models[(int)ent->v->modelindex]->hulls[0].firstclipnode, MASK_PLAYERSOLID, ent->v->origin, ent->v->angles); - if (trace.fraction < 1 || trace.startsolid ) + if (trace.fraction < 1 || trace.startsolid) trace.ent = ent; return trace; } #endif - - -// fill in a default trace - memset (&trace, 0, sizeof(trace_t)); - trace.fraction = 1; - trace.allsolid = true; - VectorCopy (end, trace.endpos); +*/ // get the clipping hull - hull = SV_HullForEntity (ent, hullnum, mins, maxs, offset); - - VectorSubtract (start, offset, start_l); - VectorSubtract (end, offset, end_l); + if (ent->v->solid == SOLID_BSP) + { + model = sv.models[(int)ent->v->modelindex]; + if (!model || model->type != mod_brush) + SV_Error("SOLID_BSP with non bsp model (classname: %s)", svprogfuncs->stringtable + ent->v->classname); + } + else + { + vec3_t boxmins, boxmaxs; + VectorSubtract (ent->v->mins, maxs, boxmins); + VectorSubtract (ent->v->maxs, mins, boxmaxs); + SV_HullForBox(boxmins, boxmaxs); + model = NULL; + } // trace a line through the apropriate clipping hull if (progstype == PROG_H2 && ent->v->solid == SOLID_BSP) { ent->v->angles[0]*=-1; - TransformedHullCheck(hull, start_l, end_l, &trace, ent->v->angles); + TransformedTrace(model, 0, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles); ent->v->angles[0]*=-1; } else { - TransformedHullCheck(hull, start_l, end_l, &trace, ent->v->angles); + TransformedTrace(model, 0, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles); } // fix trace up by the offset if (trace.fraction != 1) - VectorAdd (trace.endpos, offset, trace.endpos); + { + if (!model && hitmodel && ent->v->solid != SOLID_BSP && ent->v->modelindex > 0) + { + //okay, we hit the bbox + + model_t *model; + if (ent->v->modelindex < 1 || ent->v->modelindex >= MAX_MODELS) + SV_Error("SV_ClipMoveToEntity: modelindex out of range\n"); + model = sv.models[ (int)ent->v->modelindex ]; + if (!model) + { //if the model isn't loaded, load it. + //this saves on memory requirements with mods that don't ever use this. + model = sv.models[(int)ent->v->modelindex] = Mod_ForName(sv.model_precache[(int)ent->v->modelindex], false); + } + + if (model && model->funcs.Trace) + { + //do the second trace + TransformedTrace(model, 0, ent->v->frame, start, end, mins, maxs, &trace, ent->v->origin, ent->v->angles); + } + } + + if (trace.startsolid) + { + if (ent != sv.edicts) + Con_Printf("Trace started solid\n"); + } + } // did we clip the move? if (trace.fraction < 1 || trace.startsolid ) @@ -1172,23 +1089,11 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max trace_t SVQ2_ClipMoveToEntity (q2edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) { trace_t trace; + /* vec3_t offset; vec3_t start_l, end_l; hull_t *hull; -/* -#ifdef Q2BSPS - if (ent->s.solid == Q2SOLID_BSP) - if (sv.models[(int)ent->s.modelindex] && (sv.models[(int)ent->s.modelindex]->fromgame == fg_quake2 || sv.models[(int)ent->s.modelindex]->fromgame == fg_quake3)) - { - trace = CM_TransformedBoxTrace (start, end, mins, maxs, sv.models[(int)ent->s.modelindex]->hulls[0].firstclipnode, MASK_PLAYERSOLID, ent->s.origin, ent->s.angles); - if (trace.fraction < 1 || trace.startsolid ) - trace.ent = (edict_t *)ent; - return trace; - } -#endif -*/ - // fill in a default trace memset (&trace, 0, sizeof(trace_t)); trace.fraction = 1; @@ -1202,7 +1107,7 @@ trace_t SVQ2_ClipMoveToEntity (q2edict_t *ent, vec3_t start, vec3_t mins, vec3_t VectorSubtract (end, offset, end_l); // trace a line through the apropriate clipping hull - TransformedHullCheck(hull, start_l, end_l, &trace, ent->s.angles); + TransformedTrace(ent->s.modelindex, start_l, end_l, &trace, ent->s.angles); // fix trace up by the offset if (trace.fraction != 1) @@ -1211,7 +1116,7 @@ trace_t SVQ2_ClipMoveToEntity (q2edict_t *ent, vec3_t start, vec3_t mins, vec3_t // did we clip the move? if (trace.fraction < 1 || trace.startsolid ) trace.ent = (edict_t *)ent; - +*/ return trace; } #endif @@ -1420,7 +1325,7 @@ int SVQ2_HeadnodeForEntity (q2edict_t *ent) return CM_HeadnodeForBox (ent->mins, ent->maxs); } #endif - +/* void SV_ClipMoveToEntities ( moveclip_t *clip ) { int i, num; @@ -1486,21 +1391,45 @@ void SV_ClipMoveToEntities ( moveclip_t *clip ) touch->v->origin, angles); if (trace.allsolid || trace.startsolid || - trace.fraction < clip->trace.fraction) + trace.fraction < clip->trace.fraction) { - trace.ent = touch; - if (clip->trace.startsolid) + if (clip->type & MOVE_HITMODEL && touch->v->solid != SOLID_BSP) { - clip->trace = trace; - clip->trace.startsolid = true; + model_t *model; + if (touch->v->modelindex < 1 || touch->v->modelindex >= MAX_MODELS) + SV_Error("SV_ClipMoveToEntity: modelindex out of range\n"); + model = sv.models[ (int)touch->v->modelindex ]; + if (!model) + { //if the model isn't loaded, load it. + //this saves on memory requirements with mods that don't ever use this. + model = sv.models[(int)touch->v->modelindex] = Mod_ForName(sv.model_precache[(int)touch->v->modelindex], false); + } + + if (model && model->hulls[0].available) + { + hull_t *hull = &model->hulls[0]; + //do the second trace + memset (&trace, 0, sizeof(trace_t)); + trace.fraction = 1; + trace.allsolid = true; + TransformedHullCheck(hull, clip->start, clip->end, &trace, touch->v->angles); + + if (trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + clip->trace = trace; + } + } } else + { + trace.ent = touch; clip->trace = trace; + } } - else if (trace.startsolid) - clip->trace.startsolid = true; } } +*/ #ifdef Q2SERVER void SVQ2_ClipMoveToEntities ( moveclip_t *clip, int contentsmask ) { @@ -1636,23 +1565,15 @@ void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) } if ((int)touch->v->flags & FL_MONSTER) - trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum); + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); else - trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum); + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { trace.ent = touch; - if (clip->trace.startsolid) - { - clip->trace = trace; - clip->trace.startsolid = true; - } - else - clip->trace = trace; + clip->trace = trace; } - else if (trace.startsolid) - clip->trace.startsolid = true; } // recurse down both sides @@ -1712,20 +1633,13 @@ void SVQ2_ClipToLinks ( areanode_t *node, moveclip_t *clip ) // trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end); // else trace = SVQ2_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end); + if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { trace.ent = (edict_t *)touch; - if (clip->trace.startsolid) - { - clip->trace = trace; - clip->trace.startsolid = true; - } - else - clip->trace = trace; + clip->trace = trace; } - else if (trace.startsolid) - clip->trace.startsolid = true; } // recurse down both sides @@ -1812,13 +1726,13 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e } // clip to world - clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end, hullnum); + clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end, hullnum, false); clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; - clip.type = type; + clip.type = type|4; clip.passedict = passedict; clip.hullnum = hullnum; #ifdef Q2SERVER @@ -1843,11 +1757,12 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); // clip to entities -#ifdef Q2BSPS +/*#ifdef Q2BSPS if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3) SV_ClipMoveToEntities(&clip); else #endif +*/ SV_ClipToLinks ( sv_areanodes, &clip ); if (clip.trace.startsolid)