diff --git a/engine/botlib/l_utils.h b/engine/botlib/l_utils.h index 6944d06f9..41cf4231c 100644 --- a/engine/botlib/l_utils.h +++ b/engine/botlib/l_utils.h @@ -29,7 +29,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ -#define Vector2Angles(v,a) vectoangles(v,a) +void QDECL VectorAngles(float *forward, float *up, float *result, qboolean meshpitch); +#define Vector2Angles(v,a) VectorAngles(v,NULL,a,qfalse) #ifndef MAX_PATH #define MAX_PATH MAX_QPATH #endif diff --git a/engine/botlib/q_shared.h b/engine/botlib/q_shared.h index a076fa3c4..55b5a7c9e 100644 --- a/engine/botlib/q_shared.h +++ b/engine/botlib/q_shared.h @@ -652,7 +652,6 @@ float Q_crandom( int *seed ); #define random() ((rand () & 0x7fff) / ((float)0x7fff)) #define crandom() (2.0 * (random() - 0.5)) -void vectoangles( const vec3_t value1, vec3_t angles); void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ); void AxisClear( vec3_t axis[3] ); diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 9cf170d0b..541ff9d97 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -621,8 +621,7 @@ static float Cam_TryFlyby(vec3_t selforigin, vec3_t playerorigin, vec3_t vec, qb pmove.player_maxs[0] = pmove.player_maxs[1] = 16; pmove.player_maxs[2] = 32; - VectorAngles(vec, NULL, v); -// v[0] = -v[0]; + VectorAngles(vec, NULL, v, true); VectorCopy (v, pmove.angles); VectorNormalize(vec); VectorMA(playerorigin, 800, vec, v); @@ -791,8 +790,7 @@ void Cam_SelfTrack(playerview_t *pv) VectorCopy(pv->cam_desired_position, r_refdef.vieworg); VectorSubtract(pv->simorg, pv->cam_desired_position, vec); - VectorAngles(vec, NULL, r_refdef.viewangles); - r_refdef.viewangles[0] = -r_refdef.viewangles[0]; + VectorAngles(vec, NULL, r_refdef.viewangles, false); } } diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 1a0ff53a2..cbf4f4efb 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1945,9 +1945,9 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt model = NULL; if (model && model->type == mod_alias) { - ang[0]*=-1; + ang[0]*=r_meshpitch.value; AngleVectors(ang, axis[0], axis[1], axis[2]); - ang[0]*=-1; + ang[0]*=r_meshpitch.value; } else AngleVectors(ang, axis[0], axis[1], axis[2]); @@ -2090,10 +2090,10 @@ entity_t *V_AddEntity(entity_t *in) *ent = *in; - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; return ent; } @@ -2120,10 +2120,10 @@ void VQ2_AddLerpEntity(entity_t *in) //a convienience function ent->framestate.g[FS_REG].lerpfrac = back; - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; } */ int V_AddLight (int entsource, vec3_t org, float quant, float r, float g, float b) @@ -3094,7 +3094,7 @@ void CLQ1_AddPowerupShell(entity_t *ent, qboolean viewweap, unsigned int effects ); } shell->shaderRGBAf[0] *= (effects & EF_RED)?1:0; - shell->shaderRGBAf[1] *= 0;//(effects & EF_GREEN)?1:0; + shell->shaderRGBAf[1] *= (effects & EF_GREEN)?1:0; shell->shaderRGBAf[2] *= (effects & EF_BLUE)?1:0; shell->shaderRGBAf[3] *= v_powerupshell.value; /*let the shader do all the work*/ @@ -3129,12 +3129,11 @@ static void CL_UpdateNetFrameLerpState(qboolean force, int curframe, int curbase curbaseframe = curframe; else if (curbasebone == 255) curframe = curbaseframe; - else - le->basebone = curbasebone; + le->basebone = curbasebone; } for (fst = 0; fst < FS_COUNT; fst++) { - frame = fst?curframe:curbaseframe; + frame = (fst==FST_BASE)?curbaseframe:curframe; if (force || frame != le->newframe[fst]) { le->framelerpdeltatime[fst] = bound(0, cl.servertime - le->newframestarttime[fst], 0.1); //clamp to 10 tics per second @@ -3216,10 +3215,10 @@ void CL_LinkStaticEntities(void *pvs) //figure out the correct axis for the model if (clmodel && clmodel->type == mod_alias && (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)) - { - stat->state.angles[0]*=-1; + { //q2 is fixed, but q1 pitches the wrong way + stat->state.angles[0]*=r_meshpitch.value; AngleVectors(stat->state.angles, stat->ent.axis[0], stat->ent.axis[1], stat->ent.axis[2]); - stat->state.angles[0]*=-1; + stat->state.angles[0]*=r_meshpitch.value; } else AngleVectors(stat->state.angles, stat->ent.axis[0], stat->ent.axis[1], stat->ent.axis[2]); @@ -3905,7 +3904,7 @@ void CL_LinkPacketEntities (void) { VectorCopy(le->angles, angles); //if (model && model->type == mod_alias) - angles[0]*=-1; //pflags matches alias models. + angles[0]*=r_meshpitch.value; //pflags matches alias models. AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); VectorInverse(dl->axis[1]); R_LoadNumberedLightTexture(dl, state->skinnum); @@ -4096,7 +4095,7 @@ void CL_LinkPacketEntities (void) } if (model && model->type == mod_alias) - angles[0]*=-1; //carmack screwed up when he added alias models - they pitch the wrong way. + angles[0]*=r_meshpitch.value; //carmack screwed up when he added alias models - they pitch the wrong way. VectorCopy(angles, ent->angles); AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); @@ -4319,10 +4318,10 @@ void CL_LinkProjectiles (void) VectorCopy (pr->origin, ent->origin); VectorCopy (pr->angles, ent->angles); - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; } } @@ -4821,7 +4820,7 @@ void CL_AddFlagModels (entity_t *ent, int team) newent->angles[2] -= 45; VectorCopy(newent->angles, angles); - angles[0]*=-1; + angles[0]*=r_meshpitch.value; AngleVectors(angles, newent->axis[0], newent->axis[1], newent->axis[2]); VectorInverse(newent->axis[1]); } @@ -5071,7 +5070,7 @@ void CL_LinkPlayers (void) } if (model && model->type == mod_alias) - angles[0]*=-1; //carmack screwed up when he added alias models - they pitch the wrong way. + angles[0]*=r_meshpitch.value; //carmack screwed up when he added alias models - they pitch the wrong way. VectorCopy(angles, ent->angles); AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); @@ -5162,7 +5161,7 @@ void CL_LinkViewModel(void) entity_t ent; unsigned int plnum; - player_state_t *plstate; + unsigned int playereffects; float alpha; playerview_t *pv = r_refdef.playerview; @@ -5295,16 +5294,27 @@ void CL_LinkViewModel(void) plnum = Cam_TrackNum(pv); if (plnum == -1) plnum = r_refdef.playerview->playernum; - plstate = &cl.inframes[parsecountmod].playerstate[plnum]; + playereffects = 0; + if (r_refdef.playerview->nolocalplayer && plnum >= 0 && plnum < cl.maxlerpents) + { + if (plnum+1 < cl.maxlerpents) + { + lerpents_t *le = &cl.lerpents[plnum+1]; + if (le->entstate) + playereffects = le->entstate->effects; + } + } + else if (plnum >= 0 && plnum < cl.allocated_client_slots) + playereffects = cl.inframes[parsecountmod].playerstate[plnum].effects; - if (plstate->effects & DPEF_NOGUNBOB) + if (playereffects & DPEF_NOGUNBOB) ent.flags |= RF_WEAPONMODELNOBOB; /* ent.topcolour = TOP_DEFAULT;//cl.players[plnum].ttopcolor; ent.bottomcolour = cl.players[plnum].tbottomcolor; ent.h2playerclass = cl.players[plnum].h2playerclass; */ - CLQ1_AddPowerupShell(V_AddEntity(&ent), true, plstate?plstate->effects:0); + CLQ1_AddPowerupShell(V_AddEntity(&ent), true, playereffects); //small hack to mask depth so only the front faces of the weaponmodel appear (no glitchy intra faces). if (alpha < 1 && qrenderer == QR_OPENGL) @@ -5382,7 +5392,7 @@ void CL_SetSolidEntities (void) if (pent->model->loadstate != MLS_LOADED) continue; VectorCopy (state->angles, pent->angles); - pent->angles[0]*=-1; + pent->angles[0]*=r_meshpitch.value; } else { diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 40ab7f27f..e7caaaaf2 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -739,8 +739,7 @@ void CL_ClampPitch (int pnum) Matrix4_Multiply(Matrix4x4_CM_NewRotation(roll, 1, 0, 0), mat, mat2); #endif Matrix3x4_RM_ToVectors(mat2, view[0], view[1], view[2], view[3]); - VectorAngles(view[0], view[2], pv->viewangles); - pv->viewangles[PITCH]=360 - pv->viewangles[PITCH]; + VectorAngles(view[0], view[2], pv->viewangles, false); VectorClear(pv->viewanglechange); return; @@ -782,8 +781,7 @@ void CL_ClampPitch (int pnum) Matrix4_Multiply(viewm, invsurfm, mat); /*convert that back to angles*/ Matrix3x4_RM_ToVectors(mat, view[0], view[1], view[2], view[3]); - VectorAngles(view[0], view[2], vang); - vang[PITCH] *= -1; + VectorAngles(view[0], view[2], vang, false); /*edit it*/ vang[PITCH] += pv->viewanglechange[PITCH]; @@ -833,8 +831,7 @@ void CL_ClampPitch (int pnum) Matrix4_Multiply(mat, surfm, viewm); /*and figure out the final result*/ Matrix3x4_RM_ToVectors(viewm, view[0], view[1], view[2], view[3]); - VectorAngles(view[0], view[2], cl.playerview[pnum].viewangles); - cl.playerview[pnum].viewangles[PITCH] *= -1; + VectorAngles(view[0], view[2], cl.playerview[pnum].viewangles, false); if (pv->viewangles[ROLL] >= 360) pv->viewangles[ROLL] -= 360; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a796a343c..d5eef9305 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -4931,7 +4931,7 @@ void CL_UpdateHeadAngles(void) AngleVectorsFLU(pv->viewangles, tmp[0], tmp[1], tmp[2]); R_ConcatRotations(headchange, tmp, tmp2); VectorAngles(tmp2[0], tmp2[2], pv->viewangles); - pv->viewangles[0] *= -1; + pv->viewangles[0] *= r_meshpitch.value; //fall through default: diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 3de937475..14acb5606 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -4448,9 +4448,9 @@ void CL_ParseStaticProt (int baselinetype) VectorCopy (es.angles, ent->angles); if (ent->model && ent->model->type == mod_alias) { - es.angles[0]*=-1; + es.angles[0]*=r_meshpitch.value; AngleVectors(es.angles, ent->axis[0], ent->axis[1], ent->axis[2]); - es.angles[0]*=-1; + es.angles[0]*=r_meshpitch.value; } else AngleVectors(es.angles, ent->axis[0], ent->axis[1], ent->axis[2]); diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 7526087a7..8b37dd7c1 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -776,7 +776,7 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st VectorSet(plstate->gravitydir, 0, 0, -1); else { - a[0] = ((-192-state->u.q1.gravitydir[0])/256.0f) * 360; + a[0] = ((192+state->u.q1.gravitydir[0])/256.0f) * 360; a[1] = (state->u.q1.gravitydir[1]/256.0f) * 360; a[2] = 0; AngleVectors(a, plstate->gravitydir, NULL, NULL); @@ -1302,10 +1302,9 @@ void CL_PredictMovePNum (int seat) #endif { VectorScale(pv->simangles, 1, le->angles); - if (pv->pmovetype == PM_6DOF) - le->angles[0] *= -1; - else - le->angles[0] *= -0.333; + if (pv->pmovetype != PM_6DOF) + le->angles[0] *= 0.333; + le->angles[0] *= r_meshpitch.value; } } @@ -1316,8 +1315,7 @@ void CL_PredictMovePNum (int seat) vec3_t dir; VectorSubtract(pv->simorg, pv->cam_desired_position, dir); - VectorAngles(dir, NULL, pv->simangles); - pv->simangles[0] *= -1; + VectorAngles(dir, NULL, pv->simangles, false); VectorCopy(pv->simangles, pv->viewangles); pv->viewangles[0] = anglemod(pv->viewangles[0]); if (pv->viewangles[0] > 180) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 7a3c82494..cd888a684 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -481,8 +481,15 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode) } else if (str[1] == 'I') { - char *e = strchr(str+=2, ':'); - int l = e - str; + char *e; + int l; + str+=2; + e = strchr(str, ':'); + if (!e) + e = strchr(str, ' '); //probably an error + if (!e) + e = str + strlen(str)-1; //error + l = e - str; if (l >= sizeof(p->titleimage)) l = sizeof(p->titleimage)-1; strncpy(p->titleimage, str, l); @@ -2384,7 +2391,7 @@ static void SCR_ScreenShot_f (void) Con_Printf (CON_ERROR "Couldn't write %s\n", sysname); } -void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, enum uploadfmt *fmt) +static void *SCR_ScreenShot_Capture(int fbwidth, int fbheight, enum uploadfmt *fmt) { int width, height; void *buf; @@ -2468,10 +2475,10 @@ static void SCR_ScreenShot_Mega_f(void) if (!fbwidth) fbwidth = sh_config.texture_maxsize; - fbwidth = bound(0, fbwidth, sh_config.texture_maxsize); + fbwidth = bound(1, fbwidth, sh_config.texture_maxsize); if (!fbheight) fbheight = (fbwidth * 3)/4; - fbheight = bound(0, fbheight, sh_config.texture_maxsize); + fbheight = bound(1, fbheight, sh_config.texture_maxsize); if (strstr (screenyname, "..") || strchr(screenyname, ':') || *screenyname == '.' || *screenyname == '/') screenyname = ""; @@ -2567,6 +2574,8 @@ static void SCR_ScreenShot_VR_f(void) if (width <= 2) width = 2048; + if (width > sh_config.texture_maxsize) + width = sh_config.texture_maxsize; height = width/2; if (step <= 0) step = 5; @@ -2693,9 +2702,57 @@ static void SCR_ScreenShot_VR_f(void) VectorClear(r_refdef.eyeoffset); } -void SCR_ScreenShot_EnvMap_f(void) +void SCR_ScreenShot_Cubemap_f(void) { - Con_Printf("Not implemented\n"); + void *buffer; + int fbwidth, fbheight; + uploadfmt_t fmt; + char filename[MAX_QPATH]; + char *fname = Cmd_Argv(1); + int i; + const struct + { + vec3_t angle; + const char *postfix; + } sides[] = + { + {{0, 0, 0}, "_px"}, + {{0, 180, 0}, "_nx"}, + {{0, 90, 0}, "_py"}, + {{0, 270, 0}, "_ny"}, + {{90, 0, 0}, "_pz"}, + {{-90, 0, 0}, "_nz"} + }; + + r_refdef.stereomethod = STEREO_OFF; + + fbheight = atoi(Cmd_Argv(2)); + if (fbheight < 1) + fbheight = 512; + fbwidth = fbheight; + + for (i = 0; i < countof(sides); i++) + { + Q_snprintfz(filename, sizeof(filename), "cubemaps/%s%s", fname, sides[i].postfix); + COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename)); + + buffer = SCR_ScreenShot_Capture(fbwidth, fbheight, &fmt); + if (buffer) + { + char sysname[1024]; + if (SCR_ScreenShot(filename, FS_GAMEONLY, &buffer, 1, fbwidth, fbheight, fmt)) + { + FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); + Con_Printf ("Wrote %s\n", sysname); + } + else + { + FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); + Con_Printf ("Failed to write %s\n", sysname); + } + BZ_Free(buffer); + } + } } @@ -3035,7 +3092,8 @@ void SCR_Init (void) Cmd_AddCommandD ("screenshot_mega",SCR_ScreenShot_Mega_f, "screenshot_mega [width] [height]\nTakes a screenshot with explicit sizes that are not tied to the size of your monitor, allowing for true monstrosities."); Cmd_AddCommandD ("screenshot_stereo",SCR_ScreenShot_Mega_f, "screenshot_stereo [width] [height]\nTakes a simple stereo screenshot."); Cmd_AddCommandD ("screenshot_vr",SCR_ScreenShot_VR_f, "screenshot_vr [width]\nTakes a spherical stereoscopic panorama image, for viewing with VR displays."); - Cmd_AddCommand ("envmap",SCR_ScreenShot_EnvMap_f); + Cmd_AddCommandD ("screenshot_cubemap",SCR_ScreenShot_Cubemap_f, "screenshot_cubemap [size]\nTakes 6 screenshots forming a single cubemap."); + Cmd_AddCommandD ("envmap",SCR_ScreenShot_Cubemap_f, "Legacy name for the screenshot_cubemap command."); //legacy Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); Cmd_AddCommand ("sizeup",SCR_SizeUp_f); Cmd_AddCommand ("sizedown",SCR_SizeDown_f); diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index fd5ebdbb7..9c9dc5ec6 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -1378,6 +1378,7 @@ void CL_ParseTEnt (void) explosion_t *ex = CL_AllocExplosion (pos); ex->start = cl.time; ex->model = Mod_ForName ("progs/s_explod.spr", MLV_WARN); + ex->endalpha = ex->startalpha; //don't fade out } break; @@ -2369,7 +2370,7 @@ void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, vec3_t orientationup, model_t ex->angles[1] = 270; else ex->angles[1] = 0; - ex->angles[0]*=-1; + ex->angles[0]*=r_meshpitch.value; } @@ -2789,7 +2790,7 @@ fixme: ex->angles[1] = 270; else ex->angles[1] = 0; - ex->angles[0]*=-1; + ex->angles[0]*=r_meshpitch.value; S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0); @@ -3116,7 +3117,7 @@ fixme: ex->angles[1] = 270; else ex->angles[1] = 0; - ex->angles[0]*=-1; + ex->angles[0]*=r_meshpitch.value; S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0); @@ -3165,7 +3166,7 @@ fixme: ex->angles[1] = 270; else ex->angles[1] = 0; - ex->angles[0]*=-1; + ex->angles[0]*=r_meshpitch.value; S_StartSound (0, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, NULL, 1, 1, 0, 0, 0); @@ -3569,10 +3570,9 @@ void CL_UpdateBeams (void) VectorSubtract (playerbeam_end[j], vieworg, org); len = VectorLength(org); org[2] -= 22; // adjust for view height - VectorAngles (org, NULL, ang); + VectorAngles (org, NULL, ang, false); // lerp pitch - ang[0] = -ang[0]; if (ang[0] < -180) ang[0] += 360; ang[0] += (viewang[0] - ang[0]) * f; @@ -3823,7 +3823,7 @@ void CL_UpdateExplosions (void) VectorCopy (ex->oldorigin, ent->oldorigin); VectorCopy (ex->angles, ent->angles); ent->skinnum = ex->skinnum; - ent->angles[0]*=-1; + ent->angles[0]*=r_meshpitch.value; AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); ent->model = ex->model; diff --git a/engine/client/client.h b/engine/client/client.h index c1e55d95b..eabacf2ca 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1430,8 +1430,6 @@ void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg); void CL_InitCam(void); void Cam_AutoTrack_Update(const char *mode); //reset autotrack setting (because we started a new map or whatever) -void QDECL vectoangles(vec3_t fwd, vec3_t ang); - // //zqtp.c // diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index d55a51b10..9ca2cba71 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1762,7 +1762,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame) } } - ent.angles[0]*=-1; //q2 has it fixed. + ent.angles[0]*=r_meshpitch.value; //q2 has it fixed. if (s1->number == cl.playerview[0].playernum+1) //woo! this is us! { diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 9c0b69746..535f67e23 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -348,7 +348,7 @@ void PM_ValidatePackage(package_t *p) } } } - if (o && o->qhash && p->qhash && (o->flags & DPF_CACHED) && fl == DPF_CACHED) + if (o && o->qhash && p->qhash && (o->flags & DPF_CACHED) || fl == DPF_CACHED) p->flags |= DPF_CACHED; else if (!o) { @@ -2547,13 +2547,13 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsig case DPF_MARKED: p->flags |= DPF_PURGE; //now: re-get despite already having it. - if ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p)) + if ((p->flags & DPF_CORRUPT) || ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p))) break; //only makes sense if we already have a cached copy that we're not going to use. //fallthrough case DPF_MARKED|DPF_PURGE: PM_UnmarkPackage(p); //now: delete - if ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p)) + if ((p->flags & DPF_CORRUPT) || ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p))) break; //only makes sense if we have a cached/corrupt copy of it already //fallthrough case DPF_PURGE: diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 14cd2d5d3..867f07ed3 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -2933,10 +2933,10 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ ent.light_known = 2; -// ent.angles[0]*=-1; +// ent.angles[0]*=r_meshpitch.value; AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]); VectorInverse(ent.axis[1]); -// ent.angles[0]*=-1; +// ent.angles[0]*=r_meshpitch.value; if (ent.model->type == mod_dummy) { diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 5149f4d35..4387aef69 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -557,17 +557,25 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t out->g[FST_BASE].frame[0] = in->xv->baseframe; out->g[FST_BASE].frame[1] = in->xv->baseframe2; + //out->g[FST_BASE].frame[2] = in->xv->baseframe3; + //out->g[FST_BASE].frame[3] = in->xv->baseframe4; out->g[FST_BASE].lerpweight[1] = in->xv->baselerpfrac; - out->g[FST_BASE].lerpweight[0] = 1-out->g[FST_BASE].lerpweight[1]; +// out->g[FST_BASE].lerpweight[2] = in->xv->baselerpfrac3; +// out->g[FST_BASE].lerpweight[3] = in->xv->baselerpfrac4; + out->g[FST_BASE].lerpweight[0] = 1-(out->g[FST_BASE].lerpweight[1]); if (rflags & CSQCRF_FRAMETIMESARESTARTTIMES) { out->g[FST_BASE].frametime[0] = *csqcg.simtime - in->xv->baseframe1time; out->g[FST_BASE].frametime[1] = *csqcg.simtime - in->xv->baseframe2time; + //out->g[FST_BASE].frametime[2] = *csqcg.simtime - in->xv->baseframe3time; + //out->g[FST_BASE].frametime[3] = *csqcg.simtime - in->xv->baseframe4time; } else { out->g[FST_BASE].frametime[0] = in->xv->baseframe1time; out->g[FST_BASE].frametime[1] = in->xv->baseframe2time; + //out->g[FST_BASE].frametime[2] = in->xv->baseframe3time; + //out->g[FST_BASE].frametime[3] = in->xv->baseframe4time; } } @@ -820,7 +828,7 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) { VectorCopy(in->v->angles, out->angles); if (model->type == mod_alias) - out->angles[0]*=-1; + out->angles[0] *= r_meshpitch.value; AngleVectors(out->angles, out->axis[0], out->axis[1], out->axis[2]); VectorInverse(out->axis[1]); @@ -1083,10 +1091,10 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa G_FLOAT(OFS_RETURN) = l->style-1; break; case lfield_angles: - VectorAngles(l->axis[0], l->axis[2], v); - G_FLOAT(OFS_RETURN+0) = anglemod(v[0]?-v[0]:0); - G_FLOAT(OFS_RETURN+1) = v[1]?v[1]:0; - G_FLOAT(OFS_RETURN+2) = v[2]?v[2]:0; + VectorAngles(l->axis[0], l->axis[2], v, false); + G_FLOAT(OFS_RETURN+0) = anglemod(v[0]); + G_FLOAT(OFS_RETURN+1) = v[1]; + G_FLOAT(OFS_RETURN+2) = v[2]; break; case lfield_fov: G_FLOAT(OFS_RETURN) = l->fov; @@ -1542,20 +1550,20 @@ void QCBUILTIN PF_R_AddTrisoup(pubprogfuncs_t *prinst, struct globalvars_s *pr_g //validates the pointer. numverts = (prinst->stringtablesize - vertsptr) / sizeof(qcvertex_t); - if (numverts < 1 || vertsptr <= 0 || vertsptr+numverts*sizeof(qcvertex_t) >= prinst->stringtablesize) + if (numverts < 1 || vertsptr <= 0 || vertsptr+numverts*sizeof(qcvertex_t) > prinst->stringtablesize) { PR_BIError(prinst, "PF_R_AddTrisoup: invalid vertexes pointer\n"); return; } vert = (qcvertex_t*)(prinst->stringtable + vertsptr); - if (indexesptr <= 0 || indexesptr+numindexes*sizeof(int) >= prinst->stringtablesize) + if (indexesptr <= 0 || indexesptr+numindexes*sizeof(int) > prinst->stringtablesize) { PR_BIError(prinst, "PF_R_AddTrisoup: invalid indexes pointer\n"); return; } idx = (int*)(prinst->stringtable + indexesptr); - first = csqc_poly_startvert - csqc_poly_origvert; + first = cl_numstrisvert - csqc_poly_origvert; if (first + numindexes > MAX_INDICIES) { if (numindexes > MAX_INDICIES) @@ -1603,7 +1611,8 @@ void QCBUILTIN PF_R_AddTrisoup(pubprogfuncs_t *prinst, struct globalvars_s *pr_g cl_strisidx[cl_numstrisidx++] = first++; } - //this is where our current poly starts, so verts+end can still work properly afterwards. + + //in case someone calls polygonvertex+end without beginpolygon csqc_poly_startvert = cl_numstrisvert; csqc_poly_startidx = cl_numstrisidx; } @@ -2504,7 +2513,7 @@ static model_t *csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int mode return NULL; prinst->SetStringField(prinst, (void*)ent, &ent->v->model, cl.model_csqcname[-modelindex], true); if (!cl.model_csqcprecache[-modelindex]) - cl.model_csqcprecache[-modelindex] = Mod_ForName(Mod_FixName(cl.model_csqcname[-modelindex], csqc_world.worldmodel->name), MLV_WARN); + cl.model_csqcprecache[-modelindex] = Mod_ForName(Mod_FixName(cl.model_csqcname[-modelindex], csqc_world.worldmodel->publicname), MLV_WARN); model = cl.model_csqcprecache[-modelindex]; } else @@ -2587,7 +2596,7 @@ static void QCBUILTIN PF_cs_PrecacheModel(pubprogfuncs_t *prinst, struct globalv return; } - fixedname = Mod_FixName(modelname, csqc_world.worldmodel->name); + fixedname = Mod_FixName(modelname, csqc_world.worldmodel->publicname); for (i = 1; i < MAX_PRECACHE_MODELS; i++) //Make sure that the server specified model is loaded.. { @@ -2607,7 +2616,7 @@ static void QCBUILTIN PF_cs_PrecacheModel(pubprogfuncs_t *prinst, struct globalv { if (!freei) Host_EndGame("CSQC ran out of model slots\n"); - fixedname = Mod_FixName(modelname, csqc_world.worldmodel->name); + fixedname = Mod_FixName(modelname, csqc_world.worldmodel->publicname); Q_strncpyz(cl.model_csqcname[-freei], fixedname, sizeof(cl.model_csqcname[-freei])); //allocate a slot now modelindex = freei; @@ -3233,7 +3242,7 @@ static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct glo } VectorCopy(pmove.angles, ent->v->angles); - ent->v->angles[0] *= -1/3.0f; //FIXME + ent->v->angles[0] *= r_meshpitch.value * 1/3.0f; //FIXME VectorCopy(pmove.origin, ent->v->origin); VectorCopy(pmove.velocity, ent->v->velocity); ent->xv->pmove_flags = 0; @@ -4757,7 +4766,7 @@ void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent) VectorCopy(srcp->viewangles, ent->v->angles); VectorCopy(srcp->velocity, ent->v->velocity); - ent->v->angles[0] *= -0.333; + ent->v->angles[0] *= r_meshpitch.value * 0.333; ent->v->colormap = pnum+1; ent->xv->scale = srcp->scale; //ent->v->fatness = srcp->fatness; @@ -5133,7 +5142,7 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s * case GE_GRAVITYDIR: { vec3_t a; - a[0] = ((-192-es->u.q1.gravitydir[0])/256.0f) * 360; + a[0] = ((192+es->u.q1.gravitydir[0])/256.0f) * 360; a[1] = (es->u.q1.gravitydir[1]/256.0f) * 360; a[2] = 0; AngleVectors(a, G_VECTOR(OFS_RETURN), NULL, NULL); @@ -6856,7 +6865,7 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks csqc_world.Get_CModel = CSQC_World_ModelForIndex; csqc_world.Get_FrameState = CSQC_World_GetFrameState; csqc_world.defaultgravityscale = 1; - World_ClearWorld(&csqc_world); + World_ClearWorld(&csqc_world, false); CSQC_InitFields(); //let the qclib know the field order that the engine needs. if (setjmp(csqc_abort)) @@ -7033,6 +7042,8 @@ void CSQC_WorldLoaded(void) worldent->readonly = false; //just in case + World_ClearWorld(&csqc_world, true); + if (csqc_isdarkplaces) { if (csqcg.init_function) @@ -7290,7 +7301,7 @@ qboolean CSQC_SetupToRenderPortal(int entkeynum) *csqcg.self = EDICT_TO_PROG(csqcprogs, e); VectorCopy(r_refdef.vieworg, G_VECTOR(OFS_PARM0)); - VectorAngles(vpn, vup, G_VECTOR(OFS_PARM1)); + VectorAngles(vpn, vup, G_VECTOR(OFS_PARM1), true/*FIXME*/); VectorCopy(vpn, csqcg.forward); VectorCopy(vright, csqcg.right); VectorCopy(vup, csqcg.up); diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index 94741f3e5..85a155cdd 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -220,12 +220,11 @@ static void bonemat_fromentity(world_t *w, wedict_t *ed, float *trans) vec3_t d[3], a; model_t *mod; mod = w->Get_CModel(w, ed->v->modelindex); - if (!mod || mod->type == mod_alias) - a[0] = -ed->v->angles[0]; - else - a[0] = ed->v->angles[0]; + a[0] = ed->v->angles[0]; a[1] = ed->v->angles[1]; a[2] = ed->v->angles[2]; + if (!mod || mod->type == mod_alias) + a[0] *= r_meshpitch.value; AngleVectors(a, d[0], d[1], d[2]); bonemat_fromqcvectors(trans, d[0], d[1], d[2], ed->v->origin); } @@ -1610,7 +1609,7 @@ void QCBUILTIN PF_skel_ragedit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g vec3_t d[3], a; //fixme: respond to renderflags&USEAXIS? scale? - a[0] = wed->v->angles[0] * -1; /*mod_alias bug*/ + a[0] = wed->v->angles[0] * r_meshpitch.value; /*mod_alias bug*/ a[1] = wed->v->angles[1]; a[2] = wed->v->angles[2]; AngleVectors(a, d[0], d[1], d[2]); @@ -2056,7 +2055,7 @@ void QCBUILTIN PF_skel_set_bone_world (pubprogfuncs_t *prinst, struct globalvars if (prinst->callargc == 4) { vec3_t d[3], a; - a[0] = G_VECTOR(OFS_PARM3)[0] * -1; /*mod_alias bug*/ + a[0] = G_VECTOR(OFS_PARM3)[0] * r_meshpitch.value; /*mod_alias bug*/ a[1] = G_VECTOR(OFS_PARM3)[1]; a[2] = G_VECTOR(OFS_PARM3)[2]; AngleVectors(a, d[0], d[1], d[2]); diff --git a/engine/client/render.h b/engine/client/render.h index ecb2e87c2..4bc322f9b 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -628,6 +628,8 @@ extern cvar_t gl_playermip; extern cvar_t r_lightmap_saturation; +extern cvar_t r_meshpitch; + enum { RSPEED_TOTALREFRESH, RSPEED_LINKENTITIES, diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 7c3afbddf..abdf1fb54 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -611,7 +611,12 @@ void R_ToggleFullscreen_f(void) Cvar_ApplyLatches(CVAR_RENDERERLATCH); newr = currentrendererstate; - newr.fullscreen = newr.fullscreen?0:2; + if (newr.fullscreen) + newr.fullscreen = 0; //if we're currently any sort of fullscreen then go windowed + else if (vid_fullscreen.ival) + newr.fullscreen = vid_fullscreen.ival; //if we're normally meant to be fullscreen, use that + else + newr.fullscreen = 2; //otherwise use native resolution if (newr.fullscreen) { int dbpp, dheight, dwidth, drate; @@ -623,8 +628,14 @@ void R_ToggleFullscreen_f(void) drate = 0; } - newr.width = dwidth; - newr.height = dheight; + if (newr.fullscreen == 1 && vid_width.ival>0) + newr.width = vid_width.ival; + else + newr.width = dwidth; + if (newr.fullscreen == 1 && vid_height.ival>0) + newr.height = vid_height.ival; + else + newr.height = dheight; } else { @@ -1392,7 +1403,6 @@ TRACE(("dbg: R_ApplyRenderer: initing mods\n")); #ifndef CLIENTONLY if (sv.world.worldmodel) { - wedict_t *ent; #ifdef Q2SERVER q2edict_t *q2ent; #endif @@ -1419,23 +1429,9 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n")); sv.models[i] = NULL; } - World_ClearWorld (&sv.world); - ent = sv.world.edicts; + World_ClearWorld (&sv.world, true); +// ent = sv.world.edicts; // ent->v->model = PR_NewString(svprogfuncs, sv.worldmodel->name); //FIXME: is this a problem for normal ents? - for (i=0 ; iarea.prev) - { - ent->area.prev = ent->area.next = NULL; - World_LinkEdict (&sv.world, ent, false); // relink ents so touch functions continue to work. - } - } } #ifdef Q2SERVER else if (svs.gametype == GT_QUAKE2) @@ -1455,7 +1451,7 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n")); sv.models[i] = NULL; } - World_ClearWorld (&sv.world); + World_ClearWorld (&sv.world, false); q2ent = ge->edicts; for (i=0 ; inum_edicts ; i++, q2ent = (q2edict_t *)((char *)q2ent + ge->edict_size)) { diff --git a/engine/client/view.c b/engine/client/view.c index ad01f28d3..bec0e49e5 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -2089,8 +2089,7 @@ void V_RenderPlayerViews(playerview_t *pv) r_secondaryview = 2; VectorSubtract(r_refdef.vieworg, pv->cam_desired_position, dir); - VectorAngles(dir, NULL, r_refdef.viewangles); - r_refdef.viewangles[0] = -r_refdef.viewangles[0]; //flip the pitch. :( + VectorAngles(dir, NULL, r_refdef.viewangles, false); VectorCopy(pv->cam_desired_position, r_refdef.vieworg); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 9ebc77cc6..7439dc653 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -524,9 +524,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef VM_CG #undef TEXTEDITOR #undef RUNTIMELIGHTING - #undef DSPMODELS - #undef SPRMODELS - #undef SP2MODELS #undef PSET_SCRIPT #undef PSET_CLASSIC diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index cb52cc63f..958105ea4 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -14,6 +14,20 @@ qboolean r_loadbumpmapping; extern cvar_t dpcompat_psa_ungroup; extern cvar_t r_noframegrouplerp; cvar_t r_lerpmuzzlehack = CVARF ("r_lerpmuzzlehack", "1", CVAR_ARCHIVE); +static void QDECL r_meshpitch_callback(cvar_t *var, char *oldvalue) +{ + if (!strcmp(var->string, "-1") || !strcmp(var->string, "1")) + return; + if (var->value <= 0) + Cvar_ForceSet(var, "-1"); + else + Cvar_ForceSet(var, "1"); +} +#ifdef NOLEGACY +cvar_t r_meshpitch = CVARCD ("r_meshpitch", "1", r_meshpitch_callback, "Specifies the direction of the pitch angle on mesh models formats, also affects gamecode, so do not change from its default."); +#else +cvar_t r_meshpitch = CVARCD ("r_meshpitch", "-1", r_meshpitch_callback, "Specifies the direction of the pitch angle on mesh models formats, Quake compatibility requires -1."); +#endif #ifndef SERVERONLY void Mod_UpdateCRC(void *ctx, void *data, size_t a, size_t b) @@ -2761,10 +2775,11 @@ void Mod_BuildTextureVectors(galiasinfo_t *galias) #ifndef SERVERONLY //looks for foo.md3_0.skin files, for dp compat //also try foo_0.skin, because people appear to use that too. *sigh*. -int Mod_CountSkinFiles(char *modelname) +int Mod_CountSkinFiles(model_t *mod) { int i; char skinfilename[MAX_QPATH]; + char *modelname = mod->name; //try and add numbered skins, and then try fixed names. for (i = 0; ; i++) { @@ -2781,7 +2796,7 @@ int Mod_CountSkinFiles(char *modelname) } //support for foo.md3_0.skin -shader_t *Mod_ShaderFromQ3SkinFile(galiasinfo_t *surf, char *modelname, int skinnum) +shader_t *Mod_ShaderFromQ3SkinFile(galiasinfo_t *surf, model_t *mod, int skinnum) { shader_t *result = NULL; skinid_t skinid; @@ -2789,6 +2804,7 @@ shader_t *Mod_ShaderFromQ3SkinFile(galiasinfo_t *surf, char *modelname, int skin int i; char *filedata; char skinfilename[MAX_QPATH]; + char *modelname = mod->name; if (qrenderer == QR_NONE) return NULL; @@ -2888,7 +2904,7 @@ void Mod_LoadAliasShaders(model_t *mod) for (j = 0, f = s->frame; j < s->numframes; j++, f++) { if (j == 0) - f->shader = Mod_ShaderFromQ3SkinFile(ai, mod->name, i); + f->shader = Mod_ShaderFromQ3SkinFile(ai, mod, i); else f->shader = NULL; if (!f->shader) @@ -4909,7 +4925,7 @@ qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) root = NULL; #ifndef SERVERONLY - externalskins = Mod_CountSkinFiles(mod->name); + externalskins = Mod_CountSkinFiles(mod); #endif min[0] = min[1] = min[2] = 0; @@ -5335,7 +5351,7 @@ qboolean QDECL Mod_LoadZymoticModel(model_t *mod, void *buffer, size_t fsize) } #ifndef SERVERONLY - skinfiles = Mod_CountSkinFiles(mod->name); + skinfiles = Mod_CountSkinFiles(mod); if (skinfiles < 1) skinfiles = 1; @@ -6297,7 +6313,7 @@ qboolean QDECL Mod_LoadDarkPlacesModel(model_t *mod, void *buffer, size_t fsize) } #ifndef SERVERONLY - skinfiles = Mod_CountSkinFiles(mod->name); + skinfiles = Mod_CountSkinFiles(mod); if (skinfiles < 1) skinfiles = 1; #endif @@ -7054,7 +7070,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsi mesh = (struct iqmmesh*)(buffer + h->ofs_meshes); #ifndef SERVERONLY - skinfiles = Mod_CountSkinFiles(mod->name); + skinfiles = Mod_CountSkinFiles(mod); if (skinfiles < 1) skinfiles = 1; //iqms have 1 skin and one skin only and always. make sure its loaded. #endif diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 8e82ca8dc..b332b644a 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -216,7 +216,7 @@ typedef struct modplugfuncs_s void (QDECL *ConcatTransforms) (float in1[3][4], float in2[3][4], float out[3][4]); void (QDECL *M3x4_Invert) (const float *in1, float *out); - void (QDECL *VectorAngles)(float *forward, float *up, float *result); + void (QDECL *VectorAngles)(float *forward, float *up, float *result, qboolean meshpitch); void (QDECL *AngleVectors)(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); void (QDECL *GenMatrixPosQuat4Scale)(const vec3_t pos, const vec4_t quat, const vec3_t scale, float result[12]); diff --git a/engine/common/com_phys_bullet.cpp b/engine/common/com_phys_bullet.cpp index 7361547ac..db786c52a 100644 --- a/engine/common/com_phys_bullet.cpp +++ b/engine/common/com_phys_bullet.cpp @@ -259,7 +259,7 @@ static void World_Bullet_Frame_BodyToEntity(world_t *world, wedict_t *ed) foo Matrix3x4_RM_ToVectors(entitymatrix, forward, left, up, origin); VectorAngles(forward, up, angles); - angles[0]*=-1; + angles[0]*=r_meshpitch.value; avelocity[PITCH] = RAD2DEG(spinvelocity[PITCH]); avelocity[YAW] = RAD2DEG(spinvelocity[ROLL]); @@ -270,8 +270,8 @@ static void World_Bullet_Frame_BodyToEntity(world_t *world, wedict_t *ed) model = world->Get_CModel(world, ed->v->modelindex); if (!model || model->type == mod_alias) { - angles[PITCH] *= -1; - avelocity[PITCH] *= -1; + angles[PITCH] *= r_meshpitch.value; + avelocity[PITCH] *= r_meshpitch.value; } } @@ -856,7 +856,7 @@ public: if (!model || model->type == mod_alias) ; else - edict->v->angles[PITCH] *= -1; + edict->v->angles[PITCH] *= r_meshpitch.value; } //so it doesn't get rebuilt @@ -1219,8 +1219,8 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed) model = world->Get_CModel(world, ed->v->modelindex); if (!model || model->type == mod_alias) { - qangles[PITCH] *= -1; - qavelocity[PITCH] *= -1; + qangles[PITCH] *= r_meshpitch.value; + qavelocity[PITCH] *= r_meshpitch.value; } } diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index c961e71a7..30ed561ab 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -82,6 +82,7 @@ static BUILTINR(cvar_t*, Cvar_GetNVFDG, (const char *name, const char *defaultva #undef ARGNAMES static rbeplugfuncs_t *rbefuncs; +cvar_t r_meshpitch; //============================================================================ // physics engine support @@ -1484,8 +1485,7 @@ static void World_ODE_Frame_BodyToEntity(world_t *world, wedict_t *ed) Matrix4_Multiply(ed->ode.ode_offsetimatrix, bodymatrix, entitymatrix); Matrix3x4_RM_ToVectors(entitymatrix, forward, left, up, origin); - VectorAngles(forward, up, angles); - angles[0]*=-1; + VectorAngles(forward, up, angles, false); avelocity[PITCH] = RAD2DEG(spinvelocity[PITCH]); avelocity[YAW] = RAD2DEG(spinvelocity[ROLL]); avelocity[ROLL] = RAD2DEG(spinvelocity[YAW]); @@ -1495,8 +1495,8 @@ static void World_ODE_Frame_BodyToEntity(world_t *world, wedict_t *ed) model = world->Get_CModel(world, ed->v->modelindex); if (!model || model->type == mod_alias) { - angles[PITCH] *= -1; - avelocity[PITCH] *= -1; + angles[PITCH] *= r_meshpitch.value; + avelocity[PITCH] *= r_meshpitch.value; } } @@ -2321,8 +2321,8 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed) model = world->Get_CModel(world, ed->v->modelindex); if (!model || model->type == mod_alias) { - qangles[PITCH] *= -1; - qavelocity[PITCH] *= -1; + qangles[PITCH] *= r_meshpitch.value; + qavelocity[PITCH] *= r_meshpitch.value; } } @@ -2737,6 +2737,8 @@ static void QDECL World_ODE_Start(world_t *world) memset(ctx, 0, sizeof(*ctx)); world->rbe = &ctx->pub; + r_meshpitch.value = pCvar_GetFloat("physics_ode_quadtree_depth"); + VectorAvg(world->worldmodel->mins, world->worldmodel->maxs, center); VectorSubtract(world->worldmodel->maxs, center, extents); ctx->dworld = dWorldCreate(); diff --git a/engine/common/common.c b/engine/common/common.c index 05ad85576..1276ebadd 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -5531,6 +5531,8 @@ void COM_Init (void) Cvar_Register (&com_highlightcolor, "Internationalisation"); com_parseutf8.ival = 1; + Cvar_Register (&r_meshpitch, "Gamecode"); + TranslateInit(); COM_BiDi_Setup(); diff --git a/engine/common/fs.c b/engine/common/fs.c index 9fc2c168a..b45764c41 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1083,10 +1083,37 @@ static void FS_RebuildFSHash_Update(const char *fname) searchpath_t *search; int depth = 0; fsbucket_t *old; + void *filehandle = NULL; if (com_fschanged) return; + if (!filehandle && com_purepaths) + { //go for the pure paths first. + for (search = com_purepaths; search; search = search->nextpure) + { + if (search->handle->FindFile(search->handle, &loc, fname, NULL)) + { + filehandle = loc.fhandle; + break; + } + depth++; + } + } + if (!filehandle && fs_puremode < 2) + { + for (search = com_searchpaths ; search ; search = search->next) + { + if (search->handle->FindFile(search->handle, &loc, fname, NULL)) + { + filehandle = loc.fhandle; + break; + } + depth++; + } + } + + COM_WorkerFullSync(); if (!Sys_LockMutex(fs_thread_mutex)) return; //amg! @@ -1098,30 +1125,8 @@ static void FS_RebuildFSHash_Update(const char *fname) fs_hash_files--; } - if (com_purepaths) - { //go for the pure paths first. - for (search = com_purepaths; search; search = search->nextpure) - { - if (search->handle->FindFile(search->handle, &loc, fname, NULL)) - { - FS_AddFileHash(depth, fname, NULL, loc.fhandle); - return; - } - depth++; - } - } - if (fs_puremode < 2) - { - for (search = com_searchpaths ; search ; search = search->next) - { - if (search->handle->FindFile(search->handle, &loc, fname, NULL)) - { - FS_AddFileHash(depth, fname, NULL, loc.fhandle); - return; - } - depth++; - } - } + if (filehandle) + FS_AddFileHash(depth, fname, NULL, filehandle); Sys_UnlockMutex(fs_thread_mutex); } diff --git a/engine/common/log.c b/engine/common/log.c index ee43ff6d4..7fcd0657c 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -533,8 +533,10 @@ static void IPLog_Identify_f(void) Con_Printf("%s: ip address of %s is not known\n", Cmd_Argv(0), cl.players[slot].name); else { - NET_StringToAdr(cl.players[slot].ip, 0, &adr); - IPLog_Identify(&adr, NULL, "Identity of %s [%s]", cl.players[slot].name, cl.players[slot].ip); + if (NET_StringToAdrMasked(cl.players[slot].ip, false, &adr, &mask)) + IPLog_Identify(&adr, &mask, "Identity of %s [%s]", cl.players[slot].name, cl.players[slot].ip); + else + Con_Printf("ip address of %s not known, cannot identify\n", cl.players[slot].name); } } #endif diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index e2428abe5..bae1c9d38 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -291,7 +291,7 @@ void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up) CrossProduct(right, forward, up); } -void QDECL VectorAngles(float *forward, float *up, float *result) //up may be NULL +void QDECL VectorAngles(float *forward, float *up, float *result, qboolean meshpitch) //up may be NULL { float yaw, pitch, roll; @@ -331,9 +331,11 @@ void QDECL VectorAngles(float *forward, float *up, float *result) //up may be NU roll = 0; } - pitch *= -180 / M_PI; + pitch *= 180 / M_PI; yaw *= 180 / M_PI; roll *= 180 / M_PI; + if (meshpitch) + pitch *= r_meshpitch.value; if (pitch < 0) pitch += 360; if (yaw < 0) @@ -381,11 +383,6 @@ void QDECL AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3 } } -void QDECL vectoangles(vec3_t fwd, vec3_t ang) -{ - VectorAngles(fwd, NULL, ang); -} - int VectorCompare (const vec3_t v1, const vec3_t v2) { int i; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index acecd9432..3a70917fc 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -114,8 +114,6 @@ typedef struct { float m[4][4]; } matrix4x4_t; - - //vec_t _DotProduct (vec3_t v1, vec3_t v2); //void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out); //void _VectorCopy (vec3_t in, vec3_t out); @@ -123,7 +121,7 @@ typedef struct { void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); float anglemod (float a); void QDECL AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); -void QDECL VectorAngles (float *forward, float *up, float *angles); //up may be NULL +void QDECL VectorAngles (float *forward, float *up, float *angles, qboolean meshpitch); //up may be NULL void VARGS BOPS_Error (void); int VARGS BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane); void ClearBounds (vec3_t mins, vec3_t maxs); diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 0d7272130..701837072 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -138,8 +138,7 @@ static qboolean PM_PortalTransform(world_t *w, int portalnum, vec3_t org, vec3_t VectorCopy(pmove.angles, G_VECTOR(OFS_PARM1)); AngleVectors(pmove.angles, w->g.v_forward, w->g.v_right, w->g.v_up); PR_ExecuteProgram (w->progs, portal->xv->camera_transform); - VectorAngles(w->g.v_forward, w->g.v_up, newang); - newang[0] *= -1; + VectorAngles(w->g.v_forward, w->g.v_up, newang, false); } *w->g.self = oself; @@ -1155,11 +1154,11 @@ void PM_NudgePosition (void) if (PM_TestPlayerPosition (pmove.origin, false)) return; - for (z=0 ; zg.v_forward, src[0]); diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 90bd713a5..4d5e160d1 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -577,7 +577,7 @@ typedef struct void (QDECL *ReleaseCollisionMesh) (wedict_t *ed); void (QDECL *LinkEdict)(world_t *w, wedict_t *ed, qboolean touchtriggers); - void (QDECL *VectorAngles)(float *forward, float *up, float *result); + void (QDECL *VectorAngles)(float *forward, float *up, float *result, qboolean meshpitch); void (QDECL *AngleVectors)(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); } rbeplugfuncs_t; #define RBEPLUGFUNCS_VERSION 1 diff --git a/engine/common/world.h b/engine/common/world.h index 733a4b045..f5348d8d3 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -261,7 +261,7 @@ void World_RBE_Start(world_t *world); void World_RBE_Shutdown(world_t *world); -void World_ClearWorld (world_t *w); +void World_ClearWorld (world_t *w, qboolean relink); // called after the world model has been loaded, before linking any entities void World_UnlinkEdict (wedict_t *ent); diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 07aeffade..9dda6e643 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -363,7 +363,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext) Q_strncpyz(skin->mappings[skin->nummappings].surface, com_token, sizeof(skin->mappings[skin->nummappings].surface)); skintext = COM_ParseToken(skintext+1, NULL); Q_strncpyz(shadername, com_token, sizeof(shadername)); - skin->mappings[skin->nummappings].shader = R_RegisterSkin(shadername, skin->skinname); + skin->mappings[skin->nummappings].shader = R_RegisterCustom (shadername, 0, Shader_DefaultSkin, NULL); R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader); skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures; skin->nummappings++; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index e377af64d..a15260d47 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -4591,7 +4591,7 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ void GLBE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, vbo_t *vbo, unsigned int beflags) { shader->next = NULL; - BE_DrawMesh_List(shader, 1, &mesh, NULL, NULL, beflags); + GLBE_DrawMesh_List(shader, 1, &mesh, NULL, NULL, beflags); } void GLBE_SubmitBatch(batch_t *batch) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 0374a82b0..b83996817 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -635,6 +635,9 @@ void Mod_Purge(enum mod_purge_e ptype) { unused = mod->datasequence != mod_datasequence; + if (mod->loadstate == MLS_NOTLOADED) + continue; + //this model isn't active any more. if (unused || ptype != MP_MAPCHANGED) { @@ -904,7 +907,7 @@ model_t *Mod_FindName (const char *name) // search the currently loaded models // for (i=0 , mod=mod_known ; iname, name) ) + if (!strcmp (mod->publicname, name) ) break; if (i == mod_numknown) @@ -912,16 +915,17 @@ model_t *Mod_FindName (const char *name) #ifdef LOADERTHREAD Sys_LockMutex(com_resourcemutex); for (i=0 , mod=mod_known ; iname, name) ) + if (!strcmp (mod->publicname, name) ) break; if (i == mod_numknown) { #endif if (mod_numknown == MAX_MOD_KNOWN) Sys_Error ("mod_numknown == MAX_MOD_KNOWN"); - if (strlen(name) >= sizeof(mod->name)) + if (strlen(name) >= sizeof(mod->publicname)) Sys_Error ("model name is too long: %s", name); memset(mod, 0, sizeof(model_t)); //clear the old model as the renderers use the same globals + Q_strncpyz (mod->publicname, name, sizeof(mod->publicname)); Q_strncpyz (mod->name, name, sizeof(mod->name)); mod->loadstate = MLS_NOTLOADED; mod_numknown++; @@ -1143,7 +1147,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b) size_t filesize; char ext[8]; - if (!*mod->name) + if (!*mod->publicname) { mod->type = mod_dummy; mod->mins[0] = -16; @@ -1172,43 +1176,43 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b) // load the file // // set necessary engine flags for loading purposes - if (!strcmp(mod->name, "progs/player.mdl")) + if (!strcmp(mod->publicname, "progs/player.mdl")) mod->engineflags |= MDLF_PLAYER | MDLF_DOCRC; - else if (!strcmp(mod->name, "progs/flame.mdl") || - !strcmp(mod->name, "progs/flame2.mdl") || - !strcmp(mod->name, "models/flame1.mdl") || //hexen2 small standing flame - !strcmp(mod->name, "models/flame2.mdl") || //hexen2 large standing flame - !strcmp(mod->name, "models/cflmtrch.mdl")) //hexen2 wall torch + else if (!strcmp(mod->publicname, "progs/flame.mdl") || + !strcmp(mod->publicname, "progs/flame2.mdl") || + !strcmp(mod->publicname, "models/flame1.mdl") || //hexen2 small standing flame + !strcmp(mod->publicname, "models/flame2.mdl") || //hexen2 large standing flame + !strcmp(mod->publicname, "models/cflmtrch.mdl")) //hexen2 wall torch mod->engineflags |= MDLF_FLAME; - else if (!strcmp(mod->name, "progs/bolt.mdl") || - !strcmp(mod->name, "progs/bolt2.mdl") || - !strcmp(mod->name, "progs/bolt3.mdl") || - !strcmp(mod->name, "progs/beam.mdl") || - !strcmp(mod->name, "models/stsunsf2.mdl") || - !strcmp(mod->name, "models/stsunsf1.mdl") || - !strcmp(mod->name, "models/stice.mdl")) + else if (!strcmp(mod->publicname, "progs/bolt.mdl") || + !strcmp(mod->publicname, "progs/bolt2.mdl") || + !strcmp(mod->publicname, "progs/bolt3.mdl") || + !strcmp(mod->publicname, "progs/beam.mdl") || + !strcmp(mod->publicname, "models/stsunsf2.mdl") || + !strcmp(mod->publicname, "models/stsunsf1.mdl") || + !strcmp(mod->publicname, "models/stice.mdl")) mod->engineflags |= MDLF_BOLT; - else if (!strcmp(mod->name, "progs/backpack.mdl")) + else if (!strcmp(mod->publicname, "progs/backpack.mdl")) mod->engineflags |= MDLF_NOTREPLACEMENTS; - else if (!strcmp(mod->name, "progs/eyes.mdl")) + else if (!strcmp(mod->publicname, "progs/eyes.mdl")) mod->engineflags |= MDLF_NOTREPLACEMENTS|MDLF_DOCRC; /*handle ezquake-originated cheats that would feck over fte users if fte didn't support these are the conditions required for r_fb_models on non-players*/ mod->engineflags |= MDLF_EZQUAKEFBCHEAT; if ((mod->engineflags & MDLF_DOCRC) || - !strcmp(mod->name, "progs/backpack.mdl") || - !strcmp(mod->name, "progs/gib1.mdl") || - !strcmp(mod->name, "progs/gib2.mdl") || - !strcmp(mod->name, "progs/gib3.mdl") || - !strcmp(mod->name, "progs/h_player.mdl") || - !strncmp(mod->name, "progs/v_", 8)) + !strcmp(mod->publicname, "progs/backpack.mdl") || + !strcmp(mod->publicname, "progs/gib1.mdl") || + !strcmp(mod->publicname, "progs/gib2.mdl") || + !strcmp(mod->publicname, "progs/gib3.mdl") || + !strcmp(mod->publicname, "progs/h_player.mdl") || + !strncmp(mod->publicname, "progs/v_", 8)) mod->engineflags &= ~MDLF_EZQUAKEFBCHEAT; mod->engineflags |= MDLF_RECALCULATERAIN; // get string used for replacement tokens - COM_FileExtension(mod->name, ext, sizeof(ext)); + COM_FileExtension(mod->publicname, ext, sizeof(ext)); if (!Q_strcasecmp(ext, "spr") || !Q_strcasecmp(ext, "sp2")) replstr = ""; // sprite #ifdef DSPMODELS @@ -1225,7 +1229,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b) if (!gl_load24bit.value) replstr = ""; - COM_StripExtension(mod->name, mdlbase, sizeof(mdlbase)); + COM_StripExtension(mod->publicname, mdlbase, sizeof(mdlbase)); while (replstr) { @@ -1238,12 +1242,17 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b) Q_snprintfz(altname, sizeof(altname), "%s.%s", mdlbase, token); TRACE(("Mod_LoadModel: Trying to load (replacement) model \"%s\"\n", altname)); buf = (unsigned *)COM_LoadFile (altname, 5, &filesize); + + if (buf) + Q_strncpyz(mod->name, altname, sizeof(mod->name)); } else { - TRACE(("Mod_LoadModel: Trying to load model \"%s\"\n", mod->name)); - buf = (unsigned *)COM_LoadFile (mod->name, 5, &filesize); - if (!buf) + TRACE(("Mod_LoadModel: Trying to load model \"%s\"\n", mod->publicname)); + buf = (unsigned *)COM_LoadFile (mod->publicname, 5, &filesize); + if (buf) + Q_strncpyz(mod->name, mod->publicname, sizeof(mod->name)); + else if (!buf) { #ifdef DSPMODELS if (doomsprite) // special case needed for doom sprites @@ -5119,14 +5128,12 @@ TRACE(("LoadBrushModel %i\n", __LINE__)); char name[MAX_QPATH]; model_t *nextmod; -// if (isnotmap) - Q_snprintfz (name, sizeof(name), "*%i:%s", i+1, mod->name); -// else//FIXME: this can bug out if we've still got one of these queued from a previous map change -// Q_snprintfz (name, sizeof(name), "*%i", i+1); + Q_snprintfz (name, sizeof(name), "*%i:%s", i+1, mod->publicname); nextmod = Mod_FindName (name); *nextmod = *submod; nextmod->submodelof = mod; - Q_strncpyz(nextmod->name, name, sizeof(nextmod->name)); + Q_strncpyz(nextmod->publicname, name, sizeof(nextmod->publicname)); + Q_snprintfz (nextmod->name, sizeof(nextmod->publicname), "*%i:%s", i+1, mod->publicname); submod = nextmod; memset(&submod->memgroup, 0, sizeof(submod->memgroup)); } @@ -5162,6 +5169,26 @@ SPRITES //========================================================= +#ifdef SERVERONLY +//dedicated servers should not need to load sprites. +//dedicated servers need *.bsp to be loaded for setmodel to get the correct size (or all model types with sv_gameplayfix_setmodelrealbox). +//otherwise other model types(actually: names) only need to be loaded once reflection or hitmodel is used. +//for sprites we don't really care ever. +qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer, size_t fsize) +{ + mod->type = mod_dummy; + return true; +} +qboolean QDECL Mod_LoadSprite2Model (model_t *mod, void *buffer, size_t fsize) +{ + return Mod_LoadSpriteModel(mod, buffer, fsize); +} +void Mod_LoadDoomSprite (model_t *mod) +{ + mod->type = mod_dummy; +} +#else + //we need to override the rtlight shader for sprites so they get lit properly ignoring n+s+t dirs //so lets split the shader into parts to avoid too many dupes #define SPRITE_SHADER_MAIN \ @@ -5211,7 +5238,7 @@ void Mod_LoadSpriteFrameShader(model_t *spr, int frame, int subframe, mspritefra else Q_snprintfz(name, sizeof(name), "%s_%i_%i.tga", spr->name, frame, subframe); - if (mod_litsprites_force.ival || strchr(spr->name, '!')) + if (mod_litsprites_force.ival || strchr(spr->publicname, '!')) litsprite = true; #ifndef NOLEGACY else @@ -5231,7 +5258,7 @@ void Mod_LoadSpriteFrameShader(model_t *spr, int frame, int subframe, mspritefra }; for (i = 0; forcelitsprites[i]; i++) - if (!strcmp(spr->name, forcelitsprites[i])) + if (!strcmp(spr->publicname, forcelitsprites[i])) { litsprite = true; break; @@ -5867,6 +5894,8 @@ void Mod_LoadDoomSprite (model_t *mod) } #endif +#endif + //============================================================================= /* diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 001b860b2..8d889402a 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -855,7 +855,8 @@ enum }; typedef struct model_s { - char name[MAX_QPATH]; + char name[MAX_QPATH]; //actual name on disk + char publicname[MAX_QPATH]; //name that the gamecode etc sees int datasequence; int loadstate;//MLS_ qboolean tainted; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 5f01a2c80..edcd3d42b 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -1179,7 +1179,7 @@ void R_SaveRTLights_f(void) continue; if (!light->radius) continue; - VectorAngles(light->axis[0], light->axis[2], ang); + VectorAngles(light->axis[0], light->axis[2], ang, false); VFS_PUTS(f, va( "%s%f %f %f " "%f %f %f %f " @@ -1194,7 +1194,7 @@ void R_SaveRTLights_f(void) light->radius, light->color[0], light->color[1], light->color[2], light->style-1, light->cubemapname, light->corona, - anglemod(-ang[0]), ang[1], ang[2], + ang[0], ang[1], ang[2], light->coronascale, light->lightcolourscales[0], light->lightcolourscales[1], light->lightcolourscales[2], light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE|LFLAG_CREPUSCULAR), light->rotation[0],light->rotation[1],light->rotation[2],light->fov )); diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index c33080956..4fe45fa67 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1229,8 +1229,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], //now determine the stuff the backend will use. memcpy(r_refdef.m_view, vmat, sizeof(float)*16); - VectorAngles(vpn, vup, r_refdef.viewangles); - r_refdef.viewangles[0] *= -1; + VectorAngles(vpn, vup, r_refdef.viewangles, false); VectorCopy(r_refdef.vieworg, r_origin); //determine r_refdef.flipcull & SHADER_CULL_FLIP based upon whether right is right or not. diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 577b8eb7d..5bd4c8e8d 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -2261,6 +2261,8 @@ static void Shader_DiffuseMap(shader_t *shader, shaderpass_t *pass, char **ptr) char *token = Shader_ParseString(ptr); unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); shader->defaulttextures->base = Shader_FindImage(token, flags); + + Q_strncpyz(shader->defaulttextures->mapname, token, sizeof(shader->defaulttextures->mapname)); } static void Shader_SpecularMap(shader_t *shader, shaderpass_t *pass, char **ptr) { @@ -2272,7 +2274,7 @@ static void Shader_NormalMap(shader_t *shader, shaderpass_t *pass, char **ptr) { char *token = Shader_ParseString(ptr); unsigned int flags = Shader_SetImageFlags (shader, NULL, &token); - shader->defaulttextures->bump = Shader_FindImage(token, flags); + shader->defaulttextures->bump = Shader_FindImage(token, flags|IF_TRYBUMP); } static void Shader_FullbrightMap(shader_t *shader, shaderpass_t *pass, char **ptr) { @@ -3889,6 +3891,7 @@ void Shader_FixupProgPasses(shader_t *shader, shaderpass_t *pass) parsestate.droppass = true; break; } + pass[pass->numMergedPasses].flags |= SHADER_PASS_NOCOLORARRAY; pass[pass->numMergedPasses].flags &= ~SHADER_PASS_DEPTHCMP; if (defaulttgen[i].gen == T_GEN_SHADOWMAP) pass[pass->numMergedPasses].flags |= SHADER_PASS_DEPTHCMP; diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 0d2841bf1..c09bf8601 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -652,6 +652,7 @@ cin_t *R_ShaderGetCinematic(shader_t *s); cin_t *R_ShaderFindCinematic(const char *name); shader_t *R_ShaderFind(const char *name); //does NOT increase the shader refcount. +void Shader_DefaultSkin(const char *shortname, shader_t *s, const void *args); void Shader_DefaultSkinShell(const char *shortname, shader_t *s, const void *args); void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args); void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args); diff --git a/engine/nacl/snd_ppapi.c b/engine/nacl/snd_ppapi.c index 9fca7e7d6..5a176032f 100644 --- a/engine/nacl/snd_ppapi.c +++ b/engine/nacl/snd_ppapi.c @@ -53,7 +53,7 @@ static void PPAPI_UnlockBuffer(soundcardinfo_t *sc, void *buffer) static void *PPAPI_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx) { *sampidx = 0; - return sc->sn.buffer; + return sc->sn.buffer; } static void PPAPI_Submit(soundcardinfo_t *sc, int start, int end) diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 885cc0554..6a8d11bf0 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -2450,6 +2450,7 @@ void PR_CleanUpStatements16(progfuncs_t *progfuncs, dstatement16_t *st, pbool he if (!st[i].c) st[i].c = OFS_RETURN; + //sanitise inputs if (st[i].a >= numglob) if (st[i].op != OP_GOTO) st[i].op = ~0; @@ -2477,6 +2478,7 @@ void PR_CleanUpStatements32(progfuncs_t *progfuncs, dstatement32_t *st, pbool he if (!st[i].c) st[i].c = OFS_RETURN; + //sanitise inputs if (st[i].a >= numglob) if (st[i].op != OP_GOTO) st[i].op = ~0; @@ -2484,10 +2486,10 @@ void PR_CleanUpStatements32(progfuncs_t *progfuncs, dstatement32_t *st, pbool he if (st[i].op != OP_IFNOT_I && st[i].op != OP_IF_I && st[i].op != OP_IFNOT_F && st[i].op != OP_IF_F && st[i].op != OP_IFNOT_S && st[i].op != OP_IF_S && - st[i].op != OP_BOUNDCHECK) + st[i].op != OP_BOUNDCHECK && st[i].op != OP_CASE) st[i].op = ~0; if (st[i].c >= numglob) - if (st[i].op != OP_BOUNDCHECK) + if (st[i].op != OP_BOUNDCHECK && st[i].op != OP_CASERANGE) st[i].op = ~0; } } @@ -3300,12 +3302,6 @@ retry: ((int *)glob)[d16->ofs] = PR_FindFunc(&progfuncs->funcs, s, PR_ANY); if (!((int *)glob)[d16->ofs]) printf("Warning: Runtime-linked function %s could not be found (loading %s)\n", s, filename); - /* - d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function); - if (!d2) - Sys_Error("Runtime-linked function %s was not found in primary progs (loading %s)", s, filename); - ((int *)glob)[d16->ofs] = (*(func_t *)&pr_progstate[0].globals[*d2]); - */ s+=strlen(s)+1; } } @@ -3320,18 +3316,17 @@ retry: for (i = 0; i < pr_progs->numbodylessfuncs; i++) { d32 = ED_FindGlobal32(progfuncs, s); - d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function); - if (!d2) - printf("Warning: Runtime-linked function %s was not found in existing progs", s); if (!d32) { - printf("Couldn't find def for \"%s\"", s); + printf("\"%s\" requires the external function \"%s\", but the definition was stripped\n", filename, s); PRHunkFree(progfuncs, hmark); pr_progs=NULL; return false; } - ((int *)glob)[d32->ofs] = (*(func_t *)&pr_progstate[0].globals[*d2]); + ((int *)glob)[d32->ofs] = PR_FindFunc(&progfuncs->funcs, s, PR_ANY); + if (!((int *)glob)[d32->ofs]) + printf("Warning: Runtime-linked function %s could not be found (loading %s)\n", s, filename); s+=strlen(s)+1; } } diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index c60a66937..bb444e370 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -349,14 +349,14 @@ typedef struct QCC_type_s unsigned int size; pbool typedefed:1; - pbool vargs:1; - pbool vargcount:1; + pbool vargs:1; //function has vargs + pbool vargcount:1; //function has special varg count param char *name; char *aname; struct accessor_s *accessors; - struct QCC_type_s *ptrto; //this points to a type that is a pointer back to this type. yeah, weird. + struct QCC_type_s *ptrto; //(cache) this points to a type that is a pointer back to this type. yeah, weird. } QCC_type_t; int typecmp(QCC_type_t *a, QCC_type_t *b); int typecmp_lax(QCC_type_t *a, QCC_type_t *b); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 771d8ce25..0fb72fabb 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1521,7 +1521,7 @@ const QCC_eval_t *QCC_SRef_EvalConst(QCC_sref_t ref) if (ref.sym && ref.sym->initialized && ref.sym->constant) { ref.sym->referenced = true; - return &ref.sym->symboldata[/*ref.sym->ofs +*/ ref.ofs]; + return &ref.sym->symboldata[ref.ofs]; } return NULL; } @@ -1707,6 +1707,7 @@ static void QCC_ClobberDef(QCC_def_t *def) if (statements[st].c.sym == a) statements[st].c.sym = a->generatedfor; } + tmp.sym->refcount = a->symbolheader->refcount; a->symbolheader = tmp.sym; from = QCC_MakeSRefForce(a->generatedfor, 0, a->type); a->generatedfor = tmp.sym; @@ -1714,7 +1715,6 @@ static void QCC_ClobberDef(QCC_def_t *def) a->temp = tmp.sym->temp; a->ofs = tmp.sym->ofs; tmp.sym = a; - tmp.sym->refcount = a->refcount; if (a->type->type==ev_variant || a->type->type == ev_vector) QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_V], from, tmp, NULL, STFL_PRESERVEB)); else @@ -5236,7 +5236,10 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func, if (callconvention == OP_CALL1H) { for (i = 0; i < parm && i < 2; i++) + { + args[i].ref.sym->referenced=true; QCC_FreeTemp(args[i].ref); + } } //we dont need to lock the local containing the function index because its thrown away after the call anyway @@ -6099,7 +6102,7 @@ QCC_sref_t QCC_MakeIntConst(int value) continue; typechecks++; - if ( cn->symboldata[cn->ofs]._int == value ) + if ( cn->symboldata[0]._int == value ) { return QCC_MakeSRefForce(cn, 0, type_integer); } @@ -6526,7 +6529,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype) pr.local_tail = &pr.local_head; scope->initialized = true; - scope->symboldata[scope->ofs].function = pr_scope - functions; + scope->symboldata[0].function = pr_scope - functions; ed = QCC_PR_GetSRef(type_entity, "self", NULL, true, 0, false); @@ -6760,7 +6763,8 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a if (idx.cast) allowarray = arraysize>0 || (t->type == ev_vector) || - (t->type == ev_field && t->aux_type->type == ev_vector); + (t->type == ev_field && t->aux_type->type == ev_vector) || + (t->type == ev_union && t->num_parms == 1 && !t->params[0].paramname && !arraysize); else if (!idx.cast) { allowarray = arraysize>0 || @@ -6792,6 +6796,11 @@ QCC_ref_t *QCC_PR_ParseRefArrayPointer (QCC_ref_t *retbuf, QCC_ref_t *r, pbool a /*if its a pointer that got dereferenced, follow the type*/ if (!idx.cast && t->type == ev_pointer && !arraysize) t = t->aux_type; + else if (idx.cast && (t->type == ev_union && t->num_parms == 1 && !t->params[0].paramname && !arraysize)) + { + arraysize = t->params[0].arraysize; + t = t->params[0].type; + } if (!idx.cast && r->cast->type == ev_pointer && !arraysize) { @@ -7757,6 +7766,7 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags) QCC_PR_Expect ("]"); QCC_PR_Expect(")"); QCC_PR_Expect("{"); + QCC_PR_Expect ("}"); return array; }*/ @@ -10213,6 +10223,7 @@ void QCC_PR_ParseStatement (void) conditional = 1; e = QCC_PR_Expression (TOP_PRIORITY, 0); conditional = 0; + e.sym->referenced = true; //expands @@ -11512,7 +11523,7 @@ void QCC_Marshal_Locals(int firststatement, int laststatement) { //FIXME: check for uninitialised locals. //these matter when the function goes recursive (and locals marshalling counts as recursive every time). - if (local->symboldata[local->ofs]._int) + if (local->symboldata[0]._int) { QCC_PR_Note(ERR_INTERNAL, local->filen, local->s_line, "Marshaling non-const initialised %s", local->name); error = true; @@ -11712,7 +11723,7 @@ void QCC_WriteAsmFunction(QCC_function_t *sc, unsigned int firststatement, QCC_d } #endif -QCC_function_t *QCC_PR_GenerateBuiltinFunction (QCC_def_t *def, int builtinnum) +QCC_function_t *QCC_PR_GenerateBuiltinFunction (QCC_def_t *def, int builtinnum, char *builtinname) { QCC_function_t *func; if (numfunctions >= MAX_FUNCTIONS) @@ -11721,7 +11732,13 @@ QCC_function_t *QCC_PR_GenerateBuiltinFunction (QCC_def_t *def, int builtinnum) func->filen = s_filen; func->s_filed = s_filed; func->line = def->s_line; //FIXME - func->name = def->name; + if (builtinname==def->name) + func->name = builtinname; + else + { + func->name = qccHunkAlloc(strlen(builtinname)+1); + strcpy(func->name, builtinname); + } func->builtin = builtinnum; func->code = -1; func->type = def->type; @@ -11806,7 +11823,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ binum = pr_immediate._int; else QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate"); - f = QCC_PR_GenerateBuiltinFunction(def, binum); + f = QCC_PR_GenerateBuiltinFunction(def, binum, def->name); QCC_PR_Lex (); return f; @@ -11817,7 +11834,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ || pr_immediate_type != type_float || pr_immediate._float != (int)pr_immediate._float) QCC_PR_ParseError (ERR_BADBUILTINIMMEDIATE, "Bad builtin immediate"); - f = QCC_PR_GenerateBuiltinFunction(def, (int)-pr_immediate._float); + f = QCC_PR_GenerateBuiltinFunction(def, (int)-pr_immediate._float, def->name); QCC_PR_Lex (); QCC_PR_Expect(";"); @@ -11949,6 +11966,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ { a.sym = &def_parms[u]; a.ofs = 0; + QCC_ForceUnFreeDef(a.sym); } a.cast = type_vector; QCC_UnFreeTemp(va_list); @@ -12210,7 +12228,7 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_sref_t array) pr_source_line = pr_token_line_last = pr_scope->line = array.sym->s_line; //thankfully these functions are emitted after compilation. pr_scope->filen = array.sym->filen; pr_scope->s_filed = array.sym->s_filed; - func->symboldata[func->ofs]._int = pr_scope - functions; + func->symboldata[0]._int = pr_scope - functions; index = QCC_PR_GetSRef(type_float, "index___", pr_scope, true, 0, false); index.sym->referenced = true; @@ -12271,7 +12289,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, false); scope->initialized = true; - scope->symboldata[scope->ofs]._int = pr_scope - functions; + scope->symboldata[0]._int = pr_scope - functions; /* if (fasttrackpossible) { @@ -12457,7 +12475,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, false); scope->initialized = true; - scope->symboldata[scope->ofs]._int = pr_scope - functions; + scope->symboldata[0]._int = pr_scope - functions; if (fasttrackpossible.cast) { @@ -12620,7 +12638,10 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope, } if (flags & GDF_USED) + { def->used = true; + def->referenced = true; + } def->ofs = ofs + ((a>0)?type->size*a:0); if (!first) @@ -13066,7 +13087,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, QCC_function_t *scope, int arr def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved); if (parttype->type == ev_function) def->initialized = true; - def->symboldata[def->ofs]._int = *fieldofs; + def->symboldata[0]._int = *fieldofs; *fieldofs += parttype->size; } else @@ -13191,9 +13212,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d { if (functions[i].code == -1 && functions[i].builtin == binum) { - if (!*functions[i].name) - functions[i].name = (char*)defname; - if (!strcmp(functions[i].name, defname)) + if (!*functions[i].name || !strcmp(functions[i].name, defname)) { tmp = QCC_MakeIntConst(i); break; @@ -13204,7 +13223,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d } if (!tmp.cast) - f = QCC_PR_GenerateBuiltinFunction(def.sym, binum); + f = QCC_PR_GenerateBuiltinFunction(def.sym, binum, *fname?fname:def.sym->name); else f = NULL; } @@ -13313,7 +13332,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d QCC_PR_Lex(); QCC_PR_Expect(")"); } - else if ((type->type == ev_struct || type->type == ev_union) && QCC_PR_CheckToken("{")) + else if ((type->type == ev_struct && QCC_PR_CheckToken("{")) || (type->type == ev_union && ((type->num_parms == 1 && !type->params->paramname) || QCC_PR_CheckToken("{")))) { //structs go recursive unsigned int partnum; @@ -13332,12 +13351,55 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d QCC_PR_ParseInitializerType((type)->params[partnum].arraysize, basedef, def, flags); if (isunion || !QCC_PR_CheckToken(",")) { + if (isunion && (type->num_parms == 1 && !type->params->paramname)) + break; QCC_PR_Expect("}"); break; } } return; } + else if (type->type == ev_pointer && QCC_PR_CheckToken("{")) + { + //generate a temp array + QCC_ref_t buf, buf2; + tmp.sym = QCC_PR_DummyDef(type->aux_type, NULL, pr_scope, 0, NULL, 0, false, GDF_STRIP|(pr_scope?GDF_STATIC:0)); + tmp.ofs = 0; + tmp.cast = tmp.sym->type; + + tmp.sym->refcount+=1; + + //fill up the array + do + { + //expand the array + int newsize = tmp.sym->arraysize * tmp.cast->size; + if (tmp.sym->symbolsize < newsize) + { + void *newdata; + newsize += 64 * tmp.cast->size; + newdata = qccHunkAlloc (newsize * sizeof(float)); + memcpy(newdata, tmp.sym->symboldata, tmp.sym->symbolsize*sizeof(float)); + tmp.sym->symboldata = newdata; + tmp.sym->symbolsize = newsize; + } + tmp.sym->arraysize++; + //generate the def... + QCC_PR_DummyDef(tmp.cast, NULL, pr_scope, 0, tmp.sym, tmp.ofs, false, GDF_STRIP|(pr_scope?GDF_STATIC:0)); + + //and fill it in. + QCC_PR_ParseInitializerType(0, tmp.sym, tmp, flags); + tmp.ofs += type->aux_type->size; + } while(QCC_PR_CheckToken(",")); + QCC_PR_Expect("}"); + + //drop the size back down to something sane + tmp.sym->symbolsize = tmp.ofs*sizeof(float); + + //grab the address of it. + tmp.ofs = 0; + tmp = QCC_RefToDef(QCC_PR_GenerateAddressOf(&buf, QCC_DefToRef(&buf2, tmp)), true); + } else { tmp = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); @@ -13652,24 +13714,40 @@ void QCC_PR_ParseDefs (char *classname) if (QCC_PR_CheckKeyword (keyword_typedef, "typedef")) { - type = QCC_PR_ParseType(true, false); + type = QCC_PR_ParseType(false, false); if (!type) { QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens"); } - if (QCC_PR_CheckToken("*")) + do { - QCC_type_t *ptr; - ptr = QCC_PR_NewType(QCC_CopyString(pr_token)+strings, ev_pointer, false); - ptr->aux_type = type; - type = ptr; - } - else - { - type->name = QCC_CopyString(pr_token)+strings; - } - type->typedefed = true; - QCC_PR_Lex(); + char *name; + if (QCC_PR_CheckToken(";")) + return; + + if (QCC_PR_CheckToken("*")) + type = QCC_PointerTypeTo(type); + + name = QCC_PR_ParseName(); + + if (QCC_PR_CheckToken("[")) + { + struct QCC_typeparam_s *param = qccHunkAlloc(sizeof(*param)); + param->type = type; + param->arraysize = QCC_PR_IntConstExpr(); + type = QCC_PR_NewType(name, ev_union, true); + type->params = param; + type->num_parms = 1; + type->size = param->type->size * param->arraysize; + QCC_PR_Expect("]"); + } + else + { + type = QCC_PR_DuplicateType(type, false); + type->name = name; + type->typedefed = true; + } + } while(QCC_PR_CheckToken(",")); QCC_PR_Expect(";"); return; } @@ -13745,7 +13823,7 @@ void QCC_PR_ParseDefs (char *classname) def = QCC_PR_GetDef(type_float, name, NULL, true, 0, true); if (QCC_PR_CheckToken("=")) { - def->symboldata[def->ofs]._float = pr_immediate._float; + def->symboldata[0]._float = pr_immediate._float; QCC_PR_Lex(); } } @@ -13755,11 +13833,11 @@ void QCC_PR_ParseDefs (char *classname) if (QCC_PR_CheckToken("=")) { QCC_PR_Expect("["); - def->symboldata[def->ofs].vector[0] = pr_immediate._float; + def->symboldata[0].vector[0] = pr_immediate._float; QCC_PR_Lex(); - def->symboldata[def->ofs].vector[1] = pr_immediate._float; + def->symboldata[0].vector[1] = pr_immediate._float; QCC_PR_Lex(); - def->symboldata[def->ofs].vector[2] = pr_immediate._float; + def->symboldata[0].vector[2] = pr_immediate._float; QCC_PR_Lex(); QCC_PR_Expect("]"); } @@ -13814,12 +13892,12 @@ void QCC_PR_ParseDefs (char *classname) def->initialized = 1; for (u = 0; u < def->type->size*(def->arraysize?def->arraysize:1); u++) //make arrays of fields work. { - if (*(int *)&def->symboldata[def->ofs+u]) + if (*(int *)&def->symboldata[u]) { QCC_PR_ParseWarning(0, "Field def already has a value:"); QCC_PR_ParsePrintDef(0, def); } - *(int *)&def->symboldata[def->ofs+u] = pr.size_fields+u; + *(int *)&def->symboldata[u] = pr.size_fields+u; } pr.size_fields += u; @@ -13936,7 +14014,7 @@ void QCC_PR_ParseDefs (char *classname) def->initialized = 1; def->isstatic = isstatic; - def->symboldata[def->ofs].function = numfunctions; + def->symboldata[0].function = numfunctions; f->def = def; // if (pr_dumpasm) // PR_PrintFunction (def); @@ -14162,7 +14240,7 @@ void QCC_PR_ParseDefs (char *classname) { d = d->next; d->initialized = 1; //fake function - d->symboldata[d->ofs].function = 0; + d->symboldata[0].function = 0; } continue; @@ -14277,11 +14355,11 @@ void QCC_PR_ParseDefs (char *classname) def->initialized = true; //if the field already has a value, don't allocate new field space for it as that would confuse things. //otherwise allocate new space. - if (def->symboldata[def->ofs]._int) + if (def->symboldata[0]._int) { for (i = 0; i < type->size*(arraysize?arraysize:1); i++) //make arrays of fields work. { - if (def->symboldata[def->ofs+i]._int != i + def->symboldata[def->ofs]._int) + if (def->symboldata[i]._int != i + def->symboldata[0]._int) { QCC_PR_ParseWarning(0, "Inconsistant field def:"); QCC_PR_ParsePrintDef(0, def); @@ -14293,12 +14371,12 @@ void QCC_PR_ParseDefs (char *classname) { for (i = 0; i < type->size*(arraysize?arraysize:1); i++) //make arrays of fields work. { - if (def->symboldata[def->ofs+i]._int) + if (def->symboldata[i]._int) { QCC_PR_ParseWarning(0, "Field def already has a value:"); QCC_PR_ParsePrintDef(0, def); } - def->symboldata[def->ofs+i]._int = pr.size_fields+i; + def->symboldata[i]._int = pr.size_fields+i; } pr.size_fields += i; diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 6ebb82dee..711f64d4a 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -4428,6 +4428,7 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) { do { + pbool foundinout; if (ftype->num_parms>=MAX_PARMS+MAX_EXTRA_PARMS) QCC_PR_ParseError(ERR_TOOMANYTOTALPARAMETERS, "Too many parameters. Sorry. (limit is %i)\n", MAX_PARMS+MAX_EXTRA_PARMS); @@ -4437,16 +4438,30 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) break; } - if (QCC_PR_CheckKeyword(keyword_inout, "inout")) - paramlist[numparms].out = true; - else if (QCC_PR_CheckKeyword(keyword_inout, "out")) - paramlist[numparms].out = 2; //not really supported, but parsed for readability. - else if (QCC_PR_CheckKeyword(keyword_inout, "in")) - paramlist[numparms].out = false; - else - paramlist[numparms].out = false; //the default + foundinout = false; + paramlist[numparms].optional = false; + paramlist[numparms].out = false; - paramlist[numparms].optional = QCC_PR_CheckKeyword(keyword_optional, "optional"); + while(1) + { + if (!paramlist[numparms].optional && QCC_PR_CheckKeyword(keyword_optional, "optional")) + paramlist[numparms].optional = true; + if (!foundinout && QCC_PR_CheckKeyword(keyword_inout, "inout")) + { + paramlist[numparms].out = true; + foundinout = true; + } + if (!foundinout && QCC_PR_CheckKeyword(keyword_inout, "out")) + { + paramlist[numparms].out = 2; //not really supported, but parsed for readability. + foundinout = true; + } + if (!foundinout && QCC_PR_CheckKeyword(keyword_inout, "in")) + { + paramlist[numparms].out = false; + foundinout = true; + } + } paramlist[numparms].defltvalue.cast = NULL; paramlist[numparms].ofs = 0; @@ -4455,6 +4470,9 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) if (!paramlist[numparms].type) QCC_PR_ParseError(0, "Expected type\n"); + while (QCC_PR_CheckToken("*")) + paramlist[numparms].type = QCC_PointerTypeTo(paramlist[numparms].type); + if (paramlist[numparms].type->type == ev_void) break; //float(void) has no actual args @@ -4474,6 +4492,12 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) strcpy(paramlist[numparms].paramname, name); if (definenames) strcpy (pr_parm_names[numparms], name); + + if (QCC_PR_CheckToken("[")) + { + QCC_PR_ParseError(0, "Array arguments are not supported\n"); + QCC_PR_Expect("]"); + } } else if (definenames) strcpy (pr_parm_names[numparms], ""); diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index 0210db7a5..158dae63e 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -99,6 +99,7 @@ void AddSourceFile(const char *parentsrc, const char *filename); #define SCI_BACKTAB 2328 #define SCI_SEARCHANCHOR 2366 #define SCI_SEARCHNEXT 2367 +#define SCI_SEARCHPREV 2368 #define SCI_STYLEGETFORE 2481 #define SCI_STYLEGETBACK 2482 #define SCI_STYLEGETBOLD 2483 @@ -748,12 +749,12 @@ void GUI_DialogPrint(char *title, char *text) MessageBox(mainwindow, text, title, 0); } -static void FindNextScintilla(editor_t *editor, char *findtext) +static void FindNextScintilla(editor_t *editor, char *findtext, pbool next) { int pos = SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0); Edit_SetSel(editor->editpane, pos+1, pos+1); SendMessage(editor->editpane, SCI_SEARCHANCHOR, 0, 0); - if (SendMessage(editor->editpane, SCI_SEARCHNEXT, 0, (LPARAM)findtext) != -1) + if (SendMessage(editor->editpane, next?SCI_SEARCHNEXT:SCI_SEARCHPREV, 0, (LPARAM)findtext) != -1) Edit_ScrollCaret(editor->editpane); //make sure its focused else { @@ -807,33 +808,6 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l break; } } - if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN) - { - switch(wParam) - { - case VK_F3: - { - char buffer[128]; - GetWindowText(search_name, buffer, sizeof(buffer)); - if (*buffer == 0) - SetFocus(search_name); - else - { - editor_t *editor; - for (editor = editors; editor; editor = editor->next) - { - if (editor->editpane == hWnd) - break; - } - if (editor && editor->scintilla) - { - FindNextScintilla(editor, buffer); - } - } - } - return 0; - } - } if (uMsg == WM_LBUTTONDBLCLK && hWnd == outputbox) { CHARRANGE selrange = {0}; @@ -1303,6 +1277,8 @@ enum { IDM_SAVE, IDM_RECOMPILE, IDM_FIND, + IDM_FINDNEXT, + IDM_FINDPREV, IDM_QUIT, IDM_UNDO, IDM_REDO, @@ -1726,6 +1702,29 @@ void EditorMenu(editor_t *editor, WPARAM wParam) case IDM_FIND: SetFocus(search_name); break; + case IDM_FINDNEXT: + case IDM_FINDPREV: + { + char buffer[128]; + GetWindowText(search_name, buffer, sizeof(buffer)); + if (*buffer != 0) + { + HWND ew = (HWND)SendMessage(mdibox, WM_MDIGETACTIVE, 0, 0); + editor_t *editor; + for (editor = editors; editor; editor = editor->next) + { + if (editor->window == ew) + break; + } + if (editor && editor->scintilla) + { + FindNextScintilla(editor, buffer, LOWORD(wParam) == IDM_FINDNEXT); + SetFocus(editor->window); + SetFocus(editor->editpane); + } + } + } + break; case IDM_GREP: { char buffer[1024]; @@ -5253,33 +5252,11 @@ static LRESULT CALLBACK SearchComboSubClass(HWND hWnd,UINT message, { case WM_KEYDOWN: switch (wParam) - { + { case VK_RETURN: PostMessage(mainwindow, WM_COMMAND, 0x4404, (LPARAM)search_gotodef); return true; - case VK_F3: - { - char buffer[128]; - GetWindowText(search_name, buffer, sizeof(buffer)); - if (*buffer != 0) - { - HWND ew = (HWND)SendMessage(mdibox, WM_MDIGETACTIVE, 0, 0); - editor_t *editor; - for (editor = editors; editor; editor = editor->next) - { - if (editor->window == ew) - break; - } - if (editor && editor->scintilla) - { - FindNextScintilla(editor, buffer); - SetFocus(editor->window); - SetFocus(editor->editpane); - } - } - } - } - break; + } } return CallWindowProc(combosubclassproc, hWnd, message, wParam, lParam); } @@ -6488,6 +6465,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin {FCONTROL|FVIRTKEY, 'F', IDM_FIND}, {FCONTROL|FVIRTKEY, 'G', IDM_GREP}, {FCONTROL|FVIRTKEY, 'R', IDM_RECOMPILE}, + {FVIRTKEY, VK_F3, IDM_FINDNEXT}, + {FSHIFT|FVIRTKEY, VK_F3, IDM_FINDPREV}, // {FVIRTKEY, VK_F4, IDM_NEXTERROR}, {FVIRTKEY, VK_F5, IDM_DEBUG_RUN}, {FVIRTKEY, VK_F6, IDM_OUTPUT_WINDOW}, diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 9cef0f2da..47aa1ef01 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -923,11 +923,14 @@ void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym) for (; sym; sym = sym->next) { if (sym->constant && sym->type->type == ev_field && !opt_stripunusedfields) + { sym->symbolheader->used = true; //fields should always be present, annoyingly enough, as they're often used to silence map warnings. //FIXME: we want to strip these. fte/dp extensions.qc have a LOT of fields that could be stripped. + sym->referenced = true; //FIXME + } else if (sym->constant && sym->type->type == ev_function) { //non-builtins must be present, because of spawn functions and other entrypoints. - unsigned int fnum = sym->symboldata[sym->ofs]._int; + unsigned int fnum = sym->symboldata[0]._int; if (fnum < numfunctions && functions[fnum].code == -1) sym->symbolheader->used = true; } @@ -1074,8 +1077,8 @@ void QCC_FinaliseDef(QCC_def_t *def) else memset(qcc_pr_globals+def->ofs, 0, def->symbolsize*sizeof(float)); } - def->symboldata = qcc_pr_globals; - def->symbolsize = numpr_globals; + def->symboldata = qcc_pr_globals + def->ofs; + def->symbolsize = numpr_globals - def->ofs; #ifdef DEBUG_DUMP if (!def->referenced) @@ -1187,7 +1190,7 @@ static void QCC_GenerateFieldDefs(QCC_def_t *def, char *fieldname, int ofs, QCC_ dd = &qcc_globals[numglobaldefs]; numglobaldefs++; dd->type = ev_field; - dd->ofs = ofs; + dd->ofs = def->ofs+ofs; dd->s_name = sname; } @@ -1519,13 +1522,13 @@ pbool QCC_WriteData (int crc) if (def->symbolheader->read && !def->symbolheader->written && !def->symbolheader->referenced) { char typestr[256]; - QCC_sref_t sr = {def, def->ofs, def->type}; + QCC_sref_t sr = {def, 0, def->type}; QCC_PR_Warning(WARN_READNOTWRITTEN, def->filen, def->s_line, "%s %s = %s read, but not writte.", TypeName(def->type, typestr, sizeof(typestr)), def->name, QCC_VarAtOffset(sr)); } if (def->symbolheader->written && !def->symbolheader->read && !def->symbolheader->referenced) { char typestr[256]; - QCC_sref_t sr = {def, def->ofs, def->type}; + QCC_sref_t sr = {def, 0, def->type}; QCC_PR_Warning(WARN_WRITTENNOTREAD, def->filen, def->s_line, "%s %s = %s written, but not read.", TypeName(def->type, typestr, sizeof(typestr)), def->name, QCC_VarAtOffset(sr)); } #endif @@ -1553,7 +1556,7 @@ pbool QCC_WriteData (int crc) if (def->symbolheader->used) { char typestr[256]; - QCC_sref_t sr = {def, def->ofs, def->type}; + QCC_sref_t sr = {def, 0, def->type}; QCC_PR_Warning(WARN_NOTREFERENCED, def->filen, def->s_line, "%s %s = %s used, but not referenced.", TypeName(def->type, typestr, sizeof(typestr)), def->name, QCC_VarAtOffset(sr)); } /*if (opt_unreferenced && def->type->type != ev_field) @@ -1585,7 +1588,7 @@ pbool QCC_WriteData (int crc) if (def->type->type == ev_function) { - if (opt_function_names && def->initialized && functions[def->symboldata[def->ofs].function].code<0) + if (opt_function_names && def->initialized && functions[def->symboldata[0].function].code<0) { optres_function_names++; def->name = ""; @@ -1610,7 +1613,7 @@ pbool QCC_WriteData (int crc) } else if (def->type->type == ev_field && def->constant && (!def->scope || def->isstatic || def->initialized)) { - QCC_GenerateFieldDefs(def, def->name, def->ofs, def->type->aux_type); + QCC_GenerateFieldDefs(def, def->name, 0, def->type->aux_type); continue; } else if ((def->scope||def->constant) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings))) @@ -1664,17 +1667,17 @@ pbool QCC_WriteData (int crc) #ifdef DEBUG_DUMP if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_string) - printf("code: %s:%i: %s%s%s %s@%i = \"%s\"\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, ((unsigned)def->symboldata[def->ofs].string>=(unsigned)strofs)?"???":(strings + def->symboldata[def->ofs].string)); + printf("code: %s:%i: %s%s%s %s@%i = \"%s\"\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, ((unsigned)def->symboldata[0].string>=(unsigned)strofs)?"???":(strings + def->symboldata[0].string)); else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_float) - printf("code: %s:%i: %s%s%s %s@%i = %g\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._float); + printf("code: %s:%i: %s%s%s %s@%i = %g\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[0]._float); else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_integer) - printf("code: %s:%i: %s%s%s %s@%i = %i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._int); + printf("code: %s:%i: %s%s%s %s@%i = %i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[0]._int); else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_vector) - printf("code: %s:%i: %s%s%s %s@%i = '%g %g %g'\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs].vector[0], def->symboldata[def->ofs].vector[1], def->symboldata[def->ofs].vector[2]); + printf("code: %s:%i: %s%s%s %s@%i = '%g %g %g'\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[0].vector[0], def->symboldata[0].vector[1], def->symboldata[0].vector[2]); else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_function) - printf("code: %s:%i: %s%s%s %s@%i = %i(%s)\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs].function, def->symboldata[def->ofs].function >= numfunctions?"???":functions[def->symboldata[def->ofs].function].name); + printf("code: %s:%i: %s%s%s %s@%i = %i(%s)\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[0].function, def->symboldata[0].function >= numfunctions?"???":functions[def->symboldata[0].function].name); else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_field) - printf("code: %s:%i: %s%s%s %s@%i = @%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._int); + printf("code: %s:%i: %s%s%s %s@%i = @%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[0]._int); else printf("code: %s:%i: %s%s%s %s@%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs); #endif @@ -2471,7 +2474,7 @@ static void QCC_MergeUnstrip(dfunction_t *in, unsigned int num) if (!def) { def = QCC_PR_GetDef(type_function, name, NULL, true, 0, GDF_BASICTYPE); - def->symboldata[def->ofs].function = i; + def->symboldata[0].function = i; def->initialized = true; def->referenced = true; def->assumedtype = true; diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index fd0a5842f..ef6d7c151 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -1793,7 +1793,7 @@ void NPP_QWFlush(void) //move nq players to origin + angle VectorCopy(org, cl->edict->v->origin); VectorCopy(ang, cl->edict->v->angles); - cl->edict->v->angles[0]*=-1; + cl->edict->v->angles[0]*=r_meshpitch.value; } } } @@ -1815,6 +1815,7 @@ void NPP_QWFlush(void) short data; float org[3]; edict_t *ent = EDICT_NUM(svprogfuncs, LittleShort((*(short*)&buffer[1]))); + ent->muzzletime = sv.world.physicstime+host_frametime; //flag the entity as needing an EF_MUZZLEFLASH VectorCopy(ent->v->origin, org); //we need to make a fake muzzleflash position for multicast to work properly. diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index b1c908697..11b5c2df7 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -1229,9 +1229,6 @@ void PR_ApplyCompilation_f (void) pr_global_struct->time = sv.world.physicstime; - - World_ClearWorld (&sv.world); - for (i=0 ; iparms->memfree(s); } @@ -7503,7 +7492,7 @@ static void QCBUILTIN PF_h2matchAngleToSlope(pubprogfuncs_t *prinst, struct glob AngleVectors(actor->v->angles, old_forward, old_right, P_VEC(v_up)); - VectorAngles(G_VECTOR(OFS_PARM0), NULL, G_VECTOR(OFS_RETURN)); + VectorAngles(G_VECTOR(OFS_PARM0), NULL, G_VECTOR(OFS_RETURN), true/*FIXME*/); pitch = G_FLOAT(OFS_RETURN) - 90; @@ -9548,7 +9537,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) { if (!sv_player->v->fixangle) { - sv_player->v->angles[PITCH] = -sv_player->v->v_angle[PITCH]/3; + sv_player->v->angles[PITCH] = r_meshpitch.value * sv_player->v->v_angle[PITCH]/3; sv_player->v->angles[YAW] = sv_player->v->v_angle[YAW]; } sv_player->v->angles[ROLL] = @@ -11338,7 +11327,7 @@ void PR_DumpPlatform_f(void) {"oldorigin", ".vector", QW|NQ|CS, D("This is often used on players to reset the player back to where they were last frame if they somehow got stuck inside something due to fpu precision. Never change a player's oldorigin field to inside a solid, because that might cause them to become pemanently stuck.")}, {"velocity", ".vector", QW|NQ|CS, D("The direction and speed that the entity is moving in world space.")}, {"angles", ".vector", QW|NQ|CS, D("The eular angles the entity is facing in, in pitch, yaw, roll order. Due to a legacy bug, mdl/iqm/etc formats use +x=UP, bsp/spr/etc formats use +x=DOWN.")}, - {"avelocity", ".vector", QW|NQ|CS, D("The amount the entity's angles change by each frame. Note that this is direct eular angles, and thus the angular change is non-linear and often just looks buggy.")}, + {"avelocity", ".vector", QW|NQ|CS, D("The amount the entity's angles change by per second. Note that this is direct eular angles, and thus the angular change is non-linear and often just looks buggy if you're changing more than one angle at a time.")}, {"pmove_flags", ".float", CS}, {"punchangle", ".vector", NQ}, {"classname", ".string", QW|NQ|CS, D("Identifies the class/type of the entity. Useful for debugging, also used for loading, but its value is not otherwise significant to the engine, this leaves the mod free to set it to whatever it wants and randomly test strings for values in whatever inefficient way it chooses fit.")}, diff --git a/engine/server/progs.h b/engine/server/progs.h index e5ccc00fa..9b04c771e 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -83,10 +83,13 @@ typedef struct edict_s #endif /*csqc doesn't reference the rest*/ +#ifdef NQPROT + float muzzletime; //nq clients need special handling to retain EF_MUZZLEFLASH while not breaking qw clients running nq mods. +#endif entity_state_t baseline; // other fields from progs come immediately after } edict_t; - + diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 82333c427..2a0c86244 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -329,19 +329,7 @@ void SV_Loadgame_Legacy(char *filename, vfsfile_t *f, int version) //FIXME: DP saved games have some / *\nkey values\nkey values\n* / thing in them to save precaches and stuff - World_ClearWorld(&sv.world); - - for (i=0 ; itime = sv.world.physicstime; - for (i=0 ; iprotocol == SCP_QUAKEWORLD) #define ISQ2CLIENT(cl) ((cl)->protocol == SCP_QUAKE2) #define ISQ3CLIENT(cl) ((cl)->protocol == SCP_QUAKE3) #define ISNQCLIENT(cl) ((cl)->protocol >= SCP_NETQUAKE) #define ISDPCLIENT(cl) ((cl)->protocol >= SCP_DARKPLACES6) +#else +#define ISQWCLIENT(cl) ((cl)->protocol != SCP_BAD) +#define ISQ2CLIENT(cl) false +#define ISQ3CLIENT(cl) false +#define ISNQCLIENT(cl) false +#define ISDPCLIENT(cl) false +#endif // a client can leave the server in one of four ways: // dropping properly by quiting or disconnecting diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 6d6b2e072..5467ad6e2 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2340,16 +2340,19 @@ void SV_WritePlayersToMVD (client_t *client, client_frame_t *frame, sizebuf_t *m ent = cl->edict; vent = ent; +#ifdef NQPROT if (progstype != PROG_QW) { if ((int)ent->v->effects & EF_MUZZLEFLASH) { - if (needcleanup < (j+1)) - { - needcleanup = (j+1); - } + ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH; + ent->muzzletime = sv.world.physicstime; + MSG_WriteByte (&sv.multicast, svc_muzzleflash); + MSG_WriteEntity (&sv.multicast, NUM_FOR_EDICT(svprogfuncs, ent)); + SV_MulticastProtExt (ent->v->origin, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0); } } +#endif if (SV_AddCSQCUpdate(client, ent)) continue; @@ -2579,7 +2582,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * - +#ifdef NQPROT if (progstype != PROG_QW) { if (progstype == PROG_H2 && (int)ent->v->effects & H2EF_NODRAW && ent != clent) @@ -2587,12 +2590,14 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * if ((int)ent->v->effects & EF_MUZZLEFLASH) { - if (needcleanup < (j+1)) - { - needcleanup = (j+1); - } + ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH; + ent->muzzletime = sv.world.physicstime; + MSG_WriteByte (&sv.multicast, svc_muzzleflash); + MSG_WriteEntity (&sv.multicast, NUM_FOR_EDICT(svprogfuncs, ent)); + SV_MulticastProtExt (ent->v->origin, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0); } } +#endif // ZOID visibility tracking if (ent != clent && @@ -3290,7 +3295,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli } else { - vectoangles(sv.world.g.defaultgravitydir, ang); + VectorAngles(sv.world.g.defaultgravitydir, NULL, ang, false); state->u.q1.gravitydir[0] = ((ang[0]/360) * 256) - 192; state->u.q1.gravitydir[1] = (ang[1]/360) * 256; } @@ -3298,7 +3303,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli else { vec3_t ang; - vectoangles(ent->xv->gravitydir, ang); + VectorAngles(ent->xv->gravitydir, NULL, ang, false); state->u.q1.gravitydir[0] = ((ang[0]/360) * 256) - 192; state->u.q1.gravitydir[1] = (ang[1]/360) * 256; } @@ -3321,6 +3326,15 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli state->hexen2flags |= MLS_FULLBRIGHT; #ifdef NQPROT + if (client && !ISQWCLIENT(client)) + { + if (ent->muzzletime > client->lastoutgoingphysicstime && ent->muzzletime <= (float)sv.world.physicstime) + state->effects |= EF_MUZZLEFLASH; + + if (client->spectator && !client->spec_track && ent == client->edict) + state->modelindex = sv_playermodel; + } + if (progstype != PROG_QW) { if (progstype == PROG_TENEBRAE) @@ -3561,19 +3575,19 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t continue; } +#ifdef NQPROT if (progstype != PROG_QW) { -// if (progstype == PROG_H2) -// if (ent->v->effects == H2EF_NODRAW) -// continue; if ((int)ent->v->effects & EF_MUZZLEFLASH) { - if (needcleanup < e) - { - needcleanup = e; - } + ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH; + ent->muzzletime = sv.world.physicstime; + MSG_WriteByte (&sv.multicast, svc_muzzleflash); + MSG_WriteEntity (&sv.multicast, NUM_FOR_EDICT(svprogfuncs, ent)); + SV_MulticastProtExt (ent->v->origin, MULTICAST_PHS, pr_global_struct->dimension_send, 0, 0); } } +#endif pvsflags = ent->xv->pvsflags; for (c = 0; c < maxc; c++) @@ -4050,7 +4064,6 @@ void SV_CleanupEnts(void) { int e; edict_t *ent; - vec3_t org; if (!needcleanup) return; @@ -4058,17 +4071,6 @@ void SV_CleanupEnts(void) for (e=1 ; e<=needcleanup ; e++) { ent = EDICT_NUM(svprogfuncs, e); - if ((int)ent->v->effects & EF_MUZZLEFLASH) - { - ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH; - - MSG_WriteByte(&sv.multicast, svc_muzzleflash); - MSG_WriteEntity(&sv.multicast, e); - VectorCopy(ent->v->origin, org); - if (progstype == PROG_H2) - org[2] += 24; - SV_Multicast(org, MULTICAST_PVS); - } ent->xv->SendFlags = 0; #ifndef NOLEGACY diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index d569a0f1d..e25e016ec 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -1011,7 +1011,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, // // init physics interaction links // - World_ClearWorld (&sv.world); + World_ClearWorld (&sv.world, false); //do we allow csprogs? #ifdef PEXT_CSQC diff --git a/engine/server/sv_move.c b/engine/server/sv_move.c index 9e11d3eab..41a2fb8d5 100644 --- a/engine/server/sv_move.c +++ b/engine/server/sv_move.c @@ -324,7 +324,7 @@ float World_changeyaw (wedict_t *ent) vec3_t vang; /*calc current view matrix relative to the surface*/ - ent->v->angles[PITCH] *= -1; + ent->v->angles[PITCH] *= r_meshpitch.value; AngleVectors(ent->v->angles, view[0], view[1], view[2]); VectorNegate(view[1], view[1]); @@ -338,7 +338,7 @@ float World_changeyaw (wedict_t *ent) Matrix4_Multiply(viewm, invsurfm, mat); /*convert that back to angles*/ Matrix3x4_RM_ToVectors(mat, view[0], view[1], view[2], view[3]); - VectorAngles(view[0], view[2], vang); + VectorAngles(view[0], view[2], vang, true); /*edit it*/ @@ -375,7 +375,7 @@ float World_changeyaw (wedict_t *ent) Matrix4_Multiply(mat, surfm, viewm); /*and figure out the final result*/ Matrix3x4_RM_ToVectors(viewm, view[0], view[1], view[2], view[3]); - VectorAngles(view[0], view[2], ent->v->angles); + VectorAngles(view[0], view[2], ent->v->angles, true); //make sure everything is sane ent->v->angles[PITCH] = anglemod(ent->v->angles[PITCH]); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 65e6051a8..cebb42e4a 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -305,18 +305,18 @@ static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, v } else #endif - ent->v->angles[0] *= -1; + ent->v->angles[0] *= r_meshpitch.value; VectorCopy(ent->v->angles, G_VECTOR(OFS_PARM1)); AngleVectors(ent->v->angles, w->g.v_forward, w->g.v_right, w->g.v_up); PR_ExecuteProgram (w->progs, portal->xv->camera_transform); - VectorAngles(w->g.v_forward, w->g.v_up, ent->v->angles); + VectorAngles(w->g.v_forward, w->g.v_up, ent->v->angles, true); #ifndef CLIENTONLY if (ent->entnum > 0 && ent->entnum <= svs.allocated_client_slots) { client_t *cl = &svs.clients[ent->entnum-1]; int i; vec3_t delta; - ent->v->angles[0] *= -1; + ent->v->angles[0] *= r_meshpitch.value; if (!cl->lockangles && (cl->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) { cl = ClientReliableWrite_BeginSplit(cl, svcfte_setangledelta, 7); @@ -339,7 +339,7 @@ static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, v ClientReliableWrite_Angle (cl, ent->v->angles[i]); } VectorCopy(ent->v->angles, ent->v->v_angle); - ent->v->angles[0] *= -1; + ent->v->angles[0] *= r_meshpitch.value; } #endif @@ -347,11 +347,11 @@ static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, v avelocity is horribly dependant upon eular angles. trying to treat it as a matrix is folly. if (DotProduct(ent->v->avelocity, ent->v->avelocity)) { - ent->v->avelocity[0] *= -1; + ent->v->avelocity[0] *= r_meshpitch.value; AngleVectors(ent->v->avelocity, w->g.v_forward, w->g.v_right, w->g.v_up); PR_ExecuteProgram (w->progs, portal->xv->camera_transform); VectorAngles(w->g.v_forward, w->g.v_up, ent->v->avelocity); - ent->v->avelocity[0] *= -1; + ent->v->avelocity[0] *= r_meshpitch.value; } */ diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 807dea320..60f969cc9 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1561,7 +1561,16 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum) } // a fixangle might get lost in a dropped packet. Oh well. - if (ent->v->fixangle) + if (client->spectator && ISNQCLIENT(client) && client->spec_track > 0) + { + edict_t *ed = EDICT_NUM(svprogfuncs, client->spec_track); + MSG_WriteByte(msg, svc_setangle); + MSG_WriteAngle(msg, ed->v->v_angle[0]); + MSG_WriteAngle(msg, ed->v->v_angle[1]); + MSG_WriteAngle(msg, ed->v->v_angle[2]); + VectorCopy(ed->v->origin, client->edict->v->origin); + } + else if (ent->v->fixangle) { if (!client->lockangles) { @@ -1683,6 +1692,8 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) #ifdef NQPROT ent = client->edict; + if (client->spectator && client->spec_track) + ent = EDICT_NUM(svprogfuncs, client->spec_track); if (progstype != PROG_QW) { if (ISQWCLIENT(client) && !(client->fteprotocolextensions2 & PEXT2_PREDINFO)) @@ -1871,7 +1882,10 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) if (nqjunk) { - MSG_WriteShort (msg, ent->v->health); + if (client->spectator && !client->spec_track) + MSG_WriteShort (msg, 1000); + else + MSG_WriteShort (msg, ent->v->health); if (client->protocol == SCP_FITZ666) { MSG_WriteByte (msg, (int)ent->v->currentammo & 0xff); @@ -2098,26 +2112,35 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf #endif { #ifdef QUAKESTATS - statsf[STAT_HEALTH] = ent->v->health; //sorry, but mneh - statsi[STAT_WEAPONMODELI] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel)); - if ((unsigned)statsi[STAT_WEAPONMODELI] >= client->maxmodels) - statsi[STAT_WEAPONMODELI] = 0; //play it safe, try not to crash unsuspecting clients - statsf[STAT_AMMO] = ent->v->currentammo; - statsf[STAT_ARMOR] = ent->v->armorvalue; - statsf[STAT_SHELLS] = ent->v->ammo_shells; - statsf[STAT_NAILS] = ent->v->ammo_nails; - statsf[STAT_ROCKETS] = ent->v->ammo_rockets; - statsf[STAT_CELLS] = ent->v->ammo_cells; - statsf[STAT_ACTIVEWEAPON] = ent->v->weapon; - if ((client->csqcactive && !(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) || client->protocol != SCP_QUAKEWORLD || (client->fteprotocolextensions2 & PEXT2_PREDINFO)) -// if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || client->protocol != SCP_QUAKEWORLD) - statsf[STAT_WEAPONFRAME] = ent->v->weaponframe; //weapon frame is sent differently with classic quakeworld protocols. - - // stuff the sigil bits into the high bits of items for sbar - if (sv.haveitems2) - statsi[STAT_ITEMS] = (int)ent->v->items | ((int)ent->xv->items2 << 23); + if (client->spectator && !client->spec_track && ISNQCLIENT(client)) + { + statsf[STAT_HEALTH] = 1000; + statsf[STAT_ARMOR] = 1000; + statsf[STAT_AMMO] = 1000; + } else - statsi[STAT_ITEMS] = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28); + { + statsf[STAT_HEALTH] = ent->v->health; //sorry, but mneh + statsi[STAT_WEAPONMODELI] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel)); + if ((unsigned)statsi[STAT_WEAPONMODELI] >= client->maxmodels) + statsi[STAT_WEAPONMODELI] = 0; //play it safe, try not to crash unsuspecting clients + statsf[STAT_AMMO] = ent->v->currentammo; + statsf[STAT_ARMOR] = ent->v->armorvalue; + statsf[STAT_SHELLS] = ent->v->ammo_shells; + statsf[STAT_NAILS] = ent->v->ammo_nails; + statsf[STAT_ROCKETS] = ent->v->ammo_rockets; + statsf[STAT_CELLS] = ent->v->ammo_cells; + statsf[STAT_ACTIVEWEAPON] = ent->v->weapon; + if ((client->csqcactive && !(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) || client->protocol != SCP_QUAKEWORLD || (client->fteprotocolextensions2 & PEXT2_PREDINFO)) + // if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || client->protocol != SCP_QUAKEWORLD) + statsf[STAT_WEAPONFRAME] = ent->v->weaponframe; //weapon frame is sent differently with classic quakeworld protocols. + + // stuff the sigil bits into the high bits of items for sbar + if (sv.haveitems2) + statsi[STAT_ITEMS] = (int)ent->v->items | ((int)ent->xv->items2 << 23); + else + statsi[STAT_ITEMS] = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28); + } statsf[STAT_VIEWHEIGHT] = ent->v->view_ofs[2]; @@ -2484,7 +2507,7 @@ void SV_UpdateClientStats (client_t *client, int pnum, sizebuf_t *msg, client_fr qboolean SV_CanTrack(client_t *client, int entity) { - if (entity < 0 || entity >= sv.allocated_client_slots) + if (entity <= 0 || entity > sv.allocated_client_slots) return false; if (svs.clients[entity-1].spectator) return false; @@ -3217,7 +3240,7 @@ void SV_SendClientMessages (void) c->frameunion.frames[fnum & UPDATE_MASK].packetsizeout += sentbytes; c->datagram.cursize = 0; } - + c->lastoutgoingphysicstime = sv.world.physicstime; } SV_CleanupEnts(); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 52f08c29e..6bac2b561 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -3956,6 +3956,12 @@ void SV_PTrack_f (void) ent = EDICT_NUM(svprogfuncs, host_client - svs.clients + 1); tent = EDICT_NUM(svprogfuncs, 0); ent->v->goalentity = EDICT_TO_PROG(svprogfuncs, tent); + + if (ISNQCLIENT(host_client)) + { + ClientReliableWrite_Begin(host_client, svc_setview, 4); + ClientReliableWrite_Entity(host_client, host_client - svs.clients + 1); + } return; } @@ -3975,6 +3981,12 @@ void SV_PTrack_f (void) ent = EDICT_NUM(svprogfuncs, host_client - svs.clients + 1); tent = EDICT_NUM(svprogfuncs, 0); ent->v->goalentity = EDICT_TO_PROG(svprogfuncs, tent); + + if (ISNQCLIENT(host_client)) + { + ClientReliableWrite_Begin(host_client, svc_setview, 4); + ClientReliableWrite_Entity(host_client, host_client - svs.clients + 1); + } return; } host_client->spec_track = i + 1; // now tracking @@ -3982,6 +3994,12 @@ void SV_PTrack_f (void) ent = EDICT_NUM(svprogfuncs, host_client - svs.clients + 1); tent = EDICT_NUM(svprogfuncs, i + 1); ent->v->goalentity = EDICT_TO_PROG(svprogfuncs, tent); + + if (ISNQCLIENT(host_client)) + { + ClientReliableWrite_Begin(host_client, svc_setview, 4); + ClientReliableWrite_Entity(host_client, i + 1); + } } @@ -4877,7 +4895,7 @@ void Cmd_Join_f (void) return; } - if (!(host_client->zquake_extensions & Z_EXT_JOIN_OBSERVE)) + if (!ISNQCLIENT(host_client) && !(host_client->zquake_extensions & Z_EXT_JOIN_OBSERVE)) { SV_TPrintToClient(host_client, PRINT_HIGH, "Your game client doesn't support this command\n"); return; @@ -4923,6 +4941,12 @@ void Cmd_Join_f (void) return; } + if (ISNQCLIENT(host_client)) + { //make sure the nq client is viewing from its own player entity again + ClientReliableWrite_Begin(host_client, svc_setview, 4); + ClientReliableWrite_Entity(host_client, host_client - svs.clients + 1); + } + for (; host_client; host_client = host_client->controlled) { sv_player = host_client->edict; @@ -5022,7 +5046,7 @@ void Cmd_Observe_f (void) return; } - if (!(host_client->zquake_extensions & Z_EXT_JOIN_OBSERVE)) + if (!ISNQCLIENT(host_client) && !(host_client->zquake_extensions & Z_EXT_JOIN_OBSERVE)) { SV_TPrintToClient(host_client, PRINT_HIGH, "Your game client doesn't support this command\n"); return; @@ -5808,11 +5832,11 @@ ucmd_t ucmds[] = {"nextdl", SV_NextDownload_f, true}, /*quakeworld specific things*/ - {"addseat", Cmd_AddSeat_f}, + {"addseat", Cmd_AddSeat_f}, //splitscreen {"join", Cmd_Join_f}, {"observe", Cmd_Observe_f}, - {"snap", SV_NoSnap_f}, {"ptrack", SV_PTrack_f}, //ZOID - used with autocam + {"snap", SV_NoSnap_f}, //cheat detection {"enablecsqc", SV_EnableClientsCSQC, true}, {"disablecsqc", SV_DisableClientsCSQC, true}, @@ -5938,6 +5962,11 @@ ucmd_t nqucmds[] = {"disablecsqc", SV_DisableClientsCSQC}, {"challengeconnect", NULL}, + /*spectating, this should be fun...*/ + {"join", Cmd_Join_f}, + {"observe", Cmd_Observe_f}, + {"ptrack", SV_PTrack_f}, //ZOID - used with autocam + #ifdef VOICECHAT {"voicetarg", SV_Voice_Target_f}, {"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/ @@ -6228,7 +6257,7 @@ static qboolean AddEntityToPmove(edict_t *player, edict_t *check) if (solid == SOLID_PORTAL || solid == SOLID_BSP) { if(progstype != PROG_H2) - pe->angles[0]*=-1; //quake is wierd. I guess someone fixed it hexen2... or my code is buggy or something... + pe->angles[0]*=r_meshpitch.value; //quake is wierd. I guess someone fixed it hexen2... or my code is buggy or something... pe->model = sv.models[(int)(check->v->modelindex)]; VectorCopy (check->v->angles, pe->angles); } @@ -6712,7 +6741,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) { if (sv_player->v->movetype == MOVETYPE_6DOF) { - sv_player->v->angles[PITCH] = -sv_player->v->v_angle[PITCH]; + sv_player->v->angles[PITCH] = r_meshpitch.value * sv_player->v->v_angle[PITCH]; sv_player->v->angles[YAW] = sv_player->v->v_angle[YAW]; sv_player->v->angles[ROLL] = sv_player->v->v_angle[ROLL]; } @@ -6720,7 +6749,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) { if (!sv_player->v->fixangle) { - sv_player->v->angles[PITCH] = -sv_player->v->v_angle[PITCH]/3; + sv_player->v->angles[PITCH] = r_meshpitch.value * sv_player->v->v_angle[PITCH]/3; sv_player->v->angles[YAW] = sv_player->v->v_angle[YAW]; } sv_player->v->angles[ROLL] = @@ -6996,7 +7025,7 @@ if (sv_player->v->health > 0 && before && !after ) VectorInterpolate(surf[0], 0.333, view[0], fwd); CrossProduct(surf[1], fwd, up); /*we have our player's new axis*/ - VectorAngles(fwd, up, sv_player->v->angles); + VectorAngles(fwd, up, sv_player->v->angles, true); } } @@ -7870,6 +7899,52 @@ void SVNQ_ReadClientMove (usercmd_t *move) bits = MSG_ReadLong(); else bits = MSG_ReadByte (); + if (host_client->spectator) + { + qboolean tracknext = false; + if (bits & (move->buttons ^ bits) & BUTTON_ATTACK) + { //enable/disable tracking + if (host_client->spec_track) + { //disable tracking + host_client->spec_track = 0; + host_client->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, 0)); + ClientReliableWrite_Begin(host_client, svc_setview, 4); + ClientReliableWrite_Entity(host_client, host_client - svs.clients + 1); + } + else //otherwise track the next person, if we can + tracknext = true; + } + if ((bits & (move->buttons ^ bits) & BUTTON_JUMP) && host_client->spec_track) + tracknext = true; + + if (tracknext) + { //track the next player + for (i = host_client->spec_track+1; i < sv.allocated_client_slots; i++) + { + if (SV_CanTrack(host_client, i)) + break; + } + //try a previous one instead of disabling + if (i == sv.allocated_client_slots) + { + for (i = 1; i < host_client->spec_track; i++) + { + if (SV_CanTrack(host_client, i)) + break; + } + if (i == host_client->spec_track) + i = 0; + } + + host_client->spec_track = i; + host_client->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, i)); + ClientReliableWrite_Begin(host_client, svc_setview, 4); + ClientReliableWrite_Entity(host_client, i?i:(host_client - svs.clients + 1)); + + if (i) + SV_ClientTPrintf (host_client, PRINT_HIGH, "tracking %s\n", svs.clients[i-1].name); + } + } move->buttons = bits; i = MSG_ReadByte (); diff --git a/engine/server/svhl_world.c b/engine/server/svhl_world.c index ad7fcd59e..42c8a4fd0 100644 --- a/engine/server/svhl_world.c +++ b/engine/server/svhl_world.c @@ -379,9 +379,9 @@ trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t // trace a line through the apropriate clipping hull if (ent->v.solid != SOLID_BSP) { - ent->v.angles[0]*=-1; //carmack made bsp models rotate wrongly. + ent->v.angles[0]*=r_meshpitch.value; //carmack made bsp models rotate wrongly. World_TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, false, &trace, ent->v.origin, ent->v.angles, clipmask); - ent->v.angles[0]*=-1; + ent->v.angles[0]*=r_meshpitch.value; } else { diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index ac50b79be..483d0f1f9 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -1801,7 +1801,7 @@ qboolean SVQ3_InitGame(void) SV_InitBotLib(); - World_ClearWorld(&sv.world); + World_ClearWorld(&sv.world, false); q3_sentities = Z_Malloc(sizeof(q3serverEntity_t)*MAX_GENTITIES); diff --git a/engine/server/world.c b/engine/server/world.c index 99a26d54a..ba854a68e 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -224,28 +224,29 @@ static areanode_t *World_CreateAreaNode (world_t *w, int depth, vec3_t mins, vec w->numareanodes++; ClearLink (&anode->edicts); - - if (depth == w->areanodedepth) + + VectorSubtract (maxs, mins, size); + + if (depth == w->areanodedepth || (size[0] < 512 && size[1] < 512)) { anode->axis = -1; anode->children[0] = anode->children[1] = NULL; return anode; } - - VectorSubtract (maxs, mins, size); + if (size[0] > size[1]) anode->axis = 0; else anode->axis = 1; - + anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); VectorCopy (mins, mins1); VectorCopy (mins, mins2); VectorCopy (maxs, maxs1); VectorCopy (maxs, maxs2); - + maxs1[anode->axis] = mins2[anode->axis] = anode->dist; - + anode->children[0] = World_CreateAreaNode (w, depth+1, mins2, maxs2); anode->children[1] = World_CreateAreaNode (w, depth+1, mins1, maxs1); @@ -258,8 +259,10 @@ SV_ClearWorld =============== */ -void World_ClearWorld (world_t *w) +void World_ClearWorld (world_t *w, qboolean relink) { + int i; + wedict_t *ent; int maxdepth; vec3_t mins, maxs; if (w->worldmodel) @@ -279,18 +282,33 @@ void World_ClearWorld (world_t *w) ClearLink (&w->portallist.edicts); w->portallist.axis = -1; - maxdepth = 4; + maxdepth = 8; if (!w->areanodes || w->areanodedepth != maxdepth) { Z_Free(w->areanodes); w->areanodedepth = maxdepth; - w->areanodes = Z_Malloc(sizeof(*w->areanodes) * pow(2, w->areanodedepth+1)); + w->areanodes = Z_Malloc(sizeof(*w->areanodes) * (pow(2, w->areanodedepth+1)-1)); } else memset (w->areanodes, 0, sizeof(*w->areanodes)*w->numareanodes); w->numareanodes = 0; World_CreateAreaNode (w, 0, mins, maxs); + + + if (relink) + { + for (i=0 ; inum_edicts ; i++) + { + ent = WEDICT_NUM(w->progs, i); + if (!ent) + continue; + ent->area.prev = ent->area.next = NULL; + if (ED_ISFREE(ent)) + continue; + World_LinkEdict (w, ent, false); // relink ents so touch functions continue to work. + } + } } @@ -1126,9 +1144,9 @@ 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. + ent->v->angles[0]*=r_meshpitch.value; //carmack made bsp models rotate wrongly. World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask); - ent->v->angles[0]*=-1; + ent->v->angles[0]*=r_meshpitch.value; } else { @@ -1275,7 +1293,7 @@ static void WorldQ2_AreaEdicts_r (areanode_t *node) if (!l) { int i; - World_ClearWorld(&sv.world); + World_ClearWorld(&sv.world, false); check = ge->edicts; for (i = 0; i < ge->num_edicts; i++, check = (q2edict_t *)((char *)check + ge->edict_size)) memset(&check->area, 0, sizeof(check->area)); diff --git a/engine/vk/vk_backend.c b/engine/vk/vk_backend.c index 737900d5d..bb2f7c041 100644 --- a/engine/vk/vk_backend.c +++ b/engine/vk/vk_backend.c @@ -5468,8 +5468,7 @@ static void R_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist //now determine the stuff the backend will use. memcpy(r_refdef.m_view, vmat, sizeof(float)*16); - VectorAngles(vpn, vup, r_refdef.viewangles); - r_refdef.viewangles[0] *= -1; + VectorAngles(vpn, vup, r_refdef.viewangles, false); VectorCopy(r_refdef.vieworg, r_origin); //determine r_refdef.flipcull & SHADER_CULL_FLIP based upon whether right is right or not.