diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 0de33e866..99249dbe4 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -180,6 +180,7 @@ trace_t Cam_DoTrace(vec3_t vec1, vec3_t vec2) memset(&pmove, 0, sizeof(pmove)); pmove.numphysent = 1; + memset(&pmove.physents[0], 0, sizeof(physent_t)); VectorClear (pmove.physents[0].origin); pmove.physents[0].model = cl.worldmodel; #endif diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 06564cfee..80ccd4187 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1448,7 +1448,7 @@ void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entities_t * } le = &cl.lerpents[snew->number]; - VectorSubtract(snew->origin, sold->origin, move) + VectorSubtract(snew->origin, sold->origin, move); if (DotProduct(move, move) > 200*200 || snew->modelindex != sold->modelindex) { sold = snew; //teleported? @@ -1630,7 +1630,7 @@ void CL_LinkPacketEntities (void) } - VectorCopy(le->origin, ent->origin) + VectorCopy(le->origin, ent->origin); //bots or powerup glows. items always glow, powerups can be disabled if (state->modelindex != cl_playerindex || r_powerupglow.value) @@ -2701,7 +2701,7 @@ void CL_AddFlagModels (entity_t *ent, int team) newent->origin[i] = ent->origin[i] - offs*v_forward[i] + 22*v_right[i]; newent->origin[2] -= 16; - VectorCopy (ent->angles, newent->angles) + VectorCopy (ent->angles, newent->angles); newent->angles[2] -= 45; VectorCopy(newent->angles, angles); @@ -3102,6 +3102,7 @@ void CL_SetSolidEntities (void) packet_entities_t *pak; entity_state_t *state; + memset(&pmove.physents[0], 0, sizeof(physent_t)); pmove.physents[0].model = cl.worldmodel; VectorClear (pmove.physents[0].origin); pmove.physents[0].info = 0; @@ -3122,6 +3123,7 @@ void CL_SetSolidEntities (void) if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode || cl.model_precache[state->modelindex]->clipbox ) { + memset(&pmove.physents[pmove.numphysent], 0, sizeof(physent_t)); pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex]; VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin); VectorCopy (state->angles, pmove.physents[pmove.numphysent].angles); @@ -3271,9 +3273,8 @@ void CL_SetSolidPlayers (int playernum) if (pplayer->flags & PF_DEAD) continue; // dead players aren't solid - pent->model = 0; + memset(pent, 0, sizeof(physent_t)); VectorCopy(pplayer->origin, pent->origin); - pent->angles[0] = pent->angles[1] = pent->angles[2] = 0; //don't bother rotating - only useful with bsps VectorCopy(player_mins, pent->mins); VectorCopy(player_maxs, pent->maxs); if (++pmove.numphysent == MAX_PHYSENTS) //we just hit 88 miles per hour. diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index bd152b732..b2cf1a34d 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -545,6 +545,11 @@ qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname, unsigned if (!(flags & DLLF_OVERWRITE) && CL_CheckFile(localname)) return true; +#ifndef CLIENTONLY + if (sv.state) + return true; +#endif + //ZOID - can't download when recording if (cls.demorecording) { @@ -738,7 +743,7 @@ void Model_NextDownload (void) int i; // extern char gamedirfile[]; - Con_TPrintf (TLC_CHECKINGMODELS); +// Con_TPrintf (TLC_CHECKINGMODELS); /* if (cls.downloadnumber == 0) { @@ -905,12 +910,15 @@ int CL_LoadModels(int stage) { if (!cl.model_name[1][0]) Host_EndGame("Worldmodel name wasn't sent\n"); - else - Host_EndGame("Worldmodel wasn't loaded\n"); +// else +// return stage; +// Host_EndGame("Worldmodel wasn't loaded\n"); } - if (cl.worldmodel->fromgame == fg_quake) + if (cl.worldmodel && cl.worldmodel->fromgame == fg_quake) cl.hexen2pickups = cl.worldmodel->hulls[MAX_MAP_HULLSDH2-1].available; + else + cl.hexen2pickups = false; R_CheckSky(); @@ -952,8 +960,8 @@ int CL_LoadModels(int stage) if (atstage()) { loadmodel = cl.worldmodel; - if (!loadmodel || loadmodel->type == mod_dummy) - Host_EndGame("No worldmodel was loaded\n"); +// if (!loadmodel || loadmodel->type == mod_dummy) +// Host_EndGame("No worldmodel was loaded\n"); Mod_NowLoadExternal(); endstage(); @@ -964,8 +972,9 @@ int CL_LoadModels(int stage) if (atstage()) { loadmodel = cl.worldmodel; - if (!loadmodel || loadmodel->type == mod_dummy) - Host_EndGame("No worldmodel was loaded\n"); +// if (!loadmodel || loadmodel->type == mod_dummy) +// Host_EndGame("No worldmodel was loaded\n"); + cl.model_precaches_added = false; R_NewMap (); pmove.physents[0].model = cl.worldmodel; @@ -1015,7 +1024,7 @@ void Sound_NextDownload (void) int i; - Con_TPrintf (TLC_CHECKINGSOUNDS); +// Con_TPrintf (TLC_CHECKINGSOUNDS); #ifdef CSQC_DAT if (cls.fteprotocolextensions & PEXT_CSQC) @@ -1955,7 +1964,8 @@ void CL_ParseServerData (void) if (protover == PROTOCOL_VERSION_FTE) { cls.fteprotocolextensions = MSG_ReadLong(); - Con_TPrintf (TL_FTEEXTENSIONS, cls.fteprotocolextensions); + if (developer.value || cl_shownet.value) + Con_TPrintf (TL_FTEEXTENSIONS, cls.fteprotocolextensions); continue; } if (protover == PROTOCOL_VERSION_QW) //this ends the version info @@ -2361,9 +2371,18 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. //fill in the csqc stuff - Info_SetValueForStarKey(cl.serverinfo, "*csprogs", va("%i", cl_dp_csqc_progscrc), sizeof(cl.serverinfo)); - Info_SetValueForStarKey(cl.serverinfo, "*csprogssize", va("%i", cl_dp_csqc_progssize), sizeof(cl.serverinfo)); - Info_SetValueForStarKey(cl.serverinfo, "*csprogsname", va("%i", cl_dp_csqc_progsname), sizeof(cl.serverinfo)); + if (!cl_dp_csqc_progscrc) + { + Info_RemoveKey(cl.serverinfo, "*csprogs"); + Info_RemoveKey(cl.serverinfo, "*csprogssize"); + Info_RemoveKey(cl.serverinfo, "*csprogsname"); + } + else + { + Info_SetValueForStarKey(cl.serverinfo, "*csprogs", va("%i", cl_dp_csqc_progscrc), sizeof(cl.serverinfo)); + Info_SetValueForStarKey(cl.serverinfo, "*csprogssize", va("%i", cl_dp_csqc_progssize), sizeof(cl.serverinfo)); + Info_SetValueForStarKey(cl.serverinfo, "*csprogsname", va("%i", cl_dp_csqc_progsname), sizeof(cl.serverinfo)); + } //update gamemode if (gametype == 1) @@ -2873,7 +2892,7 @@ qboolean CL_CheckBaselines (int size) return false; size = (size + 64) & ~63; // round up to next 64 - if (size < cl_baselines_count) + if (size <= cl_baselines_count) return true; cl_baselines = BZ_Realloc(cl_baselines, sizeof(*cl_baselines)*size); @@ -4383,6 +4402,8 @@ void CL_ParsePrecache(void) Con_Printf("svc_precache: Mod_ForName(\"%s\") failed\n", s); cl.model_precache[i] = model; strcpy (cl.model_name[i], s); + + cl.model_precaches_added = true; } else Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_MODELS); @@ -5338,6 +5359,10 @@ void CLNQ_ParseServerMessage (void) cl_dp_csqc_progssize = atoi(s+14); else if (!strncmp(s, "csqc_progcrc ", 13)) cl_dp_csqc_progscrc = atoi(s+13); + else if (!strncmp(s, "cl_fullpitch ", 13) || !strncmp(s, "pq_fullpitch ", 13)) + { + // + } else { Cbuf_AddText (s, RESTRICT_SERVER); //no cheating here... @@ -5435,7 +5460,11 @@ void CLNQ_ParseServerMessage (void) if (i >= MAX_CLIENTS) MSG_ReadString(); else + { strcpy(cl.players[i].name, MSG_ReadString()); + if (*cl.players[i].name) + cl.players[i].userid = i+1; + } break; case svc_updatefrags: @@ -5448,22 +5477,22 @@ void CLNQ_ParseServerMessage (void) break; case svc_updatecolors: { - int a; - Sbar_Changed (); - i = MSG_ReadByte (); - a = MSG_ReadByte (); - if (i >= MAX_CLIENTS) - break; - //FIXME:!!!! + int a; + i = MSG_ReadByte (); + a = MSG_ReadByte (); + if (i < MAX_CLIENTS) + { + cl.players[i].rtopcolor = a&0x0f; + cl.players[i].rbottomcolor = (a&0xf0)>>4; - cl.players[i].rtopcolor = a&0x0f; - cl.players[i].rbottomcolor = (a&0xf0)>>4; + sprintf(cl.players[i].team, "%2d", cl.players[i].rbottomcolor); - if (cls.state == ca_active) - Skin_Find (&cl.players[i]); + if (cls.state == ca_active) + Skin_Find (&cl.players[i]); - Sbar_Changed (); - CL_NewTranslation (i); + Sbar_Changed (); + CL_NewTranslation (i); + } } break; case svc_lightstyle: diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 9087fce71..a3c4e1897 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -817,6 +817,19 @@ void CL_PredictMovePNum (int pnum) } */ } #endif + if (!from->playerstate[cl.playernum[pnum]].messagenum) + { + //no player states?? put the view on an ent + if (cl.playernum[pnum] < cl.maxlerpents) + { +// Con_Printf("Using lerped pos\n"); + org = cl.lerpents[cl.playernum[pnum]+1].origin; + vel = vec3_origin; + goto fixedorg; + } + } + + if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.fixangle)) { fixedorg: diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index e7a74a6dc..9780818cb 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1053,6 +1053,8 @@ void SCR_CalcRefdef (void) r_refdef.fov_x = 10; else if (r_refdef.fov_x > 170) r_refdef.fov_x = 170; + + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); diff --git a/engine/client/client.h b/engine/client/client.h index a03a688f0..39c1fb07a 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -419,11 +419,15 @@ typedef struct { float framechange; //marks time of last frame change - for halflife model sequencing. float oldframechange; float lerprate; //inverse rate... - vec3_t origin; + vec3_t origin; //current render position vec3_t angles; + vec3_t forigin; //when the frame changed + vec3_t fangles; + vec3_t foldorigin;// + vec3_t foldangles; trailstate_t *trailstate; //when to next throw out a trail trailstate_t *emitstate; //when to next emit - unsigned short frame; + unsigned short frame, oldframe; } lerpents_t; // // the client_state_t structure is wiped completely at every @@ -539,6 +543,8 @@ typedef struct char model_csqcname[MAX_CSQCMODELS][MAX_QPATH]; struct model_s *model_csqcprecache[MAX_CSQCMODELS]; + qboolean model_precaches_added; + //used for q2 sky/configstrings char skyname[MAX_QPATH]; float skyrotate; @@ -690,6 +696,7 @@ extern float server_version; // version of server we connected to // dlight_t *CL_AllocDlight (int key); dlight_t *CL_NewDlight (int key, float x, float y, float z, float radius, float time, int type); +dlight_t *CL_NewDlightRGB (int key, float x, float y, float z, float radius, float time, float r, float g, float b); void CL_DecayLights (void); void CL_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int bits, qboolean); diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 9b2f0ac2a..ee0df9415 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -592,6 +592,7 @@ void CLQ3_ParseGameState(void) if (!cl.worldmodel) Host_EndGame("CGame didn't set a map.\n"); + cl.model_precaches_added = false; R_NewMap (); SCR_EndLoadingPlaque(); @@ -943,7 +944,8 @@ void CLQ3_SendCmd(usercmd_t *cmd) // begin a client move command, if any if( cmdcount ) { - if(!ccs.snap.valid || + extern cvar_t cl_nodelta; + if(cl_nodelta.value || !ccs.snap.valid || ccs.snap.serverMessageNum != ccs.serverMessageNum) MSG_WriteBits(&msg, clcq3_nodeltaMove, 8); // no compression else diff --git a/engine/client/net_master.c b/engine/client/net_master.c index c5888744f..6ad00aa1d 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -1319,8 +1319,6 @@ void MasterInfo_Begin(void) Master_AddMaster("qwmaster.ocrana.de:27000", MT_MASTERQW, "Ocrana2 master server."); Master_AddMaster("213.221.174.165:27000", MT_MASTERQW, "unknown1 master server."); Master_AddMaster("195.74.0.8", MT_MASTERQW, "unknown2 master server."); - Master_AddMaster("192.246.40.37", MT_MASTERQW, "unknown3 master server."); - Master_AddMaster("192.246.40.37:27006", MT_MASTERQW, "unknown4 master server."); Master_AddMaster("204.182.161.2", MT_MASTERQW, "unknown5 master server."); Master_AddMaster("255.255.255.255:27500", MT_BCASTQW, "Nearby QuakeWorld UDP servers."); diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index 7ed1fae5c..60b34ad71 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -201,7 +201,10 @@ static void PClassic_DrawParticles(void) #endif if (!active_particles) + { + RQ_RenderDistAndClear(); return; + } switch(qrenderer) { @@ -229,6 +232,7 @@ static void PClassic_DrawParticles(void) break; #endif default: + RQ_RenderDistAndClear(); return; } @@ -367,13 +371,9 @@ static void PClassic_DrawParticles(void) -//this... is hard to explain. -//please don't make me do so. -#ifdef RGLQUAKE RSpeedRemark(); RQ_RenderDistAndClear(); RSpeedEnd(RSPEED_PARTICLESDRAW); -#endif } //called to set up the rendering state (opengl) diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index c63f14f74..8d6eb0949 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3600,7 +3600,6 @@ static void PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globa { int skelidx = G_FLOAT(OFS_PARM0); int boneidx = G_FLOAT(OFS_PARM1)-1; - float *matrix[4]; float temp[3][4]; float mult[3][4]; skelobject_t *skelobj; diff --git a/engine/client/r_part.c b/engine/client/r_part.c index 34bb3b093..c7627c0be 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -167,6 +167,8 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) for (i=0 ; i< pmove.numphysent ; i++) { pe = &pmove.physents[i]; + if (pe->nonsolid) + continue; if (pe->model) { VectorSubtract(start, pe->origin, ts); diff --git a/engine/client/render.h b/engine/client/render.h index 4e88e6eb0..2c856458d 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -423,7 +423,9 @@ double Media_TweekCaptureFrameTime(double time); void MYgluPerspective(double fovx, double fovy, double zNear, double zFar); -void R_MarkLeaves (void); +void R_MarkLeaves_Q1 (void); +void R_MarkLeaves_Q2 (void); +void R_MarkLeaves_Q3 (void); void R_SetFrustum (void); void R_SetRenderer(int wanted); void RQ_Init(void); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 5cae567cb..924d9f407 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -165,9 +165,9 @@ cvar_t scr_viewsize = SCVARFC("viewsize", "100", cvar_t vid_conautoscale = SCVARF ("vid_conautoscale", "0", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); -cvar_t vid_conheight = SCVARF ("vid_conheight", "480", +cvar_t vid_conheight = SCVARF ("vid_conheight", "0", CVAR_ARCHIVE); -cvar_t vid_conwidth = SCVARF ("vid_conwidth", "640", +cvar_t vid_conwidth = SCVARF ("vid_conwidth", "0", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); //see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'. cvar_t vid_renderer = SCVARF ("vid_renderer", "", @@ -2407,71 +2407,75 @@ mleaf_t *r_vischain; // linked list of visible leafs R_MarkLeaves =============== */ +#ifdef Q3BSPS +void R_MarkLeaves_Q3 (void) +{ + qbyte *vis; + int i; -void R_MarkLeaves (void) + int cluster; + mleaf_t *leaf; + + if (r_oldviewcluster == r_viewcluster && !r_novis.value && r_viewcluster != -1) + return; + + // development aid to let you run around and see exactly where + // the pvs ends +// if (r_lockpvs->value) +// return; + + r_vischain = NULL; + r_visframecount++; + r_oldviewcluster = r_viewcluster; + + if (r_novis.value || r_viewcluster == -1 || !cl.worldmodel->vis ) + { + // mark everything + for (i=0,leaf=cl.worldmodel->leafs ; inumleafs ; i++, leaf++) + { + if (!leaf->nummarksurfaces) + { + continue; + } + + leaf->visframe = r_visframecount; + leaf->vischain = r_vischain; + r_vischain = leaf; + } + } + else + { + vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster, NULL);//, cl.worldmodel); + for (i=0,leaf=cl.worldmodel->leafs ; inumleafs ; i++, leaf++) + { + cluster = leaf->cluster; + if (cluster == -1 || !leaf->nummarksurfaces) + { + continue; + } + if (vis[cluster>>3] & (1<<(cluster&7))) + { + leaf->visframe = r_visframecount; + leaf->vischain = r_vischain; + r_vischain = leaf; + } + } + } +} +#endif + +#ifdef Q2BSPS +void R_MarkLeaves_Q2 (void) { qbyte fatvis[MAX_MAP_LEAFS/8]; qbyte *vis; mnode_t *node; int i; - qbyte solid[4096]; -#ifdef Q3BSPS - if (cl.worldmodel->fromgame == fg_quake3) - { - int cluster; - mleaf_t *leaf; - if (r_oldviewcluster == r_viewcluster && !r_novis.value && r_viewcluster != -1) - return; + int cluster; + mleaf_t *leaf; - // development aid to let you run around and see exactly where - // the pvs ends -// if (r_lockpvs->value) -// return; - - r_vischain = NULL; - r_visframecount++; - r_oldviewcluster = r_viewcluster; - - if (r_novis.value || r_viewcluster == -1 || !cl.worldmodel->vis ) - { - // mark everything - for (i=0,leaf=cl.worldmodel->leafs ; inumleafs ; i++, leaf++) - { - if ( !leaf->nummarksurfaces ) { - continue; - } - - leaf->visframe = r_visframecount; - leaf->vischain = r_vischain; - r_vischain = leaf; - } - return; - } - - vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster, NULL);//, cl.worldmodel); - for (i=0,leaf=cl.worldmodel->leafs ; inumleafs ; i++, leaf++) - { - cluster = leaf->cluster; - if ( cluster == -1 || !leaf->nummarksurfaces ) { - continue; - } - if ( vis[cluster>>3] & (1<<(cluster&7)) ) { - leaf->visframe = r_visframecount; - leaf->vischain = r_vischain; - r_vischain = leaf; - } - } - return; - } -#endif - -#ifdef Q2BSPS - if (cl.worldmodel->fromgame == fg_quake2) - { int c; - mleaf_t *leaf; - int cluster; if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2) return; @@ -2525,6 +2529,14 @@ void R_MarkLeaves (void) } #endif +void R_MarkLeaves_Q1 (void) +{ + qbyte fatvis[MAX_MAP_LEAFS/8]; + qbyte *vis; + mnode_t *node; + int i; + qbyte solid[4096]; + if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.value) || r_novis.value == 2) return; @@ -2541,7 +2553,7 @@ void R_MarkLeaves (void) vis = solid; memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3); } - else if (r_viewleaf2) + else if (r_viewleaf2 && r_viewleaf2 != r_viewleaf) { int c; Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis); @@ -2572,7 +2584,6 @@ void R_MarkLeaves (void) } - mplane_t frustum[4]; diff --git a/engine/client/skin.c b/engine/client/skin.c index e955b65ff..58fdbffed 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -280,9 +280,13 @@ qbyte *Skin_Cache8 (skin_t *skin) raw = COM_LoadTempFile (name); if (!raw) { - Con_Printf ("Couldn't load skin %s\n", name); - sprintf (name, "skins/%s.pcx", baseskin.string); - raw = COM_LoadTempFile (name); + if (strcmp(skin->name, baseskin.string)) + { + //if its not already the base skin, try the base (and warn if anything not base couldn't load). + Con_Printf ("Couldn't load skin %s\n", name); + sprintf (name, "skins/%s.pcx", baseskin.string); + raw = COM_LoadTempFile (name); + } if (!raw) { skin->failedload = true; @@ -519,7 +523,7 @@ void Skin_NextDownload (void) player_info_t *sc; int i; - Con_Printf ("Checking skins...\n"); + //Con_Printf ("Checking skins...\n"); for (i = 0; i != MAX_CLIENTS; i++) { diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index bd817a66f..df983ad8d 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -66,6 +66,63 @@ dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs) return (dllhandle_t*)lib; } +void *Sys_GetAddressForName(dllhandle_t *module, char *exportname) +{ + if (!module) + return NULL; + return GetProcAddress((HINSTANCE)module, exportname); +} +#ifdef HLSERVER +char *Sys_GetNameForAddress(dllhandle_t *module, void *address) +{ + //windows doesn't provide a function to do this, so we have to do it ourselves. + //this isn't the fastest way... + //halflife needs this function. + char *base = (char *)module; + + IMAGE_DATA_DIRECTORY *datadir; + IMAGE_EXPORT_DIRECTORY *block; + IMAGE_NT_HEADERS *ntheader; + IMAGE_DOS_HEADER *dosheader = (void*)base; + + int i, j; + DWORD *funclist; + DWORD *namelist; + SHORT *ordilist; + + if (!dosheader || dosheader->e_magic != IMAGE_DOS_SIGNATURE) + return NULL; //yeah, that wasn't an exe + + ntheader = (void*)(base + dosheader->e_lfanew); + if (!dosheader->e_lfanew || ntheader->Signature != IMAGE_NT_SIGNATURE) + return NULL; //urm, wait, a 16bit dos exe? + + + datadir = &ntheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + block = (IMAGE_EXPORT_DIRECTORY *)(base + datadir->VirtualAddress); + funclist = (DWORD*)(base+block->AddressOfFunctions); + namelist = (DWORD*)(base+block->AddressOfNames); + ordilist = (SHORT*)(base+block->AddressOfNameOrdinals); + for (i = 0; i < block->NumberOfFunctions; i++) + { + if (base+funclist[i] == address) + { + for (j = 0; j < block->NumberOfNames; j++) + { + if (ordilist[j] == i) + { + return base+namelist[i]; + } + } + //it has no name. huh? + return NULL; + } + } + return NULL; +} +#endif + static HINSTANCE game_library; diff --git a/engine/client/valid.c b/engine/client/valid.c index c7e5c5bce..2b27737b8 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -444,7 +444,11 @@ void Validation_DelatchRulesets(void) Con_DPrintf("Ruleset deactivated\n"); } -void Validation_Ruleset(void) +void Validation_AllChecks(void) +{ +} + +void Validation_OldRuleset(void) { //this code is more complex than it needs to be //this allows for the ruleset code to print a ruleset name that is applied via the cvars, but not directly named by the user cvar_t *var; @@ -611,7 +615,10 @@ void Validation_Auto_Response(int playernum, char *s) } else if (!strncmp(s, "f_ruleset", 9) && rulesetresponsetime < Sys_DoubleTime()) { - Validation_Ruleset(); + if (1) + Validation_AllChecks(); + else + Validation_OldRuleset(); rulesetresponsetime = Sys_DoubleTime() + 5; } } diff --git a/engine/client/view.c b/engine/client/view.c index 4b75038a2..340be640d 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1324,7 +1324,22 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) } r_refdef.fov_x = scr_fov.value; - r_refdef.fov_y = CalcFov(r_refdef.fov_x, vrect->width, vrect->height); + if (cl.stats[pnum][STAT_VIEWZOOM]) + r_refdef.fov_x *= cl.stats[pnum][STAT_VIEWZOOM]/255.0f; + +#ifdef GLQUAKE + if (qrenderer == QR_OPENGL && vrect->width < (vrect->height*640)/432) + { + extern int glwidth, glheight; + r_refdef.fov_y = CalcFov(r_refdef.fov_x, (vrect->width*glwidth)/vid.width, (vrect->height*glheight)/vid.height); +// r_refdef.fov_x = CalcFov(r_refdef.fov_y, 432, 640); + } + else +#endif + { + r_refdef.fov_y = CalcFov(r_refdef.fov_x, 640, 432); + r_refdef.fov_x = CalcFov(r_refdef.fov_y, vrect->height, vrect->width); + } } void R_DrawNameTags(void) diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 297816cbf..df34189f7 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -2101,6 +2101,9 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr) { *offset = (name - s) + 2; flags = TPM_FAKED; + + if (msglen > 4 && *s == '(' && s[-1] == ')') + flags |= TPM_TEAM; } } @@ -3022,8 +3025,9 @@ void TP_UpdateAutoStatus(void) char newstatusbuf[sizeof(vars.autoteamstatus)]; char *newstatus; - if (vars.autoteamstatus_time < realtime) + if (vars.autoteamstatus_time > realtime) return; + vars.autoteamstatus_time = realtime + 3; newstatus = Cmd_ExpandString(tp_autostatus.string, newstatusbuf, sizeof(newstatusbuf), tp_autostatus.restriction, true, true); newstatus = TP_ParseMacroString(newstatus); @@ -3051,7 +3055,6 @@ void TP_UpdateAutoStatus(void) //the tp code will reexpand it as part of the say team Cbuf_AddText(va("say_team $\\%s\n", tp_autostatus.string), RESTRICT_LOCAL); - vars.autoteamstatus_time = realtime + 3; } void TP_StatChanged (int stat, int value) diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 8b1c0d0c1..19ad1a290 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -123,6 +123,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define Q2CLIENT //client can connect to q2 servers #define Q3CLIENT #define Q3SERVER +// #define HLSERVER #define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect') #define FISH //sw rendering only #define ZLIB //zip/pk3 support diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 0da724c61..30c327851 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -71,6 +71,10 @@ typedef struct cvar_s char *defaultstr; //default qbyte restriction; + +#ifdef HLSERVER + struct hlcvar_s *hlcvar; +#endif } cvar_t; #define FCVARC(ConsoleName,ConsoleName2,Value,Flags,Callback) {ConsoleName, Value, NULL, Flags, 0, 0, 0, ConsoleName2, Callback} diff --git a/engine/common/fs.c b/engine/common/fs.c index d0271d2e0..5f0c74569 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -151,7 +151,8 @@ int fs_hash_files; -int COM_FileOpenRead (char *path, FILE **hndl); +static int COM_FileOpenRead (char *path, FILE **hndl); +qboolean Sys_PathProtection(char *pattern); @@ -274,6 +275,9 @@ vfsfile_t *FSOS_OpenVFS(void *handle, flocation_t *loc, char *mode) { char diskname[MAX_OSPATH]; + if (Sys_PathProtection(loc->rawname)) + return NULL; + snprintf(diskname, sizeof(diskname), "%s/%s", (char*)handle, loc->rawname); return VFSOS_Open(diskname, mode); @@ -455,7 +459,7 @@ qboolean FSPAK_FLocate(void *handle, flocation_t *loc, char *filename, void *has if (loc) { loc->index = pf - pak->files; - snprintf(loc->rawname, sizeof(loc->rawname), "%s/%s", pak->descname, filename); + snprintf(loc->rawname, sizeof(loc->rawname), "%s", pak->descname); loc->offset = pf->filepos; loc->len = pf->filelen; } @@ -1392,7 +1396,8 @@ int COM_filelength (FILE *f) return end; } -int COM_FileOpenRead (char *path, FILE **hndl) +/* +static int COM_FileOpenRead (char *path, FILE **hndl) { FILE *f; @@ -1406,6 +1411,7 @@ int COM_FileOpenRead (char *path, FILE **hndl) return COM_filelength(f); } +*/ int COM_FileSize(char *path) { @@ -1575,7 +1581,8 @@ Copies a file over from the net to the local cache, creating any directories needed. This is for the convenience of developers using ISDN from home. =========== */ -void COM_CopyFile (char *netpath, char *cachepath) +/* +static void COM_CopyFile (char *netpath, char *cachepath) { FILE *in, *out; int remaining, count; @@ -1601,6 +1608,7 @@ void COM_CopyFile (char *netpath, char *cachepath) fclose (in); fclose (out); } +//*/ int fs_hash_dups; int fs_hash_files; @@ -1681,6 +1689,12 @@ int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *lo void *pf; //Con_Printf("Finding %s: ", filename); + if (Sys_PathProtection(filename)) + { + pf = NULL; + goto fail; + } + if (com_fs_cache.value) { if (com_fschanged) @@ -1896,22 +1910,39 @@ int COM_FOpenWriteFile(char *filename, FILE **file) //true if protection kicks in qboolean Sys_PathProtection(char *pattern) { + char *s; if (strchr(pattern, '\\')) { - char *s; Con_Printf("Warning: \\ characters in filename %s\n", pattern); while((s = strchr(pattern, '\\'))) *s = '/'; } + if (strstr(pattern, "//")) + { + //amiga uses // as equivelent to /../ + Con_Printf("Warning: // characters in filename %s\n", pattern); + while (s=strstr(pattern, "//")) + { + s++; + while (*s) + { + *s = *(s+1); + s++; + } + } + } + if (strstr(pattern, "..")) Con_Printf("Error: '..' characters in filename %s\n", pattern); else if (pattern[0] == '/') Con_Printf("Error: absolute path in filename %s\n", pattern); - else if (strstr(pattern, ":")) //win32 drive seperator (or mac path seperator, but / works there and they're used to it) + else if (strstr(pattern, ":")) //win32 drive seperator (or mac path seperator, but / works there and they're used to it) (or amiga device separator) Con_Printf("Error: absolute path in filename %s\n", pattern); else + { return false; + } return true; } @@ -2475,6 +2506,18 @@ qbyte *COM_LoadStackFile (char *path, void *buffer, int bufsize) +int FS_LoadFile(char *name, void **file) +{ + *file = COM_LoadMallocFile(name); + return com_filesize; +} +void FS_FreeFile(void *file) +{ + BZ_Free(file); +} + + + void COM_EnumerateFiles (char *match, int (*func)(char *, int, void *), void *parm) { searchpath_t *search; @@ -2924,6 +2967,8 @@ gamemode_info_t gamemode_info[] = { {"FTE-JK2", "jk2", "-jk2", "base/assets0.pk3", NULL, "base", "fte"}, + {"FTE-HalfLife", "hl", "-hl", "valve/liblist.gam",NULL, "valve", "fte"}, + {NULL} }; @@ -3117,6 +3162,125 @@ void FS_ReloadPackFiles_f(void) FS_ReloadPackFilesFlags((unsigned int)-1); } +#ifdef _WIN32 +#include +qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen) +{ + if (!strcmp(gamename, "q1")) + { + //try and find it via steam + //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath + //append SteamApps\common\quake + //use it if we find winquake.exe there + FILE *f; + DWORD resultlen; + HKEY key = NULL; + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + Q_strncatz(basepath, "/SteamApps/common/quake", basepathlen); + if (f = fopen(va("%s/Winquake.exe", basepath), "rb")) + { + fclose(f); + return true; + } + } + //well, okay, so they don't have quake installed from steam. + + //quite a lot of people have it in c:\quake, as that's the default install location from the quake cd. + if (f = fopen("c:/quake/quake.exe", "rb")) + { + //HAHAHA! Found it! + fclose(f); + Q_strncpyz(basepath, "c:/quake", basepathlen); + return true; + } + } + + if (!strcmp(gamename, "q2")) + { + //try and find it via steam + //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath + //append SteamApps\common\quake 2 + //use it if we find quake2.exe there + FILE *f; + DWORD resultlen; + HKEY key = NULL; + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + Q_strncatz(basepath, "/SteamApps/common/quake 2", basepathlen); + if (f = fopen(va("%s/quake2.exe", basepath), "rb")) + { + fclose(f); + return true; + } + } + //well, okay, so they don't have quake2 installed from steam. + + //look for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Quake2_exe\Path + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Quake2_exe", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "Path", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + if (f = fopen(va("%s/quake2.exe", basepath), "rb")) + { + fclose(f); + return true; + } + } + } + + if (!strcmp(gamename, "q3")) + { + DWORD resultlen; + HKEY key = NULL; + //reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Quake III Arena\InstallPath + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Quake III Arena", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + return true; + } + } +/* + if (!strcmp(gamename, "d3")) + { + DWORD resultlen; + HKEY key = NULL; + //reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Doom 3\InstallPath + if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Doom 3", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key))) + { + resultlen = basepathlen; + RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen); + RegCloseKey(key); + return true; + } + } +*/ + + if (!strcmp(gamename, "h3")) + { + //try and find it via steam + //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath + //append SteamApps\common\hexen 2 + } + + return false; +} +#else +qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen) +{ + return false; +} +#endif + /* ================ COM_InitFilesystem @@ -3181,9 +3345,40 @@ void COM_InitFilesystem (void) for (i = 0; gamemode_info[i].gamename; i++) { if (COM_CheckParm(gamemode_info[i].argname)) + { gamenum = i; + + if (gamemode_info[gamenum].auniquefile) + { + f = fopen(va("%s%s", com_quakedir, gamemode_info[i].auniquefile), "rb"); + if (f) + { + //we found it, its all okay + fclose(f); + break; + } +#ifdef _WIN32 + if (Sys_FindGameData(gamemode_info[i].exename, com_quakedir, sizeof(com_quakedir))) + { + if (com_quakedir[strlen(com_quakedir)-1] == '\\') + com_quakedir[strlen(com_quakedir)-1] = '/'; + else if (com_quakedir[strlen(com_quakedir)-1] != '/') + { + com_quakedir[strlen(com_quakedir)+1] = '\0'; + com_quakedir[strlen(com_quakedir)] = '/'; + } + } + else +#endif + { + Con_Printf("Couldn't find the gamedata for this game mode!\n"); + } + } + break; + } } + //still failed? find quake and use that one by default if (gamenum<0) { for (i = 0; gamemode_info[i].gamename; i++) @@ -3192,6 +3387,7 @@ void COM_InitFilesystem (void) gamenum = i; } } + Cvar_Set(&com_gamename, gamemode_info[gamenum].gamename); if (gamemode_info[gamenum].customexec) diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 93d633651..1ca0cba1c 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -3778,7 +3778,7 @@ void SWR_Q2BSP_StainNode (mnode_t *node, float *parms) #ifndef CLIENTONLY void Q2BSP_FatPVS (model_t *mod, vec3_t org, qboolean add); qboolean Q2BSP_EdictInFatPVS(model_t *mod, edict_t *ent); -void Q2BSP_FindTouchedLeafs(model_t *mod, edict_t *ent); +void Q2BSP_FindTouchedLeafs(model_t *mod, edict_t *ent, float *mins, float *maxs); #endif void GLQ2BSP_LightPointValues(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void SWQ2BSP_LightPointValues(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 73c6e5e6a..631e3584f 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -318,6 +318,61 @@ void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up) CrossProduct(right, forward, up); } +void VectorAngles(float *forward, float *up, float *result) //up may be NULL +{ + float yaw, pitch, roll; + + if (forward[1] == 0 && forward[0] == 0) + { + if (forward[2] > 0) + { + pitch = 90; + yaw = up ? atan2(-up[1], -up[0]) : 0; + } + else + { + pitch = 270; + yaw = up ? atan2(up[1], up[0]) : 0; + } + roll = 0; + } + else + { + yaw = atan2(forward[1], forward[0]); + pitch = -atan2(forward[2], sqrt (forward[0]*forward[0] + forward[1]*forward[1])); + + if (up) + { + vec_t cp = cos(pitch), sp = sin(pitch); + vec_t cy = cos(yaw), sy = sin(yaw); + vec3_t tleft, tup; + tleft[0] = -sy; + tleft[1] = cy; + tleft[2] = 0; + tup[0] = sp*cy; + tup[1] = sp*sy; + tup[2] = cp; + roll = -atan2(DotProduct(up, tleft), DotProduct(up, tup)); + } + else + roll = 0; + } + + pitch *= -180 / M_PI; + yaw *= 180 / M_PI; + roll *= 180 / M_PI; + if (pitch < 0) + pitch += 360; + if (yaw < 0) + yaw += 360; + if (roll < 0) + roll += 360; + + result[0] = pitch; + result[1] = yaw; + result[2] = roll; +} + void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) { float angle; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 098e13078..8c772032c 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -45,9 +45,9 @@ extern int nanmask; #define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) #define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) -#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];} -#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];} -#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];} +#define VectorSubtract(a,b,c) do{(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}while(0) +#define VectorAdd(a,b,c) do{(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}while(0) +#define VectorCopy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}while(0) #define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) #define VectorLength(a) Length(a) @@ -87,6 +87,7 @@ void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out); void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); float anglemod (float a); void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); +void VectorAngles (float *forward, float *up, float *angles); //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 a00d88016..7d236aacd 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -123,6 +123,8 @@ int PM_SlideMove (void) time_left = frametime; +// VectorAdd(pmove.velocity, pmove.basevelocity, pmove.velocity); + for (bumpcount=0 ; bumpcount 100 || wishvel[2] < -100) //large up/down move + if (wishvel[2] >= 100 || wishvel[2] <= -100) //large up/down move wishvel[2]*=10; if (pmove.cmd.buttons & 2) - wishvel[2]+=100; + wishvel[2]+=movevars.maxspeed; VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); @@ -762,6 +764,11 @@ void PM_CategorizePosition (void) } } + if (cont & FTECONTENTS_LADDER) + pmove.onladder = true; + else + pmove.onladder = false; + //are we on a ladder? #ifdef Q2BSPS if (pmove.physents[0].model->fromgame == fg_quake3) @@ -808,6 +815,14 @@ void PM_CategorizePosition (void) } #endif + //bsp objects marked as ladders mark regions to stand in to be classed as on a ladder. + cont = PM_ExtraBoxContents(pmove.origin); + if (cont & FTECONTENTS_LADDER) + { + pmove.onladder = true; + pmove.onground = false; // too steep + } + if (pmove.onground && pmove.pm_type != PM_FLY && pmove.waterlevel < 2) { // snap to ground so that we can't jump higher than we're supposed to diff --git a/engine/common/pmove.h b/engine/common/pmove.h index 658fd4abc..f1fbb5a1b 100644 --- a/engine/common/pmove.h +++ b/engine/common/pmove.h @@ -41,6 +41,7 @@ typedef struct unsigned short info; // for client or server to identify qbyte nonsolid; qbyte notouch; + unsigned int forcecontentsmask; } physent_t; typedef struct @@ -51,6 +52,7 @@ typedef struct vec3_t origin; vec3_t angles; vec3_t velocity; + vec3_t basevelocity; qboolean jump_held; int jump_msec; // msec since last jump float waterjumptime; diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index 91bfff384..1bf40c5ea 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -129,7 +129,62 @@ int PM_PointContents (vec3_t p) pe = &pmove.physents[num]; pm = pe->model; if (pm) - pc |= PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles); + { + if (pe->forcecontentsmask) + { + if (PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles)) + pc |= pe->forcecontentsmask; + } + else + { + if (pe->nonsolid) + continue; + pc |= PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles); + } + } + else if (pe->forcecontentsmask) + { + if (p[0] >= pe->mins[0] && p[0] <= pe->maxs[0] && + p[1] >= pe->mins[1] && p[1] <= pe->maxs[1] && + p[2] >= pe->mins[2] && p[2] <= pe->maxs[2]) + pc |= pe->forcecontentsmask; + } + } + + return pc; +} + +int PM_ExtraBoxContents (vec3_t p) +{ + int num; + + int pc = 0; + physent_t *pe; + model_t *pm; + trace_t tr; + + for (num = 1; num < pmove.numphysent; num++) + { + pe = &pmove.physents[num]; + if (!pe->nonsolid) + continue; + pm = pe->model; + if (pm) + { + if (pe->forcecontentsmask) + { + PM_TransformedHullCheck(pm, p, p, &tr, pe->origin, pe->angles); + if (tr.startsolid) + pc |= pe->forcecontentsmask; + } + } + else if (pe->forcecontentsmask) + { + if (p[0]+player_maxs[0] >= pe->mins[0] && p[0]+player_mins[0] <= pe->maxs[0] && + p[1]+player_maxs[1] >= pe->mins[1] && p[1]+player_mins[1] <= pe->maxs[1] && + p[2]+player_maxs[2] >= pe->mins[2] && p[2]+player_mins[2] <= pe->maxs[2]) + pc |= pe->forcecontentsmask; + } } return pc; @@ -185,7 +240,7 @@ qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, trac } // sweep the box through the model - if (model) + if (model && model->funcs.Trace) result = model->funcs.Trace(model, 0, 0, start_l, end_l, player_mins, player_maxs, trace); else { @@ -242,6 +297,9 @@ qboolean PM_TestPlayerPosition (vec3_t pos) { pe = &pmove.physents[i]; + if (pe->nonsolid) + continue; + // get the clipping hull if (pe->model) { @@ -299,6 +357,9 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end) { pe = &pmove.physents[i]; + if (pe->nonsolid) + continue; + if (!pe->model) { vec3_t mins, maxs; diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 94f30b20e..64decc148 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -934,7 +934,7 @@ SV_FindTouchedLeafs Links the edict to the right leafs so we can get it's potential visability. =============== */ -void Q1BSP_RFindTouchedLeafs (edict_t *ent, mnode_t *node) +void Q1BSP_RFindTouchedLeafs (edict_t *ent, mnode_t *node, float *mins, float *maxs) { mplane_t *splitplane; mleaf_t *leaf; @@ -965,20 +965,20 @@ void Q1BSP_RFindTouchedLeafs (edict_t *ent, mnode_t *node) // NODE_MIXED splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(ent->v->absmin, ent->v->absmax, splitplane); + sides = BOX_ON_PLANE_SIDE(mins, maxs, splitplane); // recurse down the contacted sides if (sides & 1) - Q1BSP_RFindTouchedLeafs (ent, node->children[0]); + Q1BSP_RFindTouchedLeafs (ent, node->children[0], mins, maxs); if (sides & 2) - Q1BSP_RFindTouchedLeafs (ent, node->children[1]); + Q1BSP_RFindTouchedLeafs (ent, node->children[1], mins, maxs); } -void Q1BSP_FindTouchedLeafs(model_t *mod, edict_t *ent) +void Q1BSP_FindTouchedLeafs(model_t *mod, edict_t *ent, float *mins, float *maxs) { ent->num_leafs = 0; if (ent->v->modelindex) - Q1BSP_RFindTouchedLeafs (ent, mod->nodes); + Q1BSP_RFindTouchedLeafs (ent, mod->nodes, mins, maxs); } #endif diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 543570290..71ff560a2 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -66,90 +66,31 @@ struct vm_s { int (VARGS *vmMain)(int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); }; - -#ifdef _WIN32 -#include "winquake.h" -void *Sys_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall) -{ - void (VARGS *dllEntry)(sys_calldll_t syscall); - char dllname[MAX_OSPATH]; - HINSTANCE hVM; - - sprintf(dllname, "%sx86.dll", name); - - hVM=NULL; - { - char name[MAX_OSPATH]; - char *gpath; - // run through the search paths - gpath = NULL; - while (1) - { - gpath = COM_NextPath (gpath); - if (!gpath) - return NULL; // couldn't find one anywhere - snprintf (name, sizeof(name), "%s/%s", gpath, dllname); - hVM = LoadLibrary (name); - if (hVM) - { - Con_DPrintf ("LoadLibrary (%s)\n",name); - break; - } - } - } - - if(!hVM) return NULL; - - dllEntry=(void *)GetProcAddress(hVM, "dllEntry"); - if(!dllEntry) - { - Con_Printf ("Sys_LoadDLL: %s lacks a dllEntry function\n",name); - FreeLibrary(hVM); - return NULL; - } - - dllEntry(syscall); - - *vmMain=(void *)GetProcAddress(hVM, "vmMain"); - if(!*vmMain) - { - Con_Printf ("Sys_LoadDLL: %s lacks a vmMain function\n",name); - FreeLibrary(hVM); - return NULL; - } - return hVM; -} - -/* -** Sys_UnloadDLL -*/ -void Sys_UnloadDLL(void *handle) -{ - if(handle) - { - if(!FreeLibrary((HMODULE)handle)) - Sys_Error("Sys_UnloadDLL FreeLibrary failed"); - } -} -#else #if defined(__MORPHOS__) && I_AM_BIGFOOT #include -#else -#include #endif -void *Sys_LoadDLL(const char *name, void **vmMain, int (EXPORT_FN *syscall)(int arg, ... )) +dllhandle_t *QVM_LoadDLL(const char *name, void **vmMain, int (EXPORT_FN *syscall)(int arg, ... )) { void (*dllEntry)(int (EXPORT_FN *syscall)(int arg, ... )); char dllname[MAX_OSPATH]; - void *hVM; + dllhandle_t *hVM; + + dllfunction_t funcs[] = + { + {(void*)&dllEntry, "dllEntry"}, + {(void*)vmMain, "vmMain"}, + {NULL, NULL}, + }; #if defined(__MORPHOS__) && I_AM_BIGFOOT if (DynLoadBase == 0) return 0; #endif -#if defined(__amd64__) +#ifdef _WIN32 + sprintf(dllname, "%sx86.dll", name); +#elif defined(__amd64__) return 0; //give up early, don't even try going there sprintf(dllname, "%samd.so", name); #elif defined(_M_IX86) || defined(__i386__) @@ -173,57 +114,34 @@ void *Sys_LoadDLL(const char *name, void **vmMain, int (EXPORT_FN *syscall)(int gpath = COM_NextPath (gpath); if (!gpath) return NULL; // couldn't find one anywhere - _snprintf (name, sizeof(name), "%s/%s", gpath, dllname); + snprintf (name, sizeof(name), "%s/%s", gpath, dllname); Con_Printf("Loading native: %s\n", name); - hVM = dlopen (name, RTLD_NOW); + hVM = Sys_LoadLibrary(name, funcs); if (hVM) { - Con_DPrintf ("Sys_LoadDLL: dlopen (%s)\n",name); break; } - else - { - Con_DPrintf("Sys_LoadDLL: dlerror()=\"%s\"", dlerror()); - } } } if(!hVM) return NULL; - dllEntry=(void *)dlsym(hVM, "dllEntry"); - if(!dllEntry) - { - Con_Printf("Sys_LoadDLL: %s does not have a dllEntry function\n"); - dlclose(hVM); - return NULL; - } - (*dllEntry)(syscall); - *vmMain=(void *)dlsym(hVM, "vmMain"); - if(!*vmMain) - { - Con_Printf("Sys_LoadDLL: %s does not have a vmMain function\n"); - dlclose(hVM); - return NULL; - } - return hVM; } /* ** Sys_UnloadDLL */ -void Sys_UnloadDLL(void *handle) +void QVM_UnloadDLL(dllhandle_t *handle) { if(handle) { - if(dlclose(handle)) - Sys_Error("Sys_UnloadDLL FreeLibrary failed"); + Sys_CloseLibrary(handle); } } -#endif @@ -292,9 +210,9 @@ typedef struct qvm_s sys_callqvm_t syscall; } qvm_t; -qvm_t *QVM_Load(const char *name, sys_callqvm_t syscall); -void QVM_UnLoad(qvm_t *qvm); -int QVM_Exec(qvm_t *qvm, int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7); +qvm_t *QVM_LoadVM(const char *name, sys_callqvm_t syscall); +void QVM_UnLoadVM(qvm_t *qvm); +int QVM_ExecVM(qvm_t *qvm, int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7); // ------------------------- * OP.CODES * ------------------------- @@ -397,7 +315,7 @@ typedef enum qvm_op_e /* ** QVM_Load */ -qvm_t *QVM_Load(const char *name, sys_callqvm_t syscall) +qvm_t *QVM_LoadVM(const char *name, sys_callqvm_t syscall) { char path[MAX_QPATH]; vmHeader_t *header; @@ -547,7 +465,7 @@ qvm_t *QVM_Load(const char *name, sys_callqvm_t syscall) /* ** QVM_UnLoad */ -void QVM_UnLoad(qvm_t *qvm) +void QVM_UnLoadVM(qvm_t *qvm) { Z_Free(qvm->mem_ptr); Z_Free(qvm); @@ -648,7 +566,7 @@ static void inline QVM_Return(qvm_t *vm, int size) /* ** VM_Exec */ -int QVM_Exec(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) +int QVM_ExecVM(register qvm_t *qvm, int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) { //remember that the stack is backwards. push takes 1. @@ -1026,7 +944,7 @@ vm_t *VM_Create(vm_t *vm, const char *name, sys_calldll_t syscalldll, sys_callqv { if (!COM_CheckParm("-nodlls") && !COM_CheckParm("-nosos")) //:) { - if((vm->hInst=Sys_LoadDLL(name, (void**)&vm->vmMain, syscalldll))) + if((vm->hInst=QVM_LoadDLL(name, (void**)&vm->vmMain, syscalldll))) { Con_DPrintf("Creating native machine \"%s\"\n", name); vm->type=VM_NATIVE; @@ -1038,7 +956,7 @@ vm_t *VM_Create(vm_t *vm, const char *name, sys_calldll_t syscalldll, sys_callqv if (syscallqvm) { - if((vm->hInst=QVM_Load(name, syscallqvm))) + if((vm->hInst=QVM_LoadVM(name, syscallqvm))) { Con_DPrintf("Creating virtual machine \"%s\"\n", name); vm->type=VM_BYTECODE; @@ -1060,11 +978,11 @@ void VM_Destroy(vm_t *vm) switch(vm->type) { case VM_NATIVE: - if(vm->hInst) Sys_UnloadDLL(vm->hInst); + if(vm->hInst) QVM_UnloadDLL(vm->hInst); break; case VM_BYTECODE: - if(vm->hInst) QVM_UnLoad(vm->hInst); + if(vm->hInst) QVM_UnLoadVM(vm->hInst); break; case VM_NONE: @@ -1094,11 +1012,11 @@ qboolean VM_Restart(vm_t *vm) switch(vm->type) { case VM_NATIVE: - if(vm->hInst) Sys_UnloadDLL(vm->hInst); + if(vm->hInst) QVM_UnloadDLL(vm->hInst); break; case VM_BYTECODE: - if(vm->hInst) QVM_UnLoad(vm->hInst); + if(vm->hInst) QVM_UnLoadVM(vm->hInst); break; case VM_NONE: @@ -1148,7 +1066,7 @@ int VARGS VM_Call(vm_t *vm, int instruction, ...) return vm->vmMain(instruction, arg0, arg1, arg2, arg3, arg4, arg5, arg6); case VM_BYTECODE: - return QVM_Exec(vm->hInst, instruction, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return QVM_ExecVM(vm->hInst, instruction, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); case VM_NONE: return 0; diff --git a/engine/common/sys.h b/engine/common/sys.h index 6f1c9145e..5b22e710b 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -37,6 +37,8 @@ int Sys_FileTime (char *path); void Sys_mkdir (char *path); qboolean Sys_remove (char *path); +qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen); + // // memory protection // @@ -62,6 +64,8 @@ typedef struct { typedef void *dllhandle_t; dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs); void Sys_CloseLibrary(dllhandle_t *lib); +void *Sys_GetAddressForName(dllhandle_t *module, char *exportname); +char *Sys_GetNameForAddress(dllhandle_t *module, void *address); unsigned int Sys_Milliseconds (void); double Sys_DoubleTime (void); diff --git a/engine/common/world.h b/engine/common/world.h index 6d3d3f89d..bba4488e4 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -66,7 +66,7 @@ typedef struct trace_s cplane_t plane; // surface normal at impact q2csurface_t *surface; // surface hit int contents; // contents on other side of surface hit - struct edict_s *ent; // not set by CM_*() functions + void *ent; // not set by CM_*() functions //AND THIS LINE int entnum; diff --git a/engine/d3d/d3d_rmain.c b/engine/d3d/d3d_rmain.c index ef722b390..61c7700d8 100644 --- a/engine/d3d/d3d_rmain.c +++ b/engine/d3d/d3d_rmain.c @@ -914,17 +914,24 @@ void D3D7_DrawWorld(void) } #ifdef Q3BSPS if (ent.model->fromgame == fg_quake3) - { + { + R_MarkLeaves_Q3 (); D3D7_LeafWorldNode (); } else -#endif - D3D7_RecursiveQ2WorldNode (cl.worldmodel->nodes); +#endif + { + R_MarkLeaves_Q2 (); + D3D7_RecursiveQ2WorldNode (cl.worldmodel->nodes); + } } else #endif -*/ - D3D7_RecursiveWorldNode (cl.worldmodel->nodes); +*/ + { + R_MarkLeaves_Q1 (); + D3D7_RecursiveWorldNode (cl.worldmodel->nodes); + } RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling PPL_DrawWorld\n")); @@ -947,7 +954,6 @@ void D3D7_R_RenderScene(void) if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { - R_MarkLeaves (); // done here so we know if we're in water D3D7_DrawWorld (); // adds static entities to the list } diff --git a/engine/d3d9/d3d9_rmain.c b/engine/d3d9/d3d9_rmain.c index 93820d4f9..0c470e0ca 100644 --- a/engine/d3d9/d3d9_rmain.c +++ b/engine/d3d9/d3d9_rmain.c @@ -1328,16 +1328,23 @@ void D3D9_DrawWorld(void) } #ifdef Q3BSPS if (ent.model->fromgame == fg_quake3) - { + { + R_MarkLeaves_Q3 (); D3D9_LeafWorldNode (); } else -#endif - D3D9_RecursiveQ2WorldNode (cl.worldmodel->nodes); +#endif + { + R_MarkLeaves_Q2 (); + D3D9_RecursiveQ2WorldNode (cl.worldmodel->nodes); + } } else -#endif - D3D9_RecursiveWorldNode (cl.worldmodel->nodes); +#endif + { + R_MarkLeaves_Q1 (); + D3D9_RecursiveWorldNode (cl.worldmodel->nodes); + } RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling PPL_DrawWorld\n")); @@ -1360,7 +1367,6 @@ void D3D9_R_RenderScene(void) if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { - R_MarkLeaves (); // done here so we know if we're in water D3D9_DrawWorld (); // adds static entities to the list } diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 47a2ec36b..a5eff6230 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -595,7 +595,7 @@ qboolean Heightmap_EdictInFatPVS (model_t *mod, edict_t *edict) return true; } -void Heightmap_FindTouchedLeafs (model_t *mod, edict_t *ent) +void Heightmap_FindTouchedLeafs (model_t *mod, edict_t *ent, float *mins, float *maxs) { } #endif diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 0cec36407..5d610edd0 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -393,6 +393,9 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ frametime *= sequence->timing; + if (frametime < 0) + frametime = 0; + frame = (int)frametime; frametime -= frame; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 130e0dbfd..9c59cfd52 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -46,7 +46,7 @@ typedef struct { void (*FatPVS) (struct model_s *model, vec3_t org, qboolean add); qboolean (*EdictInFatPVS) (struct model_s *model, struct edict_s *edict); - void (*FindTouchedLeafs_Q1) (struct model_s *model, struct edict_s *ent); //edict system as opposed to q2 game dll system. + void (*FindTouchedLeafs_Q1) (struct model_s *model, struct edict_s *ent, vec3_t cullmins, vec3_t cullmaxs); //edict system as opposed to q2 game dll system. void (*LightPointValues) (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void (*StainNode) (struct mnode_s *node, float *parms); @@ -401,7 +401,7 @@ qboolean Q1BSP_Trace(struct model_s *model, int forcehullnum, int frame, vec3_t qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); void Q1BSP_FatPVS (struct model_s *mod, vec3_t org, qboolean add); qboolean Q1BSP_EdictInFatPVS(struct model_s *mod, struct edict_s *ent); -void Q1BSP_FindTouchedLeafs(struct model_s *mod, struct edict_s *ent); +void Q1BSP_FindTouchedLeafs(struct model_s *mod, struct edict_s *ent, float *mins, float *maxs); qbyte *Q1BSP_LeafPVS (struct model_s *model, mleaf_t *leaf, qbyte *buffer); /* diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 638ef9dbc..783efdf4a 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1165,8 +1165,6 @@ void R_RenderScene (void) if (!GLR_DoomWorld ()) #endif { - TRACE(("dbg: calling GLR_MarkLeaves\n")); - R_MarkLeaves (); // done here so we know if we're in water TRACE(("dbg: calling R_DrawWorld\n")); R_DrawWorld (); // adds static entities to the list } diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index d5b35b620..a4d5db707 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -2771,6 +2771,80 @@ e->angles[0] = -e->angles[0]; // stupid quake bug ============================================================= */ + +#if 0 +void R_MarkLeafSurfaces_Q1 (void) +{ + static qbyte fatvis[MAX_MAP_LEAFS/8]; + static qbyte *vis; + mleaf_t *leaf; + int i, j; + qbyte solid[4096]; + msurface_t *surf; + int shift; + + r_visframecount++; + if (1)//r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) + { + } + else + { + r_oldviewleaf = r_viewleaf; + r_oldviewleaf2 = r_viewleaf2; + + if ((int)r_novis.value&1) + { + vis = solid; + memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3); + } + else if (r_viewleaf2 && r_viewleaf2 != r_viewleaf) + { + int c; + Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis); + vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL); + c = (cl.worldmodel->numleafs+31)/32; + for (i=0 ; inumleafs ; i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + leaf = (mleaf_t *)&cl.worldmodel->leafs[i+1]; + + if (R_CullBox (leaf->minmaxs, leaf->minmaxs+3)) + continue; + leaf->visframe = r_visframecount; + + for (j = 0; j < leaf->nummarksurfaces; j++) + { + surf = leaf->firstmarksurface[j]; + if (surf->visframe == r_visframecount) + continue; + surf->visframe = r_visframecount; + + R_RenderDynamicLightmaps (surf, shift); + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; + } + + //deal with static ents. + if (leaf->efrags) + R_StoreEfrags (&leaf->efrags); + } + } +} +#else + /* ================ R_RecursiveWorldNode @@ -2890,6 +2964,7 @@ start: node = node->children[!side]; goto start; } +#endif #ifdef Q2BSPS static void GLR_RecursiveQ2WorldNode (mnode_t *node) @@ -3118,15 +3193,26 @@ void R_DrawWorld (void) #ifdef Q3BSPS if (ent.model->fromgame == fg_quake3) { + R_MarkLeaves_Q3 (); GLR_LeafWorldNode (); } else #endif + { + R_MarkLeaves_Q2 (); GLR_RecursiveQ2WorldNode (cl.worldmodel->nodes); + } } else #endif + { +#if 0 + R_MarkLeafSurfaces_Q1(); +#else + R_MarkLeaves_Q1 (); GLR_RecursiveWorldNode (cl.worldmodel->nodes); +#endif + } RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling PPL_DrawWorld\n")); diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 373cad0b0..6941948b3 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -40,15 +40,58 @@ extern qboolean scr_drawloading; extern int scr_chatmode; extern cvar_t scr_chatmodecvar; +extern cvar_t vid_conautoscale; // console size manipulation callbacks void GLVID_Console_Resize(void) { extern cvar_t vid_conwidth, vid_conheight; + int cwidth, cheight; + float xratio; + float yratio=0; + cwidth = vid_conwidth.value; + cheight = vid_conheight.value; - vid.width = vid.conwidth = vid_conwidth.value; - vid.height = vid.conheight = vid_conheight.value; + xratio = vid_conautoscale.value; + if (xratio > 0) + { + char *s = strchr(vid_conautoscale.string, ' '); + if (s) + yratio = atof(s + 1); + + if (yratio <= 0) + yratio = xratio; + + xratio = 1 / xratio; + yratio = 1 / yratio; + + //autoscale overrides conwidth/height (without actually changing them) + cwidth = glwidth; + cheight = glheight; + } + else + { + xratio = 1; + yratio = 1; + } + + + if (!cwidth) + cwidth = glwidth; + if (!cheight) + cheight = glheight; + + cwidth*=xratio; + cheight*=yratio; + + if (cwidth < 320) + cwidth = 320; + if (cheight < 200) + cheight = 200; + + vid.width = vid.conwidth = cwidth; + vid.height = vid.conheight = cheight; vid.recalc_refdef = true; Con_CheckResize(); @@ -65,7 +108,7 @@ void GLVID_Conheight_Callback(struct cvar_s *var, char *oldvalue) Cvar_ForceSet(var, "1536"); return; } - if (var->value < 200) //lower would be wrong + if (var->value < 200 && var->value) //lower would be wrong { Cvar_ForceSet(var, "200"); return; @@ -82,7 +125,7 @@ void GLVID_Conwidth_Callback(struct cvar_s *var, char *oldvalue) Cvar_ForceSet(var, "2048"); return; } - if (var->value < 320) //lower would be wrong + if (var->value < 320 && var->value) //lower would be wrong { Cvar_ForceSet(var, "320"); return; @@ -93,26 +136,7 @@ void GLVID_Conwidth_Callback(struct cvar_s *var, char *oldvalue) void GLVID_Conautoscale_Callback(struct cvar_s *var, char *oldvalue) { - extern cvar_t vid_conwidth, vid_conheight; - - float xratio, yratio = 0; - - xratio = var->value; - if (xratio > 0) - { - char *s = strchr(var->string, ' '); - if (s) - yratio = atof(s + 1); - - if (yratio <= 0) - yratio = xratio; - - xratio = 1 / xratio; - yratio = 1 / yratio; - - Cvar_SetValue(&vid_conwidth, glwidth * xratio); - Cvar_SetValue(&vid_conheight, glheight * yratio); - } + GLVID_Console_Resize(); } /* diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 1d312dced..253e761a9 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -45,16 +45,6 @@ cvar_t r_vertexlight = SCVAR("r_vertexlight", "0"); #define Com_sprintf snprintf #define clamp(v,min, max) (v) = (((v)<(min))?(min):(((v)>(max))?(max):(v))); -int FS_LoadFile(char *name, void **file) -{ - *file = COM_LoadMallocFile(name); - return com_filesize; -} -void FS_FreeFile(void *file) -{ - BZ_Free(file); -} - typedef union { float f; unsigned int i; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 939b067b9..e4ef31b30 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -116,26 +116,30 @@ typedef struct { builtin_t pr_builtin[1024]; extern BuiltinList_t BuiltinList[]; +struct { + func_t ChatMessage; + + func_t getplayerstat[MAX_CL_STATS]; + func_t getplayerstati[MAX_CL_STATS]; + + func_t UserCmd, ParseClientCommand, ParseConnectionlessPacket; + func_t ConsoleCmd; + func_t UserInfo_Changed; + func_t localinfoChanged; + + func_t PausedTic; + func_t ShouldPause; + + func_t ClassChangeWeapon; +} gfuncs; +func_t getplayerstat[MAX_CL_STATS]; +func_t getplayerstati[MAX_CL_STATS]; func_t SpectatorConnect; func_t SpectatorThink; func_t SpectatorDisconnect; -func_t ChatMessage; - -func_t getplayerstat[MAX_CL_STATS]; -func_t getplayerstati[MAX_CL_STATS]; - -func_t mod_UserCmd, SV_ParseClientCommand, SV_ParseConnectionlessPacket; -func_t mod_ConsoleCmd; -func_t UserInfo_Changed; -func_t localinfoChanged; - -func_t pr_SV_PausedTic; -func_t pr_SV_ShouldPause; - func_t SV_PlayerPhysicsQC; //DP's DP_SV_PLAYERPHYSICS extension func_t EndFrameQC; -func_t pr_ClassChangeWeapon; qboolean pr_items2; @@ -459,6 +463,14 @@ void PR_Deinit(void) Z_FreeTags(Z_QC_TAG); } svprogfuncs=NULL; + + //clear out function pointers (so changing game modes cannot lead to confusions) + memset(&gfuncs, 0, sizeof(gfuncs)); + memset(&getplayerstat, 0, sizeof(getplayerstat)); + memset(&getplayerstati, 0, sizeof(getplayerstati)); + SpectatorConnect = 0; + SpectatorThink = 0; + SpectatorDisconnect = 0; } @@ -560,18 +572,18 @@ void PR_LoadGlabalStruct(void) getplayerstati[i] = PR_FindFunction(svprogfuncs, va("SetPlayerStat%ii", i), PR_ANY); } - SV_ParseClientCommand = PR_FindFunction(svprogfuncs, "SV_ParseClientCommand", PR_ANY); - SV_ParseConnectionlessPacket = PR_FindFunction(svprogfuncs, "SV_ParseConnectionlessPacket", PR_ANY); + gfuncs.ParseClientCommand = PR_FindFunction(svprogfuncs, "SV_ParseClientCommand", PR_ANY); + gfuncs.ParseConnectionlessPacket = PR_FindFunction(svprogfuncs, "SV_ParseConnectionlessPacket", PR_ANY); - UserInfo_Changed = PR_FindFunction(svprogfuncs, "UserInfo_Changed", PR_ANY); - localinfoChanged = PR_FindFunction(svprogfuncs, "localinfoChanged", PR_ANY); - ChatMessage = PR_FindFunction(svprogfuncs, "ChatMessage", PR_ANY); - mod_UserCmd = PR_FindFunction(svprogfuncs, "UserCmd", PR_ANY); - mod_ConsoleCmd = PR_FindFunction(svprogfuncs, "ConsoleCmd", PR_ANY); + gfuncs.UserInfo_Changed = PR_FindFunction(svprogfuncs, "UserInfo_Changed", PR_ANY); + gfuncs.localinfoChanged = PR_FindFunction(svprogfuncs, "localinfoChanged", PR_ANY); + gfuncs.ChatMessage = PR_FindFunction(svprogfuncs, "ChatMessage", PR_ANY); + gfuncs.UserCmd = PR_FindFunction(svprogfuncs, "UserCmd", PR_ANY); + gfuncs.ConsoleCmd = PR_FindFunction(svprogfuncs, "ConsoleCmd", PR_ANY); - pr_SV_PausedTic = PR_FindFunction(svprogfuncs, "SV_PausedTic", PR_ANY); - pr_SV_ShouldPause = PR_FindFunction(svprogfuncs, "SV_ShouldPause", PR_ANY); - pr_ClassChangeWeapon = PR_FindFunction(svprogfuncs, "ClassChangeWeapon", PR_ANY); + gfuncs.PausedTic = PR_FindFunction(svprogfuncs, "SV_PausedTic", PR_ANY); + gfuncs.ShouldPause = PR_FindFunction(svprogfuncs, "SV_ShouldPause", PR_ANY); + gfuncs.ClassChangeWeapon = PR_FindFunction(svprogfuncs, "ClassChangeWeapon", PR_ANY); if (pr_no_playerphysics.value) SV_PlayerPhysicsQC = 0; @@ -859,7 +871,7 @@ void PR_ApplyCompilation_f (void) PR_LoadGlabalStruct(); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; SV_ClearWorld (); @@ -1368,14 +1380,16 @@ void Q_InitProgs(void) qboolean PR_QCChat(char *text, int say_type) { - globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + globalvars_t *pr_globals; - if (!ChatMessage || pr_imitatemvdsv.value >= 0) + if (!gfuncs.ChatMessage || pr_imitatemvdsv.value >= 0) return false; + pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, text); G_FLOAT(OFS_PARM1) = say_type; - PR_ExecuteProgram (svprogfuncs, ChatMessage); + PR_ExecuteProgram (svprogfuncs, gfuncs.ChatMessage); if (G_FLOAT(OFS_RETURN)) return true; @@ -1386,13 +1400,13 @@ qboolean PR_GameCodePausedTic(float pausedtime) { //notications to the gamecode that the server is paused. globalvars_t *pr_globals; - if (!svprogfuncs || !pr_SV_ShouldPause) + if (!svprogfuncs || !gfuncs.ShouldPause) return false; pr_globals = PR_globals(svprogfuncs, PR_CURRENT); G_FLOAT(OFS_PARM0) = pausedtime; - PR_ExecuteProgram (svprogfuncs, pr_SV_PausedTic); + PR_ExecuteProgram (svprogfuncs, gfuncs.PausedTic); if (G_FLOAT(OFS_RETURN)) return true; @@ -1402,7 +1416,7 @@ qboolean PR_ShouldTogglePause(client_t *initiator, qboolean newpaused) { globalvars_t *pr_globals; - if (!svprogfuncs || !pr_SV_ShouldPause) + if (!svprogfuncs || !gfuncs.ShouldPause) return true; pr_globals = PR_globals(svprogfuncs, PR_CURRENT); @@ -1412,7 +1426,7 @@ qboolean PR_ShouldTogglePause(client_t *initiator, qboolean newpaused) else pr_global_struct->self = 0; G_FLOAT(OFS_PARM0) = newpaused; - PR_ExecuteProgram (svprogfuncs, pr_SV_ShouldPause); + PR_ExecuteProgram (svprogfuncs, gfuncs.ShouldPause); return G_FLOAT(OFS_RETURN); } @@ -1424,13 +1438,13 @@ qboolean PR_GameCodePacket(char *s) client_t *cl; char adr[MAX_ADR_SIZE]; - if (!SV_ParseConnectionlessPacket) + if (!gfuncs.ParseConnectionlessPacket) return false; if (!svprogfuncs) return false; pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; // check for packets from connected clients pr_global_struct->self = 0; @@ -1449,7 +1463,7 @@ qboolean PR_GameCodePacket(char *s) G_INT(OFS_PARM0) = PR_TempString(svprogfuncs, NET_AdrToString (adr, sizeof(adr), net_from)); G_INT(OFS_PARM1) = PR_TempString(svprogfuncs, s); - PR_ExecuteProgram (svprogfuncs, SV_ParseConnectionlessPacket); + PR_ExecuteProgram (svprogfuncs, gfuncs.ParseConnectionlessPacket); return G_FLOAT(OFS_RETURN); } @@ -1464,15 +1478,15 @@ qboolean PR_KrimzonParseCommand(char *s) if (!svprogfuncs) return false; - if (SV_ParseClientCommand) + if (gfuncs.ParseClientCommand) { //the QC is expected to send it back to use via a builtin. pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, s); - PR_ExecuteProgram (svprogfuncs, SV_ParseClientCommand); + PR_ExecuteProgram (svprogfuncs, gfuncs.ParseClientCommand); return true; } @@ -1493,29 +1507,29 @@ qboolean PR_UserCmd(char *s) if (!svprogfuncs) return false; - if (SV_ParseClientCommand) + if (gfuncs.ParseClientCommand) { //the QC is expected to send it back to use via a builtin. pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, s); - PR_ExecuteProgram (svprogfuncs, SV_ParseClientCommand); + PR_ExecuteProgram (svprogfuncs, gfuncs.ParseClientCommand); return true; } #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) { - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); Q1QVM_ClientCommand(); return true; //qvm can print something if it wants } #endif - if (mod_UserCmd && pr_imitatemvdsv.value >= 0) + if (gfuncs.UserCmd && pr_imitatemvdsv.value >= 0) { //we didn't recognise it. see if the mod does. //ktpro bug warning: @@ -1529,11 +1543,11 @@ qboolean PR_UserCmd(char *s) } pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, s); - PR_ExecuteProgram (svprogfuncs, mod_UserCmd); + PR_ExecuteProgram (svprogfuncs, gfuncs.UserCmd); return !!G_FLOAT(OFS_RETURN); } @@ -1562,15 +1576,15 @@ qboolean PR_ConsoleCmd(void) if (svprogfuncs) { pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - if (mod_ConsoleCmd && pr_imitatemvdsv.value >= 0) + if (gfuncs.ConsoleCmd && pr_imitatemvdsv.value >= 0) { if (sv_redirected != RD_OBLIVION) { - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); } - PR_ExecuteProgram (svprogfuncs, mod_ConsoleCmd); + PR_ExecuteProgram (svprogfuncs, gfuncs.ConsoleCmd); return (int) G_FLOAT(OFS_RETURN); } } @@ -1580,37 +1594,37 @@ qboolean PR_ConsoleCmd(void) void PR_ClientUserInfoChanged(char *name, char *oldivalue, char *newvalue) { - if (UserInfo_Changed && pr_imitatemvdsv.value >= 0) + if (gfuncs.UserInfo_Changed && pr_imitatemvdsv.value >= 0) { globalvars_t *pr_globals; pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); G_INT(OFS_PARM0) = PR_TempString(svprogfuncs, name); G_INT(OFS_PARM1) = PR_TempString(svprogfuncs, oldivalue); G_INT(OFS_PARM2) = PR_TempString(svprogfuncs, newvalue); - PR_ExecuteProgram (svprogfuncs, UserInfo_Changed); + PR_ExecuteProgram (svprogfuncs, gfuncs.UserInfo_Changed); } } void PR_LocalInfoChanged(char *name, char *oldivalue, char *newvalue) { - if (localinfoChanged && sv.state && pr_imitatemvdsv.value >= 0) + if (gfuncs.localinfoChanged && sv.state && pr_imitatemvdsv.value >= 0) { globalvars_t *pr_globals; pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); G_INT(OFS_PARM0) = PR_TempString(svprogfuncs, name); G_INT(OFS_PARM1) = PR_TempString(svprogfuncs, oldivalue); G_INT(OFS_PARM2) = PR_TempString(svprogfuncs, newvalue); - PR_ExecuteProgram (svprogfuncs, localinfoChanged); + PR_ExecuteProgram (svprogfuncs, gfuncs.localinfoChanged); } } @@ -1944,7 +1958,7 @@ void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m) SV_LinkEdict (e, false); } } - //qw was fixed - it never sets the size of an alias model. + //qw was fixed - it never sets the size of an alias model, mostly because it doesn't know it. } } } @@ -2496,7 +2510,7 @@ void PF_sound (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (volume > 255) volume = 255; - SV_StartSound (entity, channel, sample, volume, attenuation); + SVQ1_StartSound (entity, channel, sample, volume, attenuation); } //an evil one from telejano. @@ -3648,8 +3662,8 @@ void PF_aim (progfuncs_t *prinst, struct globalvars_s *pr_globals) VectorCopy (P_VEC(v_forward), dir); VectorMA (start, 2048, dir, end); tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); - if (tr.ent && tr.ent->v->takedamage == DAMAGE_AIM - && (!teamplay.value || ent->v->team <=0 || ent->v->team != tr.ent->v->team) ) + if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM + && (!teamplay.value || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) ) { VectorCopy (P_VEC(v_forward), G_VECTOR(OFS_RETURN)); return; @@ -6696,10 +6710,10 @@ void PR_SetPlayerClass(client_t *cl, int classnum, qboolean fromqc) if (!fromqc) { cl->sendinfo = true; - if (cl->state == cs_spawned && pr_ClassChangeWeapon) + if (cl->state == cs_spawned && gfuncs.ClassChangeWeapon) { pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - PR_ExecuteProgram (svprogfuncs, pr_ClassChangeWeapon); + PR_ExecuteProgram (svprogfuncs, gfuncs.ClassChangeWeapon); } } } @@ -8542,14 +8556,14 @@ void PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals if (surf->flags & SURF_PLANEBACK) { - VectorSubtract(v1->position, v2->position, edgedir) + VectorSubtract(v1->position, v2->position, edgedir); CrossProduct(edgedir, surf->plane->normal, edgenormal); if (DotProduct(edgenormal, v1->position) > DotProduct(edgenormal, point)) break; } else { - VectorSubtract(v1->position, v2->position, edgedir) + VectorSubtract(v1->position, v2->position, edgedir); CrossProduct(edgedir, surf->plane->normal, edgenormal); if (DotProduct(edgenormal, v1->position) < DotProduct(edgenormal, point)) break; diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 4d3df0d9a..486ecfd6b 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -661,7 +661,7 @@ static int syscallqvm (void *offset, unsigned int mask, int fn, const int *arg) case G_SOUND: // ( int edn, int channel, char *samp, float vol, float att ) - SV_StartSound (Q1QVMPF_EdictNum(svprogfuncs, VM_LONG(arg[0])), VM_LONG(arg[1]), VM_POINTER(arg[2]), VM_FLOAT(arg[3])*255, VM_FLOAT(arg[4])); + SVQ1_StartSound (Q1QVMPF_EdictNum(svprogfuncs, VM_LONG(arg[0])), VM_LONG(arg[1]), VM_POINTER(arg[2]), VM_FLOAT(arg[3])*255, VM_FLOAT(arg[4])); break; case G_TRACELINE: @@ -1380,12 +1380,12 @@ void Q1QVM_ClientConnect(client_t *cl) strcpy(cl->name, cl->namebuf); } // call the spawn function - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); VM_Call(q1qvm, GAME_CLIENT_CONNECT, cl->spectator); // actually spawn the player - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); VM_Call(q1qvm, GAME_PUT_CLIENT_IN_SERVER, cl->spectator); } @@ -1399,7 +1399,7 @@ qboolean Q1QVM_GameConsoleCommand(void) //FIXME: if an rcon command from someone on the server, mvdsv sets self to match the ip of that player //this is not required (broken by proxies anyway) but is a nice handy feature - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; oldself = pr_global_struct->self; //these are usually useless oldother = pr_global_struct->other; //but its possible that someone makes a mod that depends on the 'mod' command working via redirectcmd+co //this at least matches mvdsv @@ -1421,7 +1421,7 @@ qboolean Q1QVM_ClientSay(edict_t *player, qboolean team) SV_EndRedirect(); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player); washandled = VM_Call(q1qvm, GAME_CLIENT_SAY, team); @@ -1435,7 +1435,7 @@ qboolean Q1QVM_UserInfoChanged(edict_t *player) if (!q1qvm) return false; - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player); return VM_Call(q1qvm, GAME_CLIENT_USERINFO_CHANGED); } diff --git a/engine/server/progs.h b/engine/server/progs.h index 683f4ac9f..093de6141 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -110,6 +110,7 @@ extern progparms_t svprogparms; extern progsnum_t svmainprogs; extern progsnum_t clmainprogs; #define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) +#define HLEDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,hledict_t,area) #define Q2EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,q2edict_t,area) #define Q3EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,q3serverEntity_t,area) diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 209d494b2..db8f2d94b 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -36,6 +36,13 @@ void SV_SavegameComment (char *text) kills[0] = '\0'; } else +#endif +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + { + sprintf (kills,"kills:moo"); + } + else #endif sprintf (kills,"kills:%3i/%3i", (int)pr_global_struct->killed_monsters, (int)pr_global_struct->total_monsters); memcpy (text+22, kills, strlen(kills)); @@ -404,8 +411,7 @@ void SV_Loadgame_f(void) sv.time = time; - pr_global_struct->time = sv.time; - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; fclose (f); @@ -663,7 +669,7 @@ qboolean SV_LoadLevelCache(char *level, char *startspot, qboolean ignoreplayers) PR_LoadGlabalStruct(); - pr_global_struct->time = sv.time = time; + pr_global_struct->time = sv.time = sv.physicstime = time; sv.starttime = Sys_DoubleTime() - sv.time; VFS_SEEK(f, modelpos); @@ -710,7 +716,7 @@ qboolean SV_LoadLevelCache(char *level, char *startspot, qboolean ignoreplayers) if (spawnparamglobals[j]) *spawnparamglobals[j] = host_client->spawn_parms[j]; } - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); ent->area.next = ent->area.prev = NULL; G_FLOAT(OFS_PARM0) = sv.time-host_client->spawninfotime; @@ -787,6 +793,14 @@ void SV_SaveLevelCache(qboolean dontharmgame) } #endif +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + { + SVHL_SaveLevelCache(name); + return; + } +#endif + f = fopen (name, "wb"); if (!f) { diff --git a/engine/server/server.h b/engine/server/server.h index dc1532dee..2d90d7c0b 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -115,7 +115,7 @@ typedef struct double time; double starttime; - float physicstime; //nq clients do so much better with times sent with physics than real. + double physicstime; //This is the time at which the physics were last run. int framenum; int lastcheck; // used by PF_checkclient @@ -370,9 +370,13 @@ typedef struct client_s int viewent; //fake the entity positioning. edict_t *edict; // EDICT_NUM(clientnum+1) +//additional game modes use additional edict pointers. this ensures that references are crashes. #ifdef Q2SERVER q2edict_t *q2edict; // EDICT_NUM(clientnum+1) #endif +#ifdef HLSERVER + struct hledict_s *hledict; +#endif int playercolor; int playerclass; @@ -691,6 +695,7 @@ typedef struct filteredip_s { typedef enum { GT_PROGS, //q1, qw, h2 are similar enough that we consider it only one game mode. (We don't support the h2 protocol) GT_Q1QVM, + GT_HALFLIFE, GT_QUAKE2, //q2 servers run from a q2 game dll GT_QUAKE3, //q3 servers run off the q3 qvm api GT_MAX @@ -1009,8 +1014,8 @@ void VARGS SV_Multicast (vec3_t origin, multicast_t to); #define FULLDIMENSIONMASK 0xffffffff void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int with, int without); -void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, - float attenuation); +void SV_StartSound (int entnum, vec3_t origin, int seenmask, int channel, char *sample, int volume, float attenuation); +void SVQ1_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation); void SV_PrintToClient(client_t *cl, int level, char *string); void VARGS SV_ClientPrintf (client_t *cl, int level, char *fmt, ...); void VARGS SV_ClientTPrintf (client_t *cl, int level, translation_t text, ...); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index d0e245d86..b9203628c 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -254,15 +254,17 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) int en; int currentsequence = client->netchan.outgoing_sequence; unsigned short mask; - globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + globalvars_t *pr_globals; edict_t *ent; qboolean writtenheader = false; //we don't check that we got some already - because this is delta compressed! - if (!(client->csqcactive)) + if (!(client->csqcactive) || !svprogfuncs) return; + pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + //FIXME: prioritise the list of csqc ents somehow csqcmsgbuffer.data = messagebuffer; @@ -700,7 +702,10 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t * if (newnum < oldnum) { // this is a new entity, send it from the baseline - ent = EDICT_NUM(svprogfuncs, newnum); + if (svprogfuncs) + ent = EDICT_NUM(svprogfuncs, newnum); + else + ent = NULL; //Con_Printf ("baseline %i\n", newnum); #ifdef PROTOCOLEXTENSIONS SV_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true, client->fteprotocolextensions); @@ -2685,7 +2690,12 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore else { clent = client->edict; - pvs = SV_Snapshot_SetupPVS(client); +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + pvs = SVHL_Snapshot_SetupPVS(client); + else +#endif + pvs = SV_Snapshot_SetupPVS(client); } host_client = client; @@ -2693,7 +2703,8 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore SV_Snapshot_Clear(pack); // send over the players in the PVS - SV_WritePlayersToClient (client, clent, pvs, msg); + if (svs.gametype != GT_HALFLIFE) + SV_WritePlayersToClient (client, clent, pvs, msg); // put other visible entities into either a packet_entities or a nails message @@ -2703,7 +2714,12 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore } else { - SV_Snapshot_BuildQ1(client, pack, pvs, clent, ignorepvs); +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + SVHL_Snapshot_Build(client, pack, pvs, clent, ignorepvs); + else +#endif + SV_Snapshot_BuildQ1(client, pack, pvs, clent, ignorepvs); } #ifdef NQPROT diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 1574361f7..641c887fd 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -540,6 +540,9 @@ void SV_UnspawnServer (void) //terminate the running server. } #ifdef Q2SERVER SVQ2_ShutdownGameProgs(); +#endif +#ifdef HLSERVER + SVHL_ShutdownGame(); #endif sv.worldmodel = NULL; sv.state = ss_dead; @@ -863,6 +866,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us sv.state = ss_loading; newgametype = svs.gametype; +#ifdef HLSERVER + if (SVHL_InitGame()) + newgametype = GT_HALFLIFE; + else +#endif #ifdef Q3SERVER if (SVQ3_InitGame()) newgametype = GT_QUAKE3; @@ -897,6 +905,10 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us } svs.gametype = newgametype; +#ifdef HLSERVER + if (newgametype != GT_HALFLIFE) + SVHL_ShutdownGame(); +#endif #ifdef Q3SERVER if (newgametype != GT_QUAKE3) SVQ3_ShutdownGame(); @@ -1053,6 +1065,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us case GT_QUAKE3: #ifdef Q3SERVER sv.allocated_client_slots = 32; +#endif + break; + case GT_HALFLIFE: +#ifdef HLSERVER + SVHL_SetupGame(); #endif break; } @@ -1218,6 +1235,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us break; case GT_QUAKE3: break; + case GT_HALFLIFE: +#ifdef HLSERVER + SVHL_SpawnEntities(file); +#endif + break; } BZ_Free(file); } @@ -1239,6 +1261,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us break; case GT_QUAKE3: break; + case GT_HALFLIFE: +#ifdef HLSERVER + SVHL_SpawnEntities(sv.worldmodel->entities); +#endif + break; } } @@ -1365,12 +1392,12 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us sv_player->xv->clientcolors = atoi(Info_ValueForKey(host_client->userinfo, "topcolor"))*16 + atoi(Info_ValueForKey(host_client->userinfo, "bottomcolor")); // call the spawn function - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); // actually spawn the player - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index fc42ceeca..a9f128fb9 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -487,6 +487,11 @@ void SV_DropClient (client_t *drop) case GT_QUAKE3: #ifdef Q3SERVER SVQ3_DropClient(drop); +#endif + break; + case GT_HALFLIFE: +#ifdef HLSERVER + SVHL_DropClient(drop); #endif break; } @@ -1935,9 +1940,26 @@ client_t *SVC_DirectConnect(void) } } + //set up the gamecode for this player, optionally drop them here edictnum = (newcl-svs.clients)+1; switch (svs.gametype) { +#ifdef HLSERVER + //fallthrough + case GT_HALFLIFE: + { + char reject[128]; + if (!SVHL_ClientConnect(newcl, adr, reject)) + { + SV_RejectMessage(protocol, "%s", reject); + return NULL; + } + } + + break; +#endif + + #ifdef VM_Q1 case GT_Q1QVM: #endif @@ -1948,37 +1970,6 @@ client_t *SVC_DirectConnect(void) #endif temp.edict = ent; - - - - - - // build a new connection - // accept the new client - // this is the only place a client_t is ever initialized, for q1 mods at least -#ifdef Q3SERVER - if (ISQ3CLIENT(newcl)) - { - Huff_PreferedCompressionCRC(); - temp.frameunion.q3frames = BZ_Malloc(Q3UPDATE_BACKUP*sizeof(*temp.frameunion.q3frames)); - } - else -#endif - { - temp.frameunion.frames = newcl->frameunion.frames; //don't touch these. - if (temp.frameunion.frames) - { - Con_Printf("Debug: frames were set?\n"); - Z_Free(temp.frameunion.frames); - } - - temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); - for (i = 0; i < UPDATE_BACKUP; i++) - { - temp.frameunion.frames[i].entities.max_entities = maxpacketentities; - temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities; - } - } break; #ifdef Q2SERVER @@ -1992,6 +1983,25 @@ client_t *SVC_DirectConnect(void) ge->ClientUserinfoChanged(q2ent, temp.userinfo); + + break; +#endif + default: + Sys_Error("Bad svs.gametype in SVC_DirectConnect"); + break; + } + + //initialise the client's frames, based on that client's protocol + switch(newcl->protocol) + { + case CP_QUAKE3: + Huff_PreferedCompressionCRC(); + if (temp.frameunion.q3frames) + Z_Free(temp.frameunion.q3frames); + temp.frameunion.q3frames = Z_Malloc(Q3UPDATE_BACKUP*sizeof(*temp.frameunion.q3frames)); + break; + + case CP_QUAKE2: // build a new connection // accept the new client // this is the only place a client_t is ever initialized @@ -2001,9 +2011,21 @@ client_t *SVC_DirectConnect(void) temp.frameunion.q2frames = Z_Malloc(sizeof(q2client_frame_t)*Q2UPDATE_BACKUP); break; -#endif + default: - Sys_Error("Bad svs.gametype in SVC_DirectConnect"); + temp.frameunion.frames = newcl->frameunion.frames; //don't touch these. + if (temp.frameunion.frames) + { + Con_Printf("Debug: frames were set?\n"); + Z_Free(temp.frameunion.frames); + } + + temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); + for (i = 0; i < UPDATE_BACKUP; i++) + { + temp.frameunion.frames[i].entities.max_entities = maxpacketentities; + temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities; + } break; } @@ -3063,7 +3085,7 @@ void SV_Impulse_f (void) if (!svprogfuncs) return; - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; svs.clients[i].state = cs_connected; @@ -3074,7 +3096,7 @@ void SV_Impulse_f (void) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, svs.clients[i].edict); PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, svs.clients[i].edict); PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); @@ -3708,7 +3730,7 @@ void Master_Heartbeat (void) } if (sv_reportheartbeats.value) - Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr)); + Con_Printf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr), sv_masterlist[i].cv.string); NET_SendPacket (NS_SERVER, strlen(string), string, sv_masterlist[i].adr); } @@ -3717,7 +3739,7 @@ void Master_Heartbeat (void) if (sv_listen_dp.value) //set listen to 1 to allow qw connections, 2 to allow nq connections too. { if (sv_reportheartbeats.value) - Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr)); + Con_Printf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr), sv_masterlist[i].cv.string); { char *str = "\377\377\377\377heartbeat DarkPlaces\x0A"; diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 175df5d67..7cec48f11 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -146,11 +146,11 @@ qboolean SV_RunThink (edict_t *ent) if (sv_nomsec.value>=2) //try and imitate nq as closeley as possible { thinktime = ent->v->nextthink; - if (thinktime <= 0 || thinktime > sv.time + host_frametime) + if (thinktime <= 0 || thinktime > sv.physicstime + host_frametime) return true; - if (thinktime < sv.time) - thinktime = sv.time; // don't let things stay in the past. + if (thinktime < sv.physicstime) + thinktime = sv.physicstime; // don't let things stay in the past. // it is possible to start that way // by a trigger with a local time. ent->v->nextthink = 0; @@ -171,11 +171,11 @@ qboolean SV_RunThink (edict_t *ent) thinktime = ent->v->nextthink; if (thinktime <= 0) return true; - if (thinktime > sv.time + host_frametime) + if (thinktime > sv.physicstime + host_frametime) return true; - if (thinktime < sv.time) - thinktime = sv.time; // don't let things stay in the past. + if (thinktime < sv.physicstime) + thinktime = sv.physicstime; // don't let things stay in the past. // it is possible to start that way // by a trigger with a local time. ent->v->nextthink = 0; @@ -214,7 +214,7 @@ void SV_Impact (edict_t *e1, edict_t *e2) old_self = pr_global_struct->self; old_other = pr_global_struct->other; - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; if (e1->v->touch && e1->v->solid != SOLID_NOT) { pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, e1); @@ -338,7 +338,7 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor - if (trace.ent->v->solid == SOLID_BSP) + if (((edict_t *)trace.ent)->v->solid == SOLID_BSP) { ent->v->flags = (int)ent->v->flags | FL_ONGROUND; ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, trace.ent); @@ -903,7 +903,7 @@ float l; VectorCopy (ent->v->origin, oldorg); VectorCopy (ent->v->angles, oldang); ent->v->nextthink = 0; - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.edicts); #ifdef VM_Q1 @@ -1034,7 +1034,7 @@ void SV_CheckWaterTransition (edict_t *ent) { if (ent->v->watertype == Q1CONTENTS_EMPTY) { // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + SVQ1_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); } ent->v->watertype = cont; ent->v->waterlevel = 1; @@ -1043,7 +1043,7 @@ void SV_CheckWaterTransition (edict_t *ent) { if (ent->v->watertype != Q1CONTENTS_EMPTY) { // just crossed into open - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + SVQ1_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); } ent->v->watertype = Q1CONTENTS_EMPTY; ent->v->waterlevel = cont; @@ -1183,9 +1183,9 @@ void SV_Physics_Step (edict_t *ent) if (hitsound) { if (progstype == PROG_H2) - SV_StartSound (ent, 0, "fx/thngland.wav", 255, 1); + SVQ1_StartSound (ent, 0, "fx/thngland.wav", 255, 1); else - SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); + SVQ1_StartSound (ent, 0, "demon/dland2.wav", 255, 1); } } } @@ -1204,7 +1204,7 @@ void SV_ProgStartFrame (void) // let the progs know that a new frame has started pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.edicts); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_StartFrame(); @@ -1732,8 +1732,8 @@ void SV_MoveChain(edict_t *ent, edict_t *movechain, float *initial_origin, float { vec3_t moveang, moveorg; int i; - VectorSubtract(ent->v->angles, initial_angle, moveang) - VectorSubtract(ent->v->origin, initial_origin, moveorg) + VectorSubtract(ent->v->angles, initial_angle, moveang); + VectorSubtract(ent->v->origin, initial_origin, moveorg); for(i=16;i && movechain != sv.edicts && !movechain->isfree;i--, movechain = PROG_TO_EDICT(svprogfuncs, movechain->xv->movechain)) { @@ -1791,7 +1791,7 @@ void SV_RunEntity (edict_t *ent) // // call standard client pre-think // - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) @@ -1876,7 +1876,7 @@ void SV_RunEntity (edict_t *ent) { SV_LinkEdict (ent, true); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) @@ -1970,16 +1970,15 @@ qboolean SV_Physics (void) int i; qboolean retouch; edict_t *ent; - static double old_time; - if (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM) //make tics multiples of sv_maxtic (defaults to 0.1) + if (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM && svs.gametype != GT_HALFLIFE) //make tics multiples of sv_maxtic (defaults to 0.1) { - host_frametime = sv.time - old_time; + host_frametime = sv.time - sv.physicstime; if (host_frametime<0) { if (host_frametime < -1) - old_time = sv.time; + sv.physicstime = sv.time; host_frametime = 0; } if (svs.gametype != GT_QUAKE3) @@ -1990,7 +1989,7 @@ qboolean SV_Physics (void) } if (host_frametime > sv_maxtic.value) host_frametime = sv_maxtic.value; - old_time = sv.time; + sv.physicstime = sv.time; sv.framenum++; @@ -2012,7 +2011,7 @@ qboolean SV_Physics (void) return false; } - if (/*sv.botsonthemap &&*/ progstype == PROG_QW) + if (svs.gametype != GT_HALFLIFE && /*sv.botsonthemap &&*/ progstype == PROG_QW) { //DP_SV_BOTCLIENT - make the bots move with qw physics. //They only move when there arn't any players on the server, but they should move at the right kind of speed if there are... hopefully @@ -2065,84 +2064,105 @@ qboolean SV_Physics (void) } } - // don't bother running a frame if sys_ticrate seconds haven't passed - host_frametime = realtime - old_time; - if (host_frametime < -1) - old_time = 0; - if (host_frametime < sv_mintic.value) - return false; - if (host_frametime > sv_maxtic.value) - host_frametime = sv_maxtic.value; - old_time = realtime; - - sv.physicstime = sv.time; - - pr_global_struct->frametime = host_frametime; - - SV_ProgStartFrame (); - - PR_RunThreads(); - - - retouch = (pr_nqglobal_struct->force_retouch && *pr_nqglobal_struct->force_retouch); - -// -// treat each object in turn -// even the world gets a chance to think -// - for (i=0 ; iisfree) + host_frametime = sv.time - sv.physicstime; + if (host_frametime < 0) + { + sv.physicstime = sv.time; + break; + } + if (host_frametime <= 0 || host_frametime < sv_mintic.value) + break; + if (host_frametime > ((/*sv_captic.value<=*/0)?1:sv_maxtic.value*5)) + { + //cap the distance to run physics + host_frametime = sv_maxtic.value; + sv.physicstime = sv.time; + } + else + { + if (host_frametime > sv_maxtic.value) + host_frametime = sv_maxtic.value; + sv.physicstime += host_frametime; + } + +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + { + SVHL_RunFrame(); continue; - - if (ent->solidtype != ent->v->solid) - { -// Con_Printf("Entity \"%s\" improperly changed solid type\n", svprogfuncs->stringtable+ent->v->classname); - SV_LinkEdict (ent, true); // a change of solidity should always relink the edict. someone messed up. } - else if (retouch) - SV_LinkEdict (ent, true); // force retouch even for stationary +#endif - if (i > 0 && i <= sv.allocated_client_slots) + pr_global_struct->frametime = host_frametime; + + SV_ProgStartFrame (); + + PR_RunThreads(); + + + retouch = (pr_nqglobal_struct->force_retouch && *pr_nqglobal_struct->force_retouch); + + // + // treat each object in turn + // even the world gets a chance to think + // + for (i=0 ; iisfree) + continue; + + if (ent->solidtype != ent->v->solid) { - SV_RunEntity(ent); - SV_RunNewmis (); + // Con_Printf("Entity \"%s\" improperly changed solid type\n", svprogfuncs->stringtable+ent->v->classname); + SV_LinkEdict (ent, true); // a change of solidity should always relink the edict. someone messed up. } - else - SV_LinkEdict(ent, true); - continue; // clients are run directly from packets + else if (retouch) + SV_LinkEdict (ent, true); // force retouch even for stationary + + if (i > 0 && i <= sv.allocated_client_slots) + { + if (!svs.clients[i-1].isindependant) + { + SV_RunEntity(ent); + SV_RunNewmis (); + } + else + SV_LinkEdict(ent, true); + continue; // clients are run directly from packets + } + + SV_RunEntity (ent); + SV_RunNewmis (); } - SV_RunEntity (ent); - SV_RunNewmis (); - } - - if (retouch) - pr_global_struct->force_retouch-=1; + if (retouch) + pr_global_struct->force_retouch-=1; #ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.edicts); - pr_global_struct->time = sv.time; - Q1QVM_EndFrame(); - } - else + if (svs.gametype == GT_Q1QVM) + { + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); + pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.edicts); + pr_global_struct->time = sv.physicstime; + Q1QVM_EndFrame(); + } + else #endif - if (EndFrameQC) - { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.edicts); - pr_global_struct->time = sv.time; - PR_ExecuteProgram (svprogfuncs, EndFrameQC); - } + if (EndFrameQC) + { + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); + pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.edicts); + pr_global_struct->time = sv.physicstime; + PR_ExecuteProgram (svprogfuncs, EndFrameQC); + } - NPP_Flush(); //flush it just in case there was an error and we stopped preparsing. This is only really needed while debugging. + NPP_Flush(); //flush it just in case there was an error and we stopped preparsing. This is only really needed while debugging. + + } return false; } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index c9bc6b83c..a0caf55af 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -663,24 +663,27 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int } if (svprogfuncs) + { if (!((int)client->edict->xv->dimension_see & dimension_mask)) continue; - if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) { - vec3_t delta; - VectorSubtract(origin, client->edict->v->origin, delta); - if (Length(delta) <= 1024) - goto inrange; - } - - // -1 is because pvs rows are 1 based, not 0 based like leafs - if (mask != sv.pvs) - { - leafnum = sv.worldmodel->funcs.LeafnumForPoint (sv.worldmodel, client->edict->v->origin)-1; - if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) { - // Con_Printf ("PVS supressed multicast\n"); - continue; + vec3_t delta; + VectorSubtract(origin, client->edict->v->origin, delta); + if (Length(delta) <= 1024) + goto inrange; + } + + // -1 is because pvs rows are 1 based, not 0 based like leafs + if (mask != sv.pvs) + { + leafnum = sv.worldmodel->funcs.LeafnumForPoint (sv.worldmodel, client->edict->v->origin)-1; + if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + { + // Con_Printf ("PVS supressed multicast\n"); + continue; + } } } @@ -774,15 +777,12 @@ Larger attenuations will drop off. (max 4 attenuation) ================== */ -void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, - float attenuation) +void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sample, int volume, float attenuation) { int sound_num; int extfield_mask; int qwflags; int i; - int ent; - vec3_t origin; qboolean use_phs; qboolean reliable = false; int requiredextensions = 0; @@ -817,8 +817,6 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, return; } - ent = NUM_FOR_EDICT(svprogfuncs, entity); - if ((channel & 8) || !sv_phs.value) // no PHS flag { if (channel & 8) @@ -829,17 +827,6 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, else use_phs = true; - // use the entity origin unless it is a bmodel, in which case use its bbox middle - if (entity->v->solid == SOLID_BSP) - { - for (i=0 ; i<3 ; i++) - origin[i] = entity->v->origin[i]+0.5*(entity->v->mins[i]+entity->v->maxs[i]); - } - else - { - VectorCopy (entity->v->origin, origin); - } - // if (channel == CHAN_BODY || channel == CHAN_VOICE) // reliable = true; @@ -931,9 +918,26 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, MSG_WriteCoord (&sv.nqmulticast, origin[i]); #endif if (use_phs) - SV_MulticastProtExt(origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS, entity->xv->dimension_seen, requiredextensions, 0); + SV_MulticastProtExt(origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS, seenmask, requiredextensions, 0); else - SV_MulticastProtExt(origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL, entity->xv->dimension_seen, requiredextensions, 0); + SV_MulticastProtExt(origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL, seenmask, requiredextensions, 0); +} + +void SVQ1_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation) +{ + int i; + vec3_t origin; + if (entity->v->solid == SOLID_BSP) + { + for (i=0 ; i<3 ; i++) + origin[i] = entity->v->origin[i]+0.5*(entity->v->mins[i]+entity->v->maxs[i]); + } + else + { + VectorCopy (entity->v->origin, origin); + } + + SV_StartSound(NUM_FOR_EDICT(svprogfuncs, entity), origin, entity->xv->dimension_seen, channel, sample, volume, attenuation); } /* @@ -975,6 +979,9 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum) ent = client->edict; + if (!ent) + return; + // send a damage message if the player got hit this frame if (ent->v->dmg_take || ent->v->dmg_save) { @@ -1379,80 +1386,90 @@ void SV_UpdateClientStats (client_t *client, int pnum) if (client->spectator && client->spec_track > 0) ent = svs.clients[client->spec_track - 1].edict; - statsf[STAT_HEALTH] = ent->v->health; //sorry, but mneh - statsi[STAT_WEAPON] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel)); - if (host_client->fteprotocolextensions & PEXT_MODELDBL) +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) { - if ((unsigned)statsi[STAT_WEAPON] >= 512) - statsi[STAT_WEAPON] = 0; - } - else - { - if ((unsigned)statsi[STAT_WEAPON] >= 256) - statsi[STAT_WEAPON] = 0; - } - 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; - if (!client->spectator) - { - statsi[STAT_ACTIVEWEAPON] = ent->v->weapon; - if (client->csqcactive) - statsi[STAT_WEAPONFRAME] = ent->v->weaponframe; - } + SVHL_BuildStats(client, statsi, statsf, statss); - // stuff the sigil bits into the high bits of items for sbar - if (pr_items2) - statsi[STAT_ITEMS] = (int)ent->v->items | ((int)ent->xv->items2 << 23); + pr_globals = NULL; + } else - statsi[STAT_ITEMS] = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28); - - statsf[STAT_VIEWHEIGHT] = ent->v->view_ofs[2]; -#ifdef PEXT_VIEW2 - if (ent->xv->view2) - statsi[STAT_VIEW2] = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, ent->xv->view2)); - else - statsi[STAT_VIEW2] = 0; #endif - - if (!ent->xv->viewzoom) - statsi[STAT_VIEWZOOM] = 255; - else - statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255; - - if (host_client->protocol == SCP_DARKPLACES7) { - float *statsfi = (float*)statsi; -// statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall - statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value; - statsfi[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value; - statsfi[STAT_MOVEVARS_TICRATE] = 72; - statsfi[STAT_MOVEVARS_TIMESCALE] = sv_gamespeed.value; - statsfi[STAT_MOVEVARS_GRAVITY] = sv_gravity.value; - statsfi[STAT_MOVEVARS_STOPSPEED] = sv_stopspeed.value; - statsfi[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed; - statsfi[STAT_MOVEVARS_SPECTATORMAXSPEED] = sv_spectatormaxspeed.value; - statsfi[STAT_MOVEVARS_ACCELERATE] = sv_accelerate.value; - statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value; - statsfi[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value; - statsfi[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity; - statsfi[STAT_MOVEVARS_JUMPVELOCITY] = 280;//sv_jumpvelocity.value; //bah - statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value; - statsfi[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed; - statsfi[STAT_MOVEVARS_STEPHEIGHT] = 18; - statsfi[STAT_MOVEVARS_AIRACCEL_QW] = 1; - statsfi[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_gravity.value; + statsf[STAT_HEALTH] = ent->v->health; //sorry, but mneh + statsi[STAT_WEAPON] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel)); + if (host_client->fteprotocolextensions & PEXT_MODELDBL) + { + if ((unsigned)statsi[STAT_WEAPON] >= 512) + statsi[STAT_WEAPON] = 0; + } + else + { + if ((unsigned)statsi[STAT_WEAPON] >= 256) + statsi[STAT_WEAPON] = 0; + } + 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; + if (!client->spectator) + { + statsi[STAT_ACTIVEWEAPON] = ent->v->weapon; + if (client->csqcactive) + statsi[STAT_WEAPONFRAME] = ent->v->weaponframe; + } + + // stuff the sigil bits into the high bits of items for sbar + if (pr_items2) + 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]; + #ifdef PEXT_VIEW2 + if (ent->xv->view2) + statsi[STAT_VIEW2] = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, ent->xv->view2)); + else + statsi[STAT_VIEW2] = 0; + #endif + + if (!ent->xv->viewzoom) + statsi[STAT_VIEWZOOM] = 255; + else + statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255; + + if (host_client->protocol == SCP_DARKPLACES7) + { + float *statsfi = (float*)statsi; + // statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall + statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value; + statsfi[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value; + statsfi[STAT_MOVEVARS_TICRATE] = 72; + statsfi[STAT_MOVEVARS_TIMESCALE] = sv_gamespeed.value; + statsfi[STAT_MOVEVARS_GRAVITY] = sv_gravity.value; + statsfi[STAT_MOVEVARS_STOPSPEED] = sv_stopspeed.value; + statsfi[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed; + statsfi[STAT_MOVEVARS_SPECTATORMAXSPEED] = sv_spectatormaxspeed.value; + statsfi[STAT_MOVEVARS_ACCELERATE] = sv_accelerate.value; + statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value; + statsfi[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value; + statsfi[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity; + statsfi[STAT_MOVEVARS_JUMPVELOCITY] = 280;//sv_jumpvelocity.value; //bah + statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value; + statsfi[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed; + statsfi[STAT_MOVEVARS_STEPHEIGHT] = 18; + statsfi[STAT_MOVEVARS_AIRACCEL_QW] = 1; + statsfi[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_gravity.value; + } + + SV_UpdateQCStats(ent, statsi, statss, statsf); + + //dmw tweek for stats + pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); } - - SV_UpdateQCStats(ent, statsi, statss, statsf); - - //dmw tweek for stats - pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); - m = MAX_QW_STATS; if (client->fteprotocolextensions & PEXT_HEXEN2) m = MAX_CL_STATS; @@ -1698,12 +1715,15 @@ SV_UpdateToReliableMessages */ void SV_UpdateToReliableMessages (void) { - volatile float newval; // needed to ensure 32/32-bit fp comparisons int i, j; client_t *client, *sp; edict_t *ent; char *name; + float curgrav; + float curspeed; + int curfrags; + // check for changes to be sent over the reliable streams to all clients for (i=0, host_client = svs.clients ; iedict; + + curfrags = host_client->edict->v->frags; + curgrav = ent->xv->gravity*sv_gravity.value; + curspeed = ent->xv->maxspeed; + if (progstype != PROG_QW) + { + if (!curgrav) + curgrav = 1; + if (!curspeed) + curspeed = sv_maxspeed.value; + } + if (ent->xv->hasted) + curspeed*=ent->xv->hasted; + } + else + { + curgrav = sv_gravity.value; + curspeed = sv_maxspeed.value; + curfrags = 0; + } +#ifdef SVCHAT //enforce a no moving time when chatting. Prevent client prediction going mad. + if (host_client->chat.active) + curspeed = 0; +#endif + if (!ISQ2CLIENT(host_client)) { if (host_client->sendinfo) @@ -1784,7 +1832,7 @@ void SV_UpdateToReliableMessages (void) host_client->sendinfo = false; SV_FullClientUpdate (host_client, &sv.reliable_datagram, host_client->fteprotocolextensions); } - if (host_client->old_frags != (int)host_client->edict->v->frags) + if (host_client->old_frags != curfrags) { for (j=0, client = svs.clients ; jedict->v->frags); + ClientReliableWrite_Short(client, curfrags); } if (sv.mvdrecording) @@ -1802,45 +1850,24 @@ void SV_UpdateToReliableMessages (void) MVDWrite_Begin(dem_all, 0, 4); MSG_WriteByte((sizebuf_t*)demo.dbuf, svc_updatefrags); MSG_WriteByte((sizebuf_t*)demo.dbuf, i); - MSG_WriteShort((sizebuf_t*)demo.dbuf, host_client->edict->v->frags); + MSG_WriteShort((sizebuf_t*)demo.dbuf, curfrags); } - host_client->old_frags = host_client->edict->v->frags; + host_client->old_frags = curfrags; } { - // maxspeed/entgravity changes - ent = host_client->edict; - - newval = ent->xv->gravity*sv_gravity.value; - if (progstype != PROG_QW) - { - if (!newval) - newval = 1; - } - - if (host_client->entgravity != newval) + if (host_client->entgravity != curgrav) { if (ISQWCLIENT(host_client)) { sp = SV_SplitClientDest(host_client, svc_entgravity, 5); - ClientReliableWrite_Float(sp, newval/movevars.gravity); //lie to the client in a cunning way + ClientReliableWrite_Float(sp, curgrav/movevars.gravity); //lie to the client in a cunning way } - host_client->entgravity = newval; + host_client->entgravity = curgrav; } - newval = ent->xv->maxspeed; - if (progstype != PROG_QW) - { - if (!newval) - newval = sv_maxspeed.value; - } - if (ent->xv->hasted) - newval*=ent->xv->hasted; - #ifdef SVCHAT //enforce a no moving time when chatting. Prevent client prediction going mad. - if (host_client->chat.active) - newval = 0; - #endif - if (host_client->maxspeed != newval) + + if (host_client->maxspeed != curspeed) { //MSVC can really suck at times (optimiser bug) if (ISQWCLIENT(host_client)) { @@ -1860,15 +1887,15 @@ void SV_UpdateToReliableMessages (void) ClientReliableWrite_Begin (sp, svcfte_choosesplitclient, 7); ClientReliableWrite_Byte (sp, pnum); ClientReliableWrite_Byte (sp, svc_maxspeed); - ClientReliableWrite_Float(sp, newval); + ClientReliableWrite_Float(sp, curspeed); } else { ClientReliableWrite_Begin(host_client, svc_maxspeed, 5); - ClientReliableWrite_Float(host_client, newval); + ClientReliableWrite_Float(host_client, curspeed); } } - host_client->maxspeed = newval; + host_client->maxspeed = curspeed; } } } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index d7d3133e2..02319f3e3 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -261,12 +261,21 @@ void SV_New_f (void) splitnum = 0; for (split = host_client; split; split = split->controlled) { -#ifdef Q2SERVER - if (!svprogfuncs) - playernum = Q2NUM_FOR_EDICT(split->q2edict)-1; - else + switch(svs.gametype) + { +#ifdef HLSERVER + case GT_HALFLIFE: + playernum = split - svs.clients; + break; #endif +#ifdef Q2SERVER + case GT_QUAKE2: + playernum = Q2NUM_FOR_EDICT(split->q2edict)-1; + break; +#endif + default: playernum = NUM_FOR_EDICT(svprogfuncs, split->edict)-1; + } if (sv.demostate) { playernum = (MAX_CLIENTS-1-splitnum)|128; @@ -1241,6 +1250,8 @@ void SV_Spawn_f (void) client_t *client, *split; edict_t *ent; + int secret_total, secret_found, monsters_total, monsters_found; + if (host_client->state != cs_connected) { Con_Printf ("Spawn not valid -- already spawned\n"); @@ -1302,45 +1313,66 @@ void SV_Spawn_f (void) } } - // set up the edict - for (split = host_client; split; split = split->controlled) +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) { - ent = split->edict; - - if (split->istobeloaded) //minimal setup + for (split = host_client; split; split = split->controlled) { - split->entgravity = ent->xv->gravity; - split->maxspeed = ent->xv->maxspeed; - } - else - { - SV_SetUpClientEdict(split, ent); + split->entgravity = 1; + split->maxspeed = 320; } - // - // force stats to be updated - // - memset (host_client->statsi, 0, sizeof(host_client->statsi)); - memset (host_client->statsf, 0, sizeof(host_client->statsf)); - memset (host_client->statss, 0, sizeof(host_client->statss)); + secret_total = 0; + secret_found = 0; + monsters_total = 0; + monsters_found = 0; } + else +#endif + { + // set up the edict + for (split = host_client; split; split = split->controlled) + { + ent = split->edict; + if (split->istobeloaded) //minimal setup + { + split->entgravity = ent->xv->gravity; + split->maxspeed = ent->xv->maxspeed; + } + else + { + SV_SetUpClientEdict(split, ent); + } + + // + // force stats to be updated + // + memset (host_client->statsi, 0, sizeof(host_client->statsi)); + memset (host_client->statsf, 0, sizeof(host_client->statsf)); + memset (host_client->statss, 0, sizeof(host_client->statss)); + } + + secret_total = pr_global_struct->total_secrets; + secret_found = pr_global_struct->found_secrets; + monsters_total = pr_global_struct->total_monsters; + monsters_found = pr_global_struct->killed_monsters; + } ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS); - ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets); + ClientReliableWrite_Long (host_client, secret_total); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS); - ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters); + ClientReliableWrite_Long (host_client, monsters_total); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_SECRETS); - ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets); + ClientReliableWrite_Long (host_client, secret_found); ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6); ClientReliableWrite_Byte (host_client, STAT_MONSTERS); - ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters); - + ClientReliableWrite_Long (host_client, monsters_found); // get the client to check and download skins // when that is completed, a begin command will be issued ClientReliableWrite_Begin (host_client, svc_stufftext, 8); @@ -1385,42 +1417,94 @@ void SV_Begin_Core(client_t *split) int i; if (progstype == PROG_H2 && host_client->playerclass) host_client->edict->xv->playerclass = host_client->playerclass; //make sure it's set the same as the userinfo -#ifdef Q2SERVER - if (ge) - { - ge->ClientBegin(split->q2edict); - split->istobeloaded = false; - } - else -#endif - if (split->istobeloaded) - { - func_t f; - split->istobeloaded = false; - f = PR_FindFunction(svprogfuncs, "RestoreGame", PR_ANY); - if (f) +#ifdef Q2SERVER + if (ge) + { + ge->ClientBegin(split->q2edict); + split->istobeloaded = false; + } + else +#endif + if (split->istobeloaded) + { + func_t f; + split->istobeloaded = false; + + f = PR_FindFunction(svprogfuncs, "RestoreGame", PR_ANY); + if (f) + { + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); + PR_ExecuteProgram (svprogfuncs, f); + } + } + else + { + if (split->spectator) + { + SV_SpawnSpectator (); + + if (SpectatorConnect) { - pr_global_struct->time = sv.time; + //keep the spectator tracking the player from the previous map + if (split->spec_track > 0) + split->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, svs.clients[split->spec_track-1].edict); + else + split->edict->v->goalentity = 0; + + + // copy spawn parms out of the client_t + for (i=0 ; i< NUM_SPAWN_PARMS ; i++) + { + if (spawnparamglobals[i]) + *spawnparamglobals[i] = split->spawn_parms[i]; + } + + // call the spawn function + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); - PR_ExecuteProgram (svprogfuncs, f); + PR_ExecuteProgram (svprogfuncs, SpectatorConnect); } } else { - if (split->spectator) +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) { - SV_SpawnSpectator (); - - if (SpectatorConnect) + SVHL_PutClientInServer(split); + } + else +#endif + if (svprogfuncs) + { + eval_t *eval, *eval2; + eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0); + if (eval && split->spawninfo) { - //keep the spectator tracking the player from the previous map - if (split->spec_track > 0) - split->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, svs.clients[split->spec_track-1].edict); - else - split->edict->v->goalentity = 0; - + globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + int j; + edict_t *ent; + ent = split->edict; + j = strlen(split->spawninfo); + SV_UnlinkEdict(ent); + svprogfuncs->restoreent(svprogfuncs, split->spawninfo, &j, ent); + eval2 = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "stats_restored", NULL); + if (eval2) + eval2->_float = 1; + for (j=0 ; j< NUM_SPAWN_PARMS ; j++) + { + if (spawnparamglobals[j]) + *spawnparamglobals[j] = split->spawn_parms[j]; + } + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); + G_FLOAT(OFS_PARM0) = sv.time - split->spawninfotime; + PR_ExecuteProgram(svprogfuncs, eval->function); + } + else + { // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) { @@ -1429,88 +1513,44 @@ void SV_Begin_Core(client_t *split) } // call the spawn function - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); - PR_ExecuteProgram (svprogfuncs, SpectatorConnect); - } - } - else - { - if (svprogfuncs) - { - eval_t *eval, *eval2; - eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0); - if (eval && split->spawninfo) - { - globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - int j; - edict_t *ent; - ent = split->edict; - j = strlen(split->spawninfo); - SV_UnlinkEdict(ent); - svprogfuncs->restoreent(svprogfuncs, split->spawninfo, &j, ent); - - eval2 = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "stats_restored", NULL); - if (eval2) - eval2->_float = 1; - for (j=0 ; j< NUM_SPAWN_PARMS ; j++) - { - if (spawnparamglobals[j]) - *spawnparamglobals[j] = split->spawn_parms[j]; - } - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); - G_FLOAT(OFS_PARM0) = sv.time - split->spawninfotime; - PR_ExecuteProgram(svprogfuncs, eval->function); - } - else - { - // copy spawn parms out of the client_t - for (i=0 ; i< NUM_SPAWN_PARMS ; i++) - { - if (spawnparamglobals[i]) - *spawnparamglobals[i] = split->spawn_parms[i]; - } - - // call the spawn function #ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_ClientConnect(split); - else + if (svs.gametype == GT_Q1QVM) + Q1QVM_ClientConnect(split); + else #endif - { - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); - PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); - - // actually spawn the player - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); - PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); - } - - oh = host_client; - host_client = split; - sv_player = host_client->edict; - SV_PreRunCmd(); - { - usercmd_t cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.msec = 0; -#define ANGLE2SHORT(x) (x) * (65536/360.0) - cmd.angles[0] = ANGLE2SHORT(split->edict->v->v_angle[0]); - cmd.angles[1] = ANGLE2SHORT(split->edict->v->v_angle[1]); - cmd.angles[2] = ANGLE2SHORT(split->edict->v->v_angle[2]); - SV_RunCmd(&cmd, false); - } - SV_PostRunCmd(); - host_client = oh; - sv_player = host_client->edict; + { + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); + PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); + + // actually spawn the player + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); + PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); } + + oh = host_client; + host_client = split; + sv_player = host_client->edict; + SV_PreRunCmd(); + { + usercmd_t cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.msec = 0; +#define ANGLE2SHORT(x) (x) * (65536/360.0) + cmd.angles[0] = ANGLE2SHORT(split->edict->v->v_angle[0]); + cmd.angles[1] = ANGLE2SHORT(split->edict->v->v_angle[1]); + cmd.angles[2] = ANGLE2SHORT(split->edict->v->v_angle[2]); + SV_RunCmd(&cmd, false); + } + SV_PostRunCmd(); + host_client = oh; + sv_player = host_client->edict; } } } } +} /* ================== @@ -2722,16 +2762,26 @@ SV_Kill_f void SV_Kill_f (void) { float floodtime; + +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + { + HLSV_ClientCommand(host_client); + return; + } +#endif #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) { - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); Q1QVM_ClientCommand(); return; } #endif + if (svs.gametype != GT_PROGS) + return; if (sv_player->v->health <= 0) { @@ -2749,7 +2799,7 @@ void SV_Kill_f (void) SV_PushFloodProt(host_client); } - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientKill); @@ -3553,12 +3603,12 @@ void Cmd_Join_f (void) } // call the spawn function - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); // actually spawn the player - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); @@ -3648,7 +3698,7 @@ void Cmd_Observe_f (void) // call the spawn function if (SpectatorConnect) { - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, SpectatorConnect); } @@ -3886,6 +3936,14 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC) if (!u->name) { +#ifdef HLSERVER + if (HLSV_ClientCommand(host_client)) + { + host_client = oldhost; + return; + } +#endif + if (!fromQC) if (PR_UserCmd(s)) //Q2 and MVDSV command handling only happens if the engine didn't recognise it. { @@ -4062,7 +4120,7 @@ void SVNQ_Begin_f (void) } // call the spawn function - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, SpectatorConnect); } @@ -4077,12 +4135,12 @@ void SVNQ_Begin_f (void) } // call the spawn function - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect); // actually spawn the player - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer); } @@ -5344,7 +5402,13 @@ haveannothergo: newcmd.upmove = 0; } - +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + { + SVHL_RunPlayerCommand(cl, &oldest, &oldcmd, &newcmd); + } + else +#endif if (!sv.paused) { if (sv_nomsec.value) @@ -6213,7 +6277,7 @@ void SV_ClientThink (void) if (SV_PlayerPhysicsQC) { - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, SV_PlayerPhysicsQC); return; diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index bc0fcb879..9d6f4fa6c 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -2051,7 +2051,7 @@ void SVQ3_EmitPacketEntities(client_t *client, q3client_frame_t *from, q3client_ { // this is a new entity, send it from the baseline if (svs.gametype == GT_QUAKE3) - MSGQ3_WriteDeltaEntity( msg, &q3_baselines[newnum], newent, true ); + MSGQ3_WriteDeltaEntity( msg, &q3_baselines[newnum], newent, true ); else { q3entityState_t q3base; @@ -2128,7 +2128,7 @@ void SVQ3_WriteSnapshotToClient(client_t *client, sizebuf_t *msg) // write snapshot header MSG_WriteBits(msg, svcq3_snapshot, 8); - MSG_WriteBits(msg, (int)(sv.time*1000), 32); + MSG_WriteBits(msg, snap->serverTime, 32); MSG_WriteBits(msg, delta, 8); // what we are delta'ing from // write snapFlags @@ -2362,8 +2362,8 @@ void SVQ3_BuildClientSnapshot( client_t *client ) clientNum = client - svs.clients; if (svs.gametype == GT_QUAKE3) { - clent = GENTITY_FOR_NUM( clientNum ); - ps = PS_FOR_NUM( clientNum ); + clent = GENTITY_FOR_NUM( clientNum ); + ps = PS_FOR_NUM( clientNum ); } else { @@ -2374,7 +2374,7 @@ void SVQ3_BuildClientSnapshot( client_t *client ) // this is the frame we are creating snap = &client->frameunion.q3frames[client->netchan.outgoing_sequence & Q3UPDATE_MASK]; - snap->serverTime = Sys_DoubleTime()*1000;//svs.levelTime; // save it for ping calc later + snap->serverTime = sv.time*1000;//svs.levelTime; // save it for ping calc later snap->flags = 0; if( client->state < cs_spawned ) @@ -2418,50 +2418,50 @@ void SVQ3_BuildClientSnapshot( client_t *client ) if (svs.gametype == GT_QUAKE3) { // check for SVF_PORTAL entities first - for( i=0 ; ir.svFlags & SVF_PORTAL) ) - continue; - if( !SVQ3_EntityIsVisible( ent ) ) - continue; - - // merge PVS if portal - portalarea = CM_PointLeafnum(sv.worldmodel, ent->s.origin2); - portalarea = CM_LeafArea(sv.worldmodel, portalarea); - -// CM_MergePVS ( ent->s.origin2 ); - -// CM_MergeAreaBits( snap->areabits, portalarea ); - } - - // add all visible entities - for( i=0 ; is.number != i) - { - Con_DPrintf( "FIXING ENT->S.NUMBER!!!\n" ); - ent->s.number = i; - } - - entityStates[snap->num_entities++] = &ent->s; - - if( snap->num_entities >= MAX_ENTITIES_IN_SNAPSHOT ) + for( i=0 ; ir.svFlags & SVF_PORTAL) ) + continue; + if( !SVQ3_EntityIsVisible( ent ) ) + continue; + + // merge PVS if portal + portalarea = CM_PointLeafnum(sv.worldmodel, ent->s.origin2); + portalarea = CM_LeafArea(sv.worldmodel, portalarea); + + // CM_MergePVS ( ent->s.origin2 ); + + // CM_MergeAreaBits( snap->areabits, portalarea ); + } + + // add all visible entities + for( i=0 ; is.number != i) + { + Con_DPrintf( "FIXING ENT->S.NUMBER!!!\n" ); + ent->s.number = i; + } + + entityStates[snap->num_entities++] = &ent->s; + + if( snap->num_entities >= MAX_ENTITIES_IN_SNAPSHOT ) + { + Con_DPrintf( "MAX_ENTITIES_IN_SNAPSHOT\n" ); + break; + } } - } } else { //our q1->q3 converter @@ -2690,29 +2690,29 @@ void SVQ3_SendGameState(client_t *client) switch (svs.gametype) { case GT_QUAKE3: - // write configstrings - for( i=0; istate = cs_spawned; + + client->lastcmd.servertime = sv.time*1000; break; case cs_spawned: // run G_ClientThink() on each usercmd @@ -2991,7 +2993,7 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta) memcpy( &client->lastcmd, to, sizeof(client->lastcmd)); if (svs.gametype == GT_QUAKE3) - SVQ3_ClientThink(client); + SVQ3_ClientThink(client); else { usercmd_t temp; @@ -3007,7 +3009,7 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta) if (temp.buttons & 64) temp.buttons |= 2; SV_RunCmd(&temp, false); - } + } } if (svs.gametype != GT_QUAKE3) SV_PostRunCmd(); @@ -3025,7 +3027,7 @@ void SVQ3_UpdateUserinfo_f(client_t *cl) SV_ExtractFromUserinfo (cl); if (svs.gametype == GT_QUAKE3) - VM_Call(q3gamevm, GAME_CLIENT_USERINFO_CHANGED, (int)(cl-svs.clients)); + VM_Call(q3gamevm, GAME_CLIENT_USERINFO_CHANGED, (int)(cl-svs.clients)); } void SVQ3_Drop_f(client_t *cl) diff --git a/engine/server/world.c b/engine/server/world.c index 6b07b6e86..57ca463d8 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -273,7 +273,7 @@ void SV_TouchLinks ( edict_t *ent, areanode_t *node ) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, touch); pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->time = sv.time; + pr_global_struct->time = sv.physicstime; #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_Touch(); @@ -299,7 +299,7 @@ void SV_TouchLinks ( edict_t *ent, areanode_t *node ) } #ifdef Q2BSPS -void Q2BSP_FindTouchedLeafs(model_t *model, edict_t *ent) +void Q2BSP_FindTouchedLeafs(model_t *model, edict_t *ent, float *mins, float *maxs) { #define MAX_TOTAL_ENT_LEAFS 128 int leafs[MAX_TOTAL_ENT_LEAFS]; @@ -315,7 +315,7 @@ void Q2BSP_FindTouchedLeafs(model_t *model, edict_t *ent) ent->areanum2 = 0; //get all leafs, including solids - num_leafs = CM_BoxLeafnums (model, ent->v->absmin, ent->v->absmax, + num_leafs = CM_BoxLeafnums (model, mins, maxs, leafs, MAX_TOTAL_ENT_LEAFS, &topnode); // set areas @@ -462,8 +462,10 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) { ent->v->absmin[0] -= 15; ent->v->absmin[1] -= 15; + ent->v->absmin[2] -= 1; ent->v->absmax[0] += 15; ent->v->absmax[1] += 15; + ent->v->absmax[2] += 1; } else { // because movement is clipped an epsilon away from an actual edge, @@ -477,7 +479,7 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) } // link to PVS leafs - sv.worldmodel->funcs.FindTouchedLeafs_Q1(sv.worldmodel, ent); + sv.worldmodel->funcs.FindTouchedLeafs_Q1(sv.worldmodel, ent, ent->v->absmin, ent->v->absmax); /* #ifdef Q2BSPS if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3)