diff --git a/common/boneinfo.h b/common/boneinfo.h new file mode 100644 index 00000000..bd58845e --- /dev/null +++ b/common/boneinfo.h @@ -0,0 +1,25 @@ +/* +boneinfo.h - structure that send delta-compressed bones across network +Copyright (C) 2018 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#ifndef BONEINFO_H +#define BONEINFO_H + +typedef struct +{ + vec3_t angles; + vec3_t origin; +} boneinfo_t; + +#endif//BONEINFO_H \ No newline at end of file diff --git a/common/bspfile.h b/common/bspfile.h index 201e03dd..91d5c1fd 100644 --- a/common/bspfile.h +++ b/common/bspfile.h @@ -74,7 +74,7 @@ BRUSH MODELS #define MAX_MAP_MARKSURFACES 524288 // can be increased without problems #else #define MAX_MAP_MODELS 768 // embedded models -#define MAX_MAP_ENTSTRING 0x80000 // 512 kB should be enough +#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough #define MAX_MAP_PLANES 65536 // can be increased without problems #define MAX_MAP_NODES 32767 // because negative shorts are leafs #define MAX_MAP_CLIPNODES 32767 // because negative shorts are contents diff --git a/common/com_model.h b/common/com_model.h index 0a85c084..6642722c 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -367,7 +367,7 @@ typedef struct player_info_s int userid; // User id on server char userinfo[MAX_INFO_STRING]; // User info string char name[MAX_SCOREBOARDNAME]; // Name (extracted from userinfo) - int spectator; // Spectator or not, unused + int spectator; // Spectator or not, unused (frags for quake demo playback) int ping; int packet_loss; diff --git a/common/event_api.h b/common/event_api.h index 8b7ae640..699310d0 100644 --- a/common/event_api.h +++ b/common/event_api.h @@ -55,4 +55,4 @@ typedef struct event_api_s void ( *EV_PopTraceBounds)( void ); } event_api_t; -#endif//EVENT_API_H +#endif//EVENT_API_H \ No newline at end of file diff --git a/common/render_api.h b/common/render_api.h index 246d7512..b6b8f462 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -74,12 +74,13 @@ enum typedef enum { + TF_COLORMAP = 0, // just for tabulate source TF_NEAREST = (1<<0), // disable texfilter TF_KEEP_SOURCE = (1<<1), // some images keep source TF_NOFLIP_TGA = (1<<2), // Steam background completely ignore tga attribute 0x20 TF_EXPAND_SOURCE = (1<<3), // Don't keep source as 8-bit expand to RGBA - TF_TEXTURE_2D_ARRAY = (1<<4), // this is 2D texture array (multi-layers) - TF_TEXTURE_RECTANGLE= (1<<5), // this is GL_TEXTURE_RECTANGLE +// reserved + TF_RECTANGLE = (1<<5), // this is GL_TEXTURE_RECTANGLE TF_CUBEMAP = (1<<6), // it's cubemap texture TF_DEPTHMAP = (1<<7), // custom texture filter used TF_QUAKEPAL = (1<<8), // image has an quake1 palette @@ -92,7 +93,7 @@ typedef enum TF_NORMALMAP = (1<<15), // is a normalmap TF_HAS_ALPHA = (1<<16), // image has alpha (used only for GL_CreateTexture) TF_FORCE_COLOR = (1<<17), // force upload monochrome textures as RGB (detail textures) - TF_TEXTURE_1D = (1<<18), // this is GL_TEXTURE_1D +// reserved TF_BORDER = (1<<19), // zero clamp for projected textures TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page @@ -203,9 +204,9 @@ typedef struct render_api_s void (*GL_TextureTarget)( unsigned int target ); // change texture unit mode without bind texture void (*GL_TexCoordArrayMode)( unsigned int texmode ); void* (*GL_GetProcAddress)( const char *name ); + void (*GL_UpdateTexSize)( int texnum, int width, int height, int depth ); // recalc statistics void (*GL_Reserved0)( void ); // for potential interface expansion without broken compatibility void (*GL_Reserved1)( void ); - void (*GL_Reserved2)( void ); // Misc renderer functions void (*GL_DrawParticles)( const struct ref_viewpass_s *rvp, qboolean trans_pass, float frametime ); @@ -215,8 +216,8 @@ typedef struct render_api_s struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e ); const struct ref_overview_s *( *GetOverviewParms )( void ); const char *( *GetFileByIndex )( int fileindex ); - void (*R_Reserved1)( void ); // for potential interface expansion without broken compatibility - void (*R_Reserved2)( void ); + void (*R_Reserved0)( void ); // for potential interface expansion without broken compatibility + void (*R_Reserved1)( void ); // static allocations void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ); diff --git a/common/wadfile.h b/common/wadfile.h index b96b3658..646153b9 100644 --- a/common/wadfile.h +++ b/common/wadfile.h @@ -55,17 +55,6 @@ infotable dlumpinfo_t[dwadinfo_t->numlumps] #define TYP_COLORMAP2 69 // old stuff. build palette from LBM file (not used) #define TYP_QFONT 70 // half-life font (qfont_t) -// dlumpinfo_t->img_type -#define IMG_DIFFUSE 0 // same as default pad1 always equal 0 -#define IMG_ALPHAMASK 1 // alpha-channel that stored separate as luminance texture -#define IMG_NORMALMAP 2 // indexed normalmap -#define IMG_GLOSSMAP 3 // luminance or color specularity map -#define IMG_GLOSSPOWER 4 // gloss power map (each value is a specular pow) -#define IMG_HEIGHTMAP 5 // heightmap (for parallax occlusion mapping or source of normalmap) -#define IMG_LUMA 6 // luma or glow texture with self-illuminated parts -#define IMG_DECAL_ALPHA 7 // it's a decal texture (last color in palette is base color, and other colors his graduations) -#define IMG_DECAL_COLOR 8 // decal without alpha-channel uses base, like 127 127 127 as transparent color - /* ======================================================================== diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index 4e62420b..c69a6b5e 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -152,7 +152,7 @@ qboolean CL_ScreenshotGetName( int lastnum, char *filename ) if( lastnum < 0 || lastnum > 9999 ) { - MsgDev( D_ERROR, "unable to write screenshot\n" ); + Con_Printf( S_ERROR "unable to write screenshot\n" ); return false; } @@ -180,7 +180,7 @@ qboolean CL_SnapshotGetName( int lastnum, char *filename ) if( lastnum < 0 || lastnum > 9999 ) { - MsgDev( D_ERROR, "unable to write snapshot\n" ); + Con_Printf( S_ERROR "unable to write snapshot\n" ); FS_AllowDirectPaths( false ); return false; } diff --git a/engine/client/cl_custom.c b/engine/client/cl_custom.c index 6ea718aa..a152fc25 100644 --- a/engine/client/cl_custom.c +++ b/engine/client/cl_custom.c @@ -44,19 +44,19 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource ) if( !COM_IsSafeFileToDownload( filepath )) { - MsgDev( D_REPORT, "refusing to download %s\n", filepath ); + Con_Reportf( "refusing to download %s\n", filepath ); return true; } if( !cl_allow_download.value ) { - MsgDev( D_REPORT, "Download refused, cl_allow_download is 0\n" ); + Con_Reportf( "Download refused, cl_allow_download is 0\n" ); return true; } if( cls.state == ca_active && !cl_download_ingame.value ) { - MsgDev( D_REPORT, "In-game download refused...\n" ); + Con_Reportf( "In-game download refused...\n" ); return true; } @@ -66,7 +66,7 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource ) if( cls.demoplayback ) { - MsgDev( D_WARN, "file %s missing during demo playback.\n", filepath ); + Con_Reportf( S_WARN "file %s missing during demo playback.\n", filepath ); return true; } @@ -81,7 +81,7 @@ void CL_AddToResourceList( resource_t *pResource, resource_t *pList ) { if( pResource->pPrev != NULL || pResource->pNext != NULL ) { - MsgDev( D_ERROR, "Resource already linked\n" ); + Con_Reportf( S_ERROR "Resource already linked\n" ); return; } @@ -112,7 +112,7 @@ void CL_MoveToOnHandList( resource_t *pResource ) { if( !pResource ) { - MsgDev( D_REPORT, "Null resource passed to CL_MoveToOnHandList\n" ); + Con_Reportf( "Null resource passed to CL_MoveToOnHandList\n" ); return; } diff --git a/engine/client/cl_debug.c b/engine/client/cl_debug.c index 4f740a3c..4704b800 100644 --- a/engine/client/cl_debug.c +++ b/engine/client/cl_debug.c @@ -82,7 +82,7 @@ const char *svc_strings[svc_lastmsg+1] = "svc_director", "svc_voiceinit", "svc_voicedata", - "svc_unused54", + "svc_deltapacketbones", "svc_unused55", "svc_resourcelocation", "svc_querycvarvalue", diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 505db0c8..c37cba7e 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -126,7 +126,7 @@ void CL_StartupDemoHeader( void ) if( !cls.demoheader ) { - MsgDev( D_ERROR, "couldn't open temporary header file.\n" ); + Con_DPrintf( S_ERROR "couldn't open temporary header file.\n" ); return; } @@ -359,7 +359,7 @@ void CL_WriteDemoHeader( const char *name ) if( !cls.demofile ) { - MsgDev( D_ERROR, "couldn't open %s.\n", name ); + Con_Printf( S_ERROR "couldn't open %s.\n", name ); return; } @@ -773,14 +773,14 @@ qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length ) if( msglen < 0 ) { - MsgDev( D_ERROR, "Demo message length < 0\n" ); + Con_Reportf( S_ERROR "Demo message length < 0\n" ); CL_DemoCompleted(); return false; } if( msglen > MAX_INIT_MSG ) { - MsgDev( D_ERROR, "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); + Con_Reportf( S_ERROR "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); CL_DemoCompleted(); return false; } @@ -789,7 +789,7 @@ qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length ) { if( FS_Read( cls.demofile, buffer, msglen ) != msglen ) { - MsgDev( D_ERROR, "Error reading demo message data\n" ); + Con_Reportf( S_ERROR "Error reading demo message data\n" ); CL_DemoCompleted(); return false; } @@ -862,14 +862,14 @@ qboolean CL_DemoReadMessageQuake( byte *buffer, size_t *length ) if( msglen < 0 ) { - MsgDev( D_ERROR, "Demo message length < 0\n" ); + Con_Reportf( S_ERROR "Demo message length < 0\n" ); CL_DemoCompleted(); return false; } if( msglen > MAX_INIT_MSG ) { - MsgDev( D_ERROR, "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); + Con_Reportf( S_ERROR "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); CL_DemoCompleted(); return false; } @@ -878,7 +878,7 @@ qboolean CL_DemoReadMessageQuake( byte *buffer, size_t *length ) { if( FS_Read( cls.demofile, buffer, msglen ) != msglen ) { - MsgDev( D_ERROR, "Error reading demo message data\n" ); + Con_Reportf( S_ERROR "Error reading demo message data\n" ); CL_DemoCompleted(); return false; } @@ -910,7 +910,6 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length ) if( !cls.demofile ) { - MsgDev( D_ERROR, "tried to read a demo message with no demo file\n" ); CL_DemoCompleted(); return false; } @@ -1454,7 +1453,7 @@ void CL_PlayDemo_f( void ) } else if( !FS_FileExists( filename2, true )) { - MsgDev( D_ERROR, "couldn't open %s\n", filename2 ); + Con_Printf( S_ERROR "couldn't open %s\n", filename2 ); CL_DemoAborted(); return; } @@ -1468,7 +1467,7 @@ void CL_PlayDemo_f( void ) if( demo.header.id != IDEMOHEADER ) { - MsgDev( D_ERROR, "%s is not a demo file\n", demoname ); + Con_Printf( S_ERROR "%s is not a demo file\n", demoname ); CL_DemoAborted(); return; } @@ -1476,10 +1475,10 @@ void CL_PlayDemo_f( void ) if( demo.header.net_protocol != PROTOCOL_VERSION || demo.header.dem_protocol != DEMO_PROTOCOL ) { if( demo.header.dem_protocol != DEMO_PROTOCOL ) - MsgDev( D_ERROR, "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL ); + Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL ); if( demo.header.net_protocol != PROTOCOL_VERSION ) - MsgDev( D_ERROR, "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION ); + Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION ); CL_DemoAborted(); return; } @@ -1490,7 +1489,7 @@ void CL_PlayDemo_f( void ) if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 ) { - MsgDev( D_ERROR, "demo had bogus # of directory entries: %i\n", demo.directory.numentries ); + Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries ); CL_DemoAborted(); return; } @@ -1559,7 +1558,7 @@ void CL_StartDemos_f( void ) c = Cmd_Argc() - 1; if( c > MAX_DEMOS ) { - MsgDev( D_WARN, "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS ); + Con_DPrintf( S_WARN "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS ); c = MAX_DEMOS; } diff --git a/engine/client/cl_events.c b/engine/client/cl_events.c index c7404dc9..2d9bb4f3 100644 --- a/engine/client/cl_events.c +++ b/engine/client/cl_events.c @@ -157,10 +157,7 @@ void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func ) cl_user_event_t *ev; if( lastnum == MAX_EVENTS ) - { - MsgDev( D_ERROR, "CL_RegisterEvent: MAX_EVENTS hit!\n" ); return; - } // clear existing or allocate new one if( !clgame.events[lastnum] ) @@ -197,7 +194,7 @@ qboolean CL_FireEvent( event_info_t *ei, int slot ) if( !ev ) { idx = bound( 1, ei->index, ( MAX_EVENTS - 1 )); - MsgDev( D_ERROR, "CL_FireEvent: %s not precached\n", cl.event_precache[idx] ); + Con_Reportf( S_ERROR "CL_FireEvent: %s not precached\n", cl.event_precache[idx] ); break; } @@ -211,7 +208,7 @@ qboolean CL_FireEvent( event_info_t *ei, int slot ) } name = cl.event_precache[ei->index]; - MsgDev( D_ERROR, "CL_FireEvent: %s not hooked\n", name ); + Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name ); break; } } @@ -439,10 +436,6 @@ void CL_ParseEvent( sizebuf_t *msg ) if( args.entindex > 0 && args.entindex <= cl.maxclients ) args.angles[PITCH] /= -3.0f; } - else - { - MsgDev( D_WARN, "CL_ParseEvent: Received non-packet entity index 0 for event\n" ); - } } // Place event on queue @@ -462,28 +455,25 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa { event_args_t args; - if( flags & FEV_SERVER ) - { - MsgDev( D_WARN, "CL_PlaybackEvent: event with FEV_SERVER flag!\n" ); + if( FBitSet( flags, FEV_SERVER )) return; - } // first check event for out of bounds if( eventindex < 1 || eventindex > MAX_EVENTS ) { - MsgDev( D_ERROR, "CL_PlaybackEvent: invalid eventindex %i\n", eventindex ); + Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex ); return; } // check event for precached if( !CL_EventIndex( cl.event_precache[eventindex] )) { - MsgDev( D_ERROR, "CL_PlaybackEvent: event %i was not precached\n", eventindex ); + Con_DPrintf( S_ERROR "CL_PlaybackEvent: event %i was not precached\n", eventindex ); return; } - flags |= FEV_CLIENT; // it's a client event - flags &= ~(FEV_NOTHOST|FEV_HOSTONLY|FEV_GLOBAL); + SetBits( flags, FEV_CLIENT ); // it's a client event + ClearBits( flags, FEV_NOTHOST|FEV_HOSTONLY|FEV_GLOBAL ); if( delay < 0.0f ) delay = 0.0f; // fixup negative delays memset( &args, 0, sizeof( args )); diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index 216b70c5..661059fc 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -270,8 +270,8 @@ void CL_ProcessEntityUpdate( cl_entity_t *ent ) ent->model = CL_ModelHandle( ent->curstate.modelindex ); ent->index = ent->curstate.number; - // g-cont. make sure what it's no broke XashXT physics - COM_NormalizeAngles( ent->curstate.angles ); + if( FBitSet( ent->curstate.entityType, ENTITY_NORMAL )) + COM_NormalizeAngles( ent->curstate.angles ); parametric = CL_ParametricMove( ent ); @@ -407,19 +407,15 @@ int CL_InterpolateModel( cl_entity_t *e ) VectorCopy( e->curstate.origin, e->origin ); VectorCopy( e->curstate.angles, e->angles ); - if( cls.timedemo || !e->model ) + if( cls.timedemo || !e->model || cl.maxclients <= 1 ) return 1; - if( fabs( cl_serverframetime() - cl_clientframetime()) < 0.0001f ) - return 1; // interpolation disabled - if( e->model->type == mod_brush && !cl_bmodelinterp->value ) return 1; if( cl.local.moving && cl.local.onground == e->index ) return 1; -// t = cl.time - cl_serverframetime(); t = cl.time - cl_interp->value; CL_FindInterpolationUpdates( e, t, &ph0, &ph1 ); @@ -635,7 +631,7 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t if(( newnum < 0 ) || ( newnum >= clgame.maxEntities )) { - MsgDev( D_ERROR, "CL_DeltaEntity: invalid newnum: %d\n", newnum ); + Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum ); if( has_update ) MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] ); return; @@ -734,7 +730,6 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES )) { - MsgDev( D_NOTE, "CL_ParsePacketEntities: delta frame is too old (flush)\n"); Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" ); CL_FlushEntityPacket( msg ); return playerbytes; @@ -847,7 +842,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) } if( newframe->num_entities != count && newframe->num_entities != 0 ) - MsgDev( D_WARN, "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count ); + Con_Reportf( S_WARN "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count ); if( !newframe->valid ) return playerbytes; // frame is not valid but message was parsed @@ -943,7 +938,7 @@ void CL_LinkCustomEntity( cl_entity_t *ent, entity_state_t *state ) ent->curstate.movetype = state->modelindex; // !!! if( ent->model->type != mod_sprite ) - MsgDev( D_WARN, "bad model on beam ( %s )\n", ent->model->name ); + Con_Reportf( S_WARN "bad model on beam ( %s )\n", ent->model->name ); ent->latched.prevsequence = ent->curstate.sequence; VectorCopy( ent->origin, ent->latched.prevorigin ); @@ -1042,6 +1037,7 @@ void CL_LinkPacketEntities( frame_t *frame ) cl_entity_t *ent; entity_state_t *state; qboolean parametric; + qboolean interpolate; int i; for( i = 0; i < frame->num_entities; i++ ) @@ -1060,15 +1056,14 @@ void CL_LinkPacketEntities( frame_t *frame ) if( !ent ) { - MsgDev( D_ERROR, "CL_LinkPacketEntity: bad entity %i\n", state->number ); + Con_Reportf( S_ERROR "CL_LinkPacketEntity: bad entity %i\n", state->number ); continue; } - ent->curstate = *state; - - // XASH SPECIFIC - if( ent->curstate.rendermode == kRenderNormal && ent->curstate.renderfx == kRenderFxNone ) - ent->curstate.renderamt = 255.0f; + // animtime must keep an actual + ent->curstate.animtime = state->animtime; + ent->curstate.frame = state->frame; + interpolate = false; if( !ent->model ) continue; @@ -1096,7 +1091,9 @@ void CL_LinkPacketEntities( frame_t *frame ) #ifdef STUDIO_INTERPOLATION_FIX if( ent->lastmove >= cl.time ) VectorCopy( ent->curstate.origin, ent->latched.prevorigin ); - ent->curstate.movetype = MOVETYPE_STEP; + if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) + interpolate = true; + else ent->curstate.movetype = MOVETYPE_STEP; #else if( ent->lastmove >= cl.time ) { @@ -1149,7 +1146,7 @@ void CL_LinkPacketEntities( frame_t *frame ) if( ent->model->type == mod_studio ) { - if( ent->curstate.movetype == MOVETYPE_STEP && FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) + if( interpolate && FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) R_StudioLerpMovement( ent, cl.time, ent->origin, ent->angles ); } } @@ -1167,6 +1164,10 @@ void CL_LinkPacketEntities( frame_t *frame ) ent->curstate.rendercolor.r = ent->curstate.rendercolor.g = ent->curstate.rendercolor.b = 255; } + // XASH SPECIFIC + if( ent->curstate.rendermode == kRenderNormal && ent->curstate.renderfx == kRenderFxNone ) + ent->curstate.renderamt = 255.0f; + if( ent->curstate.aiment != 0 && ent->curstate.movetype != MOVETYPE_COMPOUND ) ent->curstate.movetype = MOVETYPE_FOLLOW; diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index d9bbab68..cc295cba 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -237,7 +237,7 @@ void CL_InitCDAudio( const char *filename ) if( ++c > MAX_CDTRACKS - 1 ) { - MsgDev( D_WARN, "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename ); + Con_Reportf( S_WARN "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename ); break; } } @@ -826,14 +826,14 @@ const char *CL_SoundFromIndex( int index ) if( !hSound ) { - MsgDev( D_ERROR, "CL_SoundFromIndex: invalid sound index %i\n", index ); + Con_DPrintf( S_ERROR "CL_SoundFromIndex: invalid sound index %i\n", index ); return NULL; } sfx = S_GetSfxByHandle( hSound ); if( !sfx ) { - MsgDev( D_ERROR, "CL_SoundFromIndex: bad sfx for index %i\n", index ); + Con_DPrintf( S_ERROR "CL_SoundFromIndex: bad sfx for index %i\n", index ); return NULL; } @@ -1059,7 +1059,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) { // NOTE: no check for DispatchFunc, check only name - if( !Q_strcmp( clgame.msg[i].name, pszName )) + if( !Q_stricmp( clgame.msg[i].name, pszName )) { clgame.msg[i].number = svc_num; clgame.msg[i].size = iSize; @@ -1211,7 +1211,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite, } else { - Con_Printf( S_ERROR "%s couldn't load\n", szSpriteName ); + Con_Reportf( S_ERROR "%s couldn't load\n", szSpriteName ); Mod_UnloadSpriteModel( m_pSprite ); return false; } @@ -1253,7 +1253,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla if( !COM_CheckString( filename )) { - MsgDev( D_ERROR, "CL_LoadSpriteModel: bad name!\n" ); + Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" ); return NULL; } @@ -1685,7 +1685,7 @@ static int pfnHookUserMsg( const char *pszName, pfnUserMsgHook pfn ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) { // see if already hooked - if( !Q_strcmp( clgame.msg[i].name, pszName )) + if( !Q_stricmp( clgame.msg[i].name, pszName )) return 1; } @@ -1712,7 +1712,7 @@ static int pfnServerCmd( const char *szCmdString ) { string buf; - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; // just like the client typed "cmd xxxxx" at the console @@ -1730,11 +1730,20 @@ pfnClientCmd */ static int pfnClientCmd( const char *szCmdString ) { - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; - Cbuf_AddText( szCmdString ); - Cbuf_AddText( "\n" ); + if( cls.initialized ) + { + Cbuf_AddText( szCmdString ); + Cbuf_AddText( "\n" ); + } + else + { + // will exec later + Q_strncat( host.deferred_cmd, va( "%s\n", szCmdString ), sizeof( host.deferred_cmd )); + } + return 1; } @@ -1793,12 +1802,8 @@ static void pfnPlaySoundByIndex( int iSound, float volume ) // make sure what we in-bounds iSound = bound( 0, iSound, MAX_SOUNDS ); hSound = cl.sound_index[iSound]; + if( !hSound ) return; - if( !hSound ) - { - MsgDev( D_ERROR, "CL_PlaySoundByIndex: invalid sound handle %i\n", iSound ); - return; - } S_StartSound( NULL, cl.viewentity, CHAN_ITEM, hSound, volume, ATTN_NORM, PITCH_NORM, SND_STOP_LOOPING ); } @@ -2241,7 +2246,7 @@ static void pfnHookEvent( const char *filename, pfnEventHook pfn ) if( !Q_stricmp( name, ev->name ) && ev->func != NULL ) { - MsgDev( D_WARN, "CL_HookEvent: %s already hooked!\n", name ); + Con_Reportf( S_WARN "CL_HookEvent: %s already hooked!\n", name ); return; } } @@ -2722,7 +2727,7 @@ pfnServerCmdUnreliable */ int pfnServerCmdUnreliable( char *szCmdString ) { - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; MSG_BeginClientCmd( &cls.datagram, clc_stringcmd ); @@ -3327,7 +3332,7 @@ void NetAPI_SendRequest( int context, int request, int flags, double timeout, ne if( !response ) { - MsgDev( D_ERROR, "Net_SendRequest: no callbcak specified for request with context %i!\n", context ); + Con_DPrintf( S_ERROR "Net_SendRequest: no callbcak specified for request with context %i!\n", context ); return; } @@ -3945,7 +3950,7 @@ qboolean CL_LoadProgs( const char *name ) // trying to get single export if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL ) { - MsgDev( D_NOTE, "CL_LoadProgs: found single callback export\n" ); + Con_Reportf( "CL_LoadProgs: found single callback export\n" ); // trying to fill interface now GetClientAPI( &clgame.dllFuncs ); @@ -3970,7 +3975,7 @@ qboolean CL_LoadProgs( const char *name ) // functions are cleared before all the extensions are evaluated if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL ) { - MsgDev( D_NOTE, "CL_LoadProgs: failed to get address of %s proc\n", func->name ); + Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name ); if( critical_exports ) { @@ -3997,13 +4002,13 @@ qboolean CL_LoadProgs( const char *name ) // functions are cleared before all the extensions are evaluated // NOTE: new exports can be missed without stop the engine if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL ) - MsgDev( D_NOTE, "CL_LoadProgs: failed to get address of %s proc\n", func->name ); + Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name ); } if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION )) { COM_FreeLibrary( clgame.hInstance ); - MsgDev( D_NOTE, "CL_LoadProgs: can't init client API\n" ); + Con_Reportf( "CL_LoadProgs: can't init client API\n" ); clgame.hInstance = NULL; return false; } diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index cf9690e8..dce138b9 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -29,6 +29,19 @@ void UI_UpdateMenu( float realtime ) { if( !gameui.hInstance ) return; + // if some deferred cmds is waiting + if( UI_IsVisible() && COM_CheckString( host.deferred_cmd )) + { + Cbuf_AddText( host.deferred_cmd ); + host.deferred_cmd[0] = '\0'; + Cbuf_Execute(); + return; + } + + // don't show menu while level is loaded + if( GameState->nextstate != STATE_RUNFRAME && !GameState->loadGame ) + return; + // menu time (not paused, not clamped) gameui.globals->time = host.realtime; gameui.globals->frametime = host.realframetime; @@ -146,7 +159,7 @@ static void UI_DrawLogo( const char *filename, float x, float y, float width, fl if( FS_FileExists( path, false ) && !fullpath ) { - MsgDev( D_ERROR, "Couldn't load %s from packfile. Please extract it\n", path ); + Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", path ); gameui.drawLogo = false; return; } @@ -365,7 +378,7 @@ static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long im if( !szPicName || !*szPicName ) { - MsgDev( D_ERROR, "CL_LoadImage: bad name!\n" ); + Con_Reportf( S_ERROR "CL_LoadImage: bad name!\n" ); return 0; } @@ -1026,7 +1039,7 @@ qboolean UI_LoadProgs( void ) if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL ) { COM_FreeLibrary( gameui.hInstance ); - MsgDev( D_NOTE, "UI_LoadProgs: can't init menu API\n" ); + Con_Reportf( "UI_LoadProgs: can't init menu API\n" ); gameui.hInstance = NULL; return false; } @@ -1039,7 +1052,7 @@ qboolean UI_LoadProgs( void ) if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals )) { COM_FreeLibrary( gameui.hInstance ); - MsgDev( D_NOTE, "UI_LoadProgs: can't init menu API\n" ); + Con_Reportf( "UI_LoadProgs: can't init menu API\n" ); Mem_FreePool( &gameui.mempool ); gameui.hInstance = NULL; return false; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 307eff59..a156a8b4 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1488,8 +1488,10 @@ CL_InternetServers_f */ void CL_InternetServers_f( void ) { + char fullquery[512] = MS_SCAN_REQUEST; + char *info = fullquery + sizeof( MS_SCAN_REQUEST ) - 1; + int remaining = sizeof( fullquery ) - sizeof( MS_SCAN_REQUEST ); netadr_t adr; - char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\"; Con_Printf( "Scanning for servers on the internet area...\n" ); NET_Config( true ); // allow remote @@ -1497,9 +1499,10 @@ void CL_InternetServers_f( void ) if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) ) MsgDev( D_ERROR, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); - Q_strcpy( &fullquery[22], GI->gamedir ); + Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); + Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version - NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, adr ); + NET_SendPacket( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ), fullquery, adr ); // now we clearing the vgui request if( clgame.master_request != NULL ) @@ -1620,10 +1623,13 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg ) CL_FixupColorStringsForInfoString( s, infostring ); if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" ))) - return; // unsupported proto + { + Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring ); + return; // unsupported proto + } // more info about servers - Con_Printf( "Server: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" )); + Con_Printf( "^2Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" )); UI_AddServerToList( from, infostring ); } @@ -1839,7 +1845,6 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) } // if we waiting more than cl_timeout or packet was trashed - Msg( "got testpacket, size mismatched %d should be %d\n", MSG_GetMaxBytes( msg ), cls.max_fragment_size ); cls.connect_time = MAX_HEARTBEAT; return; // just wait for a next responce } @@ -1853,7 +1858,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) if( crcValue == crcValue2 ) { // packet was sucessfully delivered, adjust the fragment size and get challenge - Msg( "CRC %p is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size ); + Con_DPrintf( "CRC %p is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size ); Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" ); Cvar_SetValue( "cl_dlmax", cls.max_fragment_size ); cls.connect_time = host.realtime; @@ -1870,7 +1875,6 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) return; } - Msg( "got testpacket, CRC mismatched %p should be %p, trying next fragment size %d\n", crcValue2, crcValue, cls.max_fragment_size >> 1 ); // trying the next size of packet cls.connect_time = MAX_HEARTBEAT; } @@ -2618,7 +2622,7 @@ void CL_InitLocal( void ) cl_showfps = Cvar_Get( "cl_showfps", "1", FCVAR_ARCHIVE, "show client fps" ); cl_nosmooth = Cvar_Get( "cl_nosmooth", "0", FCVAR_ARCHIVE, "disable smooth up stair climbing and interpolate position in multiplayer" ); - cl_smoothtime = Cvar_Get( "cl_smoothtime", "0.1", FCVAR_ARCHIVE, "time to smooth up" ); + cl_smoothtime = Cvar_Get( "cl_smoothtime", "0", FCVAR_ARCHIVE, "time to smooth up" ); cl_cmdbackup = Cvar_Get( "cl_cmdbackup", "10", FCVAR_ARCHIVE, "how many additional history commands are sent" ); cl_cmdrate = Cvar_Get( "cl_cmdrate", "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" ); cl_draw_particles = Cvar_Get( "r_drawparticles", "1", FCVAR_CHEAT, "render particles" ); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 9e54a943..a3ac5957 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -101,10 +101,7 @@ void CL_ParseSoundPacket( sizebuf_t *msg ) else handle = cl.sound_index[sound]; // see precached sound if( !cl.audio_prepped ) - { - MsgDev( D_WARN, "CL_StartSoundPacket: ignore sound message: too early\n" ); return; // too early - } // g-cont. sound and ambient sound have only difference with channel if( chan == CHAN_STATIC ) @@ -160,7 +157,7 @@ void CL_ParseRestoreSoundPacket( sizebuf_t *msg ) char sentenceName[32]; if( flags & SND_SEQUENCE ) - Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound + MAX_SOUNDS ); + Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound + MAX_SOUNDS ); else Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound ); handle = S_RegisterSound( sentenceName ); @@ -174,10 +171,7 @@ void CL_ParseRestoreSoundPacket( sizebuf_t *msg ) MSG_ReadBytes( msg, &forcedEnd, sizeof( forcedEnd )); if( !cl.audio_prepped ) - { - MsgDev( D_WARN, "CL_RestoreSoundPacket: ignore sound message: too early\n" ); return; // too early - } S_RestoreSound( pos, entnum, chan, handle, volume, attn, pitch, flags, samplePos, forcedEnd, wordIndex ); } @@ -229,7 +223,7 @@ void CL_ParseSignon( sizebuf_t *msg ) if( i <= cls.signon ) { - MsgDev( D_ERROR, "received signon %i when at %i\n", i, cls.signon ); + Con_Reportf( S_ERROR "received signon %i when at %i\n", i, cls.signon ); CL_Disconnect(); return; } @@ -324,7 +318,7 @@ void CL_ParseStaticEntity( sizebuf_t *msg ) i = clgame.numStatics; if( i >= MAX_STATIC_ENTITIES ) { - Con_Printf( S_ERROR, "MAX_STATIC_ENTITIES limit exceeded!\n" ); + Con_Printf( S_ERROR "MAX_STATIC_ENTITIES limit exceeded!\n" ); return; } @@ -522,7 +516,6 @@ void CL_BatchResourceRequest( qboolean initialize ) if( !COM_IsSafeFileToDownload( p->szFileName )) { CL_RemoveFromResourceList( p ); - MsgDev( D_WARN, "Invalid file type...skipping download of %s\n", p->szFileName ); Mem_Free( p ); break; } @@ -777,16 +770,10 @@ void CL_ParseResourceRequest( sizebuf_t *msg ) nStartIndex = MSG_ReadLong( msg ); if( cl.servercount != arg ) - { - MsgDev( D_ERROR, "request resources from different level\n" ); return; - } if( nStartIndex < 0 && nStartIndex > cl.num_resources ) - { - MsgDev( D_ERROR, "custom resource list request out of range\n" ); return; - } MSG_BeginClientCmd( &sbuf, clc_resourcelist ); MSG_WriteShort( &sbuf, cl.num_resources ); @@ -867,7 +854,7 @@ void CL_ParseServerData( sizebuf_t *msg ) qboolean background; int i; - MsgDev( D_NOTE, "Serverdata packet received.\n" ); + Con_Reportf( "Serverdata packet received.\n" ); cls.timestart = Sys_DoubleTime(); cls.demowaiting = false; // server is changed @@ -1687,7 +1674,7 @@ void CL_ParseResLocation( sizebuf_t *msg ) if( lastSlash && lastSlash[1] == '\0' ) Q_strncpy( cl.downloadUrl, url, sizeof( cl.downloadUrl )); else Q_snprintf( cl.downloadUrl, sizeof( cl.downloadUrl ), "%s/", url ); - MsgDev( D_REPORT, "Using %s as primary download location\n", cl.downloadUrl ); + Con_Reportf( "Using %s as primary download location\n", cl.downloadUrl ); } } @@ -1722,7 +1709,6 @@ void CL_ParseHLTV( sizebuf_t *msg ) SCR_EndLoadingPlaque(); break; default: - MsgDev( D_ERROR, "CL_ParseHLTV: unknown HLTV command.\n" ); break; } } @@ -1989,9 +1975,10 @@ dispatch messages */ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) { - size_t bufStart, playerbytes; - int cmd, param1, param2; - int old_background; + size_t bufStart, playerbytes; + int cmd, param1, param2; + int old_background; + const char *s; cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame CL_Parse_Debug( true ); // begin parsing @@ -2028,8 +2015,6 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) cmd = MSG_ReadServerCmd( msg ); -// Msg( "%s\n", CL_MsgInfo( cmd )); - // record command for debugging spew on parse problem CL_Parse_RecordCommand( cmd, bufStart ); @@ -2099,7 +2084,13 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message ) Con_Printf( "%s", MSG_ReadString( msg )); break; case svc_stufftext: - Cbuf_AddText( MSG_ReadString( msg )); + s = MSG_ReadString( msg ); +#ifdef HACKS_RELATED_HLMODS + // dsiable Cry Of Fear antisave protection + if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS ) + break; // too early +#endif + Cbuf_AddText( s ); break; case svc_setangle: CL_ParseSetAngle( msg ); diff --git a/engine/client/cl_pmove.c b/engine/client/cl_pmove.c index 5d706939..dc76da16 100644 --- a/engine/client/cl_pmove.c +++ b/engine/client/cl_pmove.c @@ -48,17 +48,10 @@ CL_PushPMStates */ void CL_PushPMStates( void ) { - if( clgame.pushed ) - { - MsgDev( D_ERROR, "PushPMStates: stack overflow\n"); - } - else - { - clgame.oldphyscount = clgame.pmove->numphysent; - clgame.oldviscount = clgame.pmove->numvisent; - clgame.pushed = true; - } - + if( clgame.pushed ) return; + clgame.oldphyscount = clgame.pmove->numphysent; + clgame.oldviscount = clgame.pmove->numvisent; + clgame.pushed = true; } /* @@ -69,16 +62,10 @@ CL_PopPMStates */ void CL_PopPMStates( void ) { - if( clgame.pushed ) - { - clgame.pmove->numphysent = clgame.oldphyscount; - clgame.pmove->numvisent = clgame.oldviscount; - clgame.pushed = false; - } - else - { - MsgDev( D_ERROR, "PopPMStates: stack underflow\n"); - } + if( !clgame.pushed ) return; + clgame.pmove->numphysent = clgame.oldphyscount; + clgame.pmove->numvisent = clgame.oldviscount; + clgame.pushed = false; } /* @@ -794,10 +781,7 @@ static void pfnStuckTouch( int hitent, pmtrace_t *tr ) } if( clgame.pmove->numtouch >= MAX_PHYSENTS ) - { - MsgDev( D_ERROR, "PM_StuckTouch: MAX_TOUCHENTS limit exceeded\n" ); return; - } VectorCopy( clgame.pmove->velocity, tr->deltavelocity ); tr->ent = hitent; @@ -995,7 +979,7 @@ void CL_InitClientMove( void ) for( i = 0; i < MAX_MAP_HULLS; i++ ) { if( clgame.dllFuncs.pfnGetHullBounds( i, host.player_mins[i], host.player_maxs[i] )) - MsgDev( D_NOTE, "CL: hull%i, player_mins: %g %g %g, player_maxs: %g %g %g\n", i, + Con_Reportf( "CL: hull%i, player_mins: %g %g %g, player_maxs: %g %g %g\n", i, host.player_mins[i][0], host.player_mins[i][1], host.player_mins[i][2], host.player_maxs[i][0], host.player_maxs[i][1], host.player_maxs[i][2] ); } @@ -1344,7 +1328,7 @@ void CL_PredictMovement( qboolean repredicting ) cl.local.onground = frame->playerstate[cl.playernum].onground; else cl.local.onground = -1; - if( !repredicting || !cl_lw->value ) + if( !repredicting || !CVAR_TO_BOOL( cl_lw )) cl.local.viewmodel = to->client.viewmodel; cl.local.repredicting = false; cl.local.moving = false; @@ -1374,7 +1358,7 @@ void CL_PredictMovement( qboolean repredicting ) cl.local.waterlevel = to->client.waterlevel; cl.local.usehull = to->playerstate.usehull; - if( !repredicting || !cl_lw->value ) + if( !repredicting || !CVAR_TO_BOOL( cl_lw )) cl.local.viewmodel = to->client.viewmodel; if( FBitSet( to->client.flags, FL_ONGROUND )) diff --git a/engine/client/cl_qparse.c b/engine/client/cl_qparse.c index 45c9959f..912a9b70 100644 --- a/engine/client/cl_qparse.c +++ b/engine/client/cl_qparse.c @@ -95,6 +95,19 @@ static int CL_UpdateQuakeStats( sizebuf_t *msg, int statnum, qboolean has_update return value; } +/* +================== +CL_UpdateQuakeGameMode + +redirect to qwrap->client +================== +*/ +static void CL_UpdateQuakeGameMode( int gamemode ) +{ + MSG_WriteByte( &msg_demo, gamemode ); + CL_DispatchQuakeMessage( "GameMode" ); +} + /* ================== CL_ParseQuakeSound @@ -132,10 +145,7 @@ static void CL_ParseQuakeSound( sizebuf_t *msg ) handle = cl.sound_index[sound]; if( !cl.audio_prepped ) - { - Con_Printf( S_WARN "CL_StartSoundPacket: ignore sound message: too early\n" ); return; // too early - } S_StartSound( pos, entnum, channel, handle, volume, attn, PITCH_NORM, flags ); } @@ -171,7 +181,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg ) Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION_QUAKE ); cl.maxclients = MSG_ReadByte( msg ); - gametype = MSG_ReadByte( msg ); // FIXME: tell the client about gametype + gametype = MSG_ReadByte( msg ); clgame.maxEntities = GI->max_edicts; clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS ); clgame.maxModels = MAX_MODELS; @@ -283,6 +293,9 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg ) cl.video_prepped = false; cl.audio_prepped = false; + // GAME_COOP or GAME_DEATHMATCH + CL_UpdateQuakeGameMode( gametype ); + // now we can start to precache CL_BatchResourceRequest( true ); @@ -420,6 +433,7 @@ void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits ) ent = CL_EDICT_NUM( newnum ); ent->index = newnum; // enumerate entity index ent->player = CL_IsPlayerIndex( newnum ); + state->animtime = cl.mtime[0]; if( ent->curstate.msg_time != cl.mtime[1] ) forcelink = true; // no previous frame to lerp from @@ -596,7 +610,7 @@ static void CL_ParseQuakeStaticEntity( sizebuf_t *msg ) i = clgame.numStatics; if( i >= MAX_STATIC_ENTITIES ) { - Con_Printf( S_ERROR, "CL_ParseStaticEntity: static entities limit exceeded!\n" ); + Con_Printf( S_ERROR "CL_ParseStaticEntity: static entities limit exceeded!\n" ); return; } @@ -730,7 +744,7 @@ static void CL_ParseQuakeSignon( sizebuf_t *msg ) int i = MSG_ReadByte( msg ); if( i == 3 ) cls.signon = SIGNONS - 1; - Msg( "CL_Signon: %d\n", i ); + Con_Printf( "CL_Signon: %d\n", i ); } /* @@ -819,8 +833,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ) continue; } -// Msg( "%s\n", CL_MsgInfo( cmd )); - // record command for debugging spew on parse problem CL_Parse_RecordCommand( cmd, bufStart ); @@ -855,6 +867,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ) Con_Printf( "%s", MSG_ReadString( msg )); break; case svc_stufftext: + // FIXME: do revision for all Quake and Nehahra console commands str = MSG_ReadString( msg ); Msg( "%s\n", str ); Cbuf_AddText( str ); @@ -881,7 +894,8 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ) case svc_updatefrags: param1 = MSG_ReadByte( msg ); param2 = MSG_ReadShort( msg ); - // FIXME: tell the client about scores + // HACKHACK: store frags into spectator + cl.players[param1].spectator = param2; break; case svc_clientdata: CL_ParseQuakeClientData( msg ); @@ -944,15 +958,15 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ) break; case svc_cdtrack: param1 = MSG_ReadByte( msg ); - param1 = bound( 0, param1, MAX_CDTRACKS ); // tracknum + param1 = bound( 0, param1, MAX_CDTRACKS - 1 ); // tracknum param2 = MSG_ReadByte( msg ); - param2 = bound( 0, param2, MAX_CDTRACKS ); // loopnum - Msg( "main track %d, loop track %d\n", param1, param2 ); - // FIXME: allow cls.forcetrack from demo - S_StartBackgroundTrack( clgame.cdtracks[param1], clgame.cdtracks[param2], 0, false ); + param2 = bound( 0, param2, MAX_CDTRACKS - 1 ); // loopnum + if(( cls.demoplayback || cls.demorecording ) && ( cls.forcetrack != -1 )) + S_StartBackgroundTrack( clgame.cdtracks[cls.forcetrack], clgame.cdtracks[cls.forcetrack], 0, false ); + else S_StartBackgroundTrack( clgame.cdtracks[param1], clgame.cdtracks[param2], 0, false ); break; case svc_sellscreen: - Cmd_ExecuteString( "help" ); + Cmd_ExecuteString( "help" ); // open quake menu break; case svc_cutscene: CL_ParseFinaleCutscene( msg, 3 ); diff --git a/engine/client/cl_remap.c b/engine/client/cl_remap.c index 30ab070e..f445ef7a 100644 --- a/engine/client/cl_remap.c +++ b/engine/client/cl_remap.c @@ -99,7 +99,7 @@ Dupliacte texture with remap pixels */ void CL_DuplicateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { - gltexture_t *glt; + gl_texture_t *glt; texture_t *tx = NULL; char texname[128]; int i, size, index; @@ -141,7 +141,7 @@ Update texture top and bottom colors */ void CL_UpdateStudioTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { - gltexture_t *glt; + gl_texture_t *glt; rgbdata_t *pic; texture_t *tx = NULL; char texname[128], name[128], mdlname[128]; @@ -179,11 +179,11 @@ void CL_UpdateStudioTexture( mstudiotexture_t *ptexture, int topcolor, int botto pic = FS_LoadImage( glt->name, raw, size ); if( !pic ) { - MsgDev( D_ERROR, "Couldn't update texture %s\n", glt->name ); + Con_DPrintf( S_ERROR "Couldn't update texture %s\n", glt->name ); return; } - index = GL_LoadTextureInternal( glt->name, pic, 0, true ); + index = GL_UpdateTextureInternal( glt->name, pic, 0 ); FS_FreeImage( pic ); // restore original palette @@ -224,7 +224,7 @@ void CL_UpdateAliasTexture( unsigned short *texture, int skinnum, int topcolor, skin.buffer = (byte *)(tx + 1); skin.palette = skin.buffer + skin.size; pic = FS_CopyImage( &skin ); // because GL_LoadTextureInternal will freed a rgbdata_t at end - *texture = GL_LoadTextureInternal( texname, pic, TF_KEEP_SOURCE, false ); + *texture = GL_LoadTextureInternal( texname, pic, TF_KEEP_SOURCE ); } // and now we can remap with internal routines diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index d3a2dac5..cc600be3 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -276,9 +276,9 @@ void SCR_MakeScreenShot( void ) { // snapshots don't writes message about image if( cls.scrshot_action != scrshot_snapshot ) - MsgDev( D_REPORT, "Write %s\n", cls.shotname ); + Con_Reportf( "Write %s\n", cls.shotname ); } - else MsgDev( D_ERROR, "Unable to write %s\n", cls.shotname ); + else Con_Printf( S_ERROR "Unable to write %s\n", cls.shotname ); cls.envshot_vieworg = NULL; cls.scrshot_action = scrshot_inactive; @@ -411,10 +411,10 @@ void SCR_TileClear( void ) if( clear.y2 <= clear.y1 ) return; // nothing disturbed - top = RI.viewport[1]; - bottom = top + RI.viewport[3] - 1; - left = RI.viewport[0]; - right = left + RI.viewport[2] - 1; + top = clgame.viewport[1]; + bottom = top + clgame.viewport[3] - 1; + left = clgame.viewport[0]; + right = left + clgame.viewport[2] - 1; if( clear.y1 < top ) { @@ -569,7 +569,7 @@ void SCR_LoadCreditsFont( void ) if( !SCR_LoadVariableWidthFont( "gfx.wad/creditsfont.fnt" )) { if( !SCR_LoadFixedWidthFont( "gfx/conchars" )) - MsgDev( D_ERROR, "failed to load HUD font\n" ); + Con_DPrintf( S_ERROR "failed to load HUD font\n" ); } } @@ -707,7 +707,6 @@ void SCR_Init( void ) { if( scr_init ) return; - MsgDev( D_NOTE, "SCR_Init()\n" ); scr_centertime = Cvar_Get( "scr_centertime", "2.5", 0, "centerprint hold time" ); cl_levelshot_name = Cvar_Get( "cl_levelshot_name", "*black", 0, "contains path to current levelshot" ); cl_allow_levelshots = Cvar_Get( "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" ); @@ -750,7 +749,6 @@ void SCR_Shutdown( void ) { if( !scr_init ) return; - MsgDev( D_NOTE, "SCR_Shutdown()\n" ); Cmd_RemoveCommand( "timerefresh" ); Cmd_RemoveCommand( "skyname" ); Cmd_RemoveCommand( "viewpos" ); diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index d2ad1459..6202f33f 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -593,7 +593,7 @@ TEMPENTITY *CL_TempEntAlloc( const vec3_t org, model_t *pmodel ) if( !cl_free_tents ) { - MsgDev( D_INFO, "Overflow %d temporary ents!\n", GI->max_tents ); + Con_DPrintf( "Overflow %d temporary ents!\n", GI->max_tents ); return NULL; } @@ -633,7 +633,7 @@ TEMPENTITY *CL_TempEntAllocHigh( const vec3_t org, model_t *pmodel ) { // didn't find anything? The tent list is either full of high-priority tents // or all tents in the list are still due to live for > 10 seconds. - MsgDev( D_INFO, "Couldn't alloc a high priority TENT!\n" ); + Con_DPrintf( "Couldn't alloc a high priority TENT!\n" ); return NULL; } @@ -870,10 +870,7 @@ void R_AttachTentToPlayer( int client, int modelIndex, float zoffset, float life model_t *pModel; if( client <= 0 || client > cl.maxclients ) - { - MsgDev( D_ERROR, "Bad client %i in AttachTentToPlayer()!\n", client ); return; - } pClient = CL_GetEntityByIndex( client ); @@ -926,10 +923,7 @@ void R_KillAttachedTents( int client ) int i; if( client <= 0 || client > cl.maxclients ) - { - MsgDev( D_ERROR, "Bad client %i in KillAttachedTents()!\n", client ); return; - } for( i = 0; i < GI->max_tents; i++ ) { @@ -1282,7 +1276,7 @@ TEMPENTITY *R_DefaultSprite( const vec3_t pos, int spriteIndex, float framerate if(( psprite = CL_ModelHandle( spriteIndex )) == NULL || psprite->type != mod_sprite ) { - MsgDev( D_INFO, "No Sprite %d!\n", spriteIndex ); + Con_Reportf( "No Sprite %d!\n", spriteIndex ); return NULL; } @@ -1339,7 +1333,7 @@ TEMPENTITY *R_TempSprite( vec3_t pos, const vec3_t dir, float scale, int modelIn if(( pmodel = CL_ModelHandle( modelIndex )) == NULL ) { - MsgDev( D_ERROR, "No model %d!\n", modelIndex ); + Con_Reportf( S_ERROR "No model %d!\n", modelIndex ); return NULL; } @@ -1446,7 +1440,7 @@ void R_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int if(( pmodel = CL_ModelHandle( modelIndex )) == NULL ) { - MsgDev( D_INFO, "No model %d!\n", modelIndex ); + Con_Reportf( "No model %d!\n", modelIndex ); return; } @@ -1577,7 +1571,7 @@ void R_FunnelSprite( const vec3_t org, int modelIndex, int reverse ) if(( pmodel = CL_ModelHandle( modelIndex )) == NULL ) { - MsgDev( D_ERROR, "no model %d!\n", modelIndex ); + Con_Reportf( S_ERROR "no model %d!\n", modelIndex ); return; } @@ -1823,10 +1817,7 @@ void R_PlayerSprites( int client, int modelIndex, int count, int size ) pEnt = CL_GetEntityByIndex( client ); if( !pEnt || !pEnt->player ) - { - MsgDev( D_INFO, "Bad ent %i in R_PlayerSprites()!\n", client ); return; - } vel = 128; @@ -2511,12 +2502,13 @@ void CL_ParseTempEntity( sizebuf_t *msg ) R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL ); break; default: - MsgDev( D_ERROR, "ParseTempEntity: illegible TE message %i\n", type ); + Con_DPrintf( S_ERROR "ParseTempEntity: illegible TE message %i\n", type ); break; } // throw warning - if( MSG_CheckOverflow( &buf )) MsgDev( D_WARN, "ParseTempEntity: overflow TE message\n" ); + if( MSG_CheckOverflow( &buf )) + Con_DPrintf( S_WARN "ParseTempEntity: overflow TE message\n" ); } @@ -2573,7 +2565,8 @@ void CL_SetLightstyle( int style, const char *s, float f ) break; } } - MsgDev( D_REPORT, "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" ); + + Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" ); } /* @@ -3014,7 +3007,7 @@ void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos if( !pCust->nUserData1 && pCust->pInfo != NULL ) { const char *decalname = va( "player%dlogo%d", playernum, customIndex ); - pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL, false ); + pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL ); } textureIndex = pCust->nUserData1; } diff --git a/engine/client/cl_video.c b/engine/client/cl_video.c index d2861158..58de74b2 100644 --- a/engine/client/cl_video.c +++ b/engine/client/cl_video.c @@ -209,7 +209,7 @@ qboolean SCR_PlayCinematic( const char *arg ) if( FS_FileExists( arg, false ) && !fullpath ) { - MsgDev( D_ERROR, "Couldn't load %s from packfile. Please extract it\n", path ); + Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", path ); return false; } @@ -235,6 +235,7 @@ qboolean SCR_PlayCinematic( const char *arg ) UI_SetActiveMenu( false ); cls.state = ca_cinematic; + Con_FastClose(); cin_time = 0.0f; cls.signon = 0; diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index 28bffe78..78ab8722 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -286,7 +286,7 @@ qboolean V_PreRender( void ) { if(( host.realtime - cls.disable_screen ) > cl_timeout->value ) { - MsgDev( D_ERROR, "V_PreRender: loading plaque timed out\n" ); + Con_Reportf( "V_PreRender: loading plaque timed out\n" ); cls.disable_screen = 0.0f; } return false; diff --git a/engine/client/client.h b/engine/client/client.h index df9f30a4..a5b3ad0f 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -948,6 +948,7 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType ); void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset ); qboolean CL_GetEntitySpatialization( struct channel_s *ch ); qboolean CL_GetMovieSpatialization( struct rawchan_s *ch ); +void CL_ProcessPlayerState( int playerindex, entity_state_t *state ); void CL_ComputePlayerOrigin( cl_entity_t *clent ); void CL_ProcessPacket( frame_t *frame ); void CL_MoveThirdpersonCamera( void ); diff --git a/engine/client/gl_alias.c b/engine/client/gl_alias.c index 124f23ec..e7df65d8 100644 --- a/engine/client/gl_alias.c +++ b/engine/client/gl_alias.c @@ -487,7 +487,7 @@ void *Mod_LoadSingleSkin( daliasskintype_t *pskintype, int skinnum, int size ) m_pAliasHeader->gl_texturenum[skinnum][0] = m_pAliasHeader->gl_texturenum[skinnum][1] = m_pAliasHeader->gl_texturenum[skinnum][2] = - m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0, false ); + m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 ); FS_FreeImage( pic ); if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags & TF_HAS_LUMA ) @@ -496,7 +496,7 @@ void *Mod_LoadSingleSkin( daliasskintype_t *pskintype, int skinnum, int size ) m_pAliasHeader->fb_texturenum[skinnum][0] = m_pAliasHeader->fb_texturenum[skinnum][1] = m_pAliasHeader->fb_texturenum[skinnum][2] = - m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA, false ); + m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA ); FS_FreeImage( pic ); } @@ -521,14 +521,14 @@ void *Mod_LoadGroupSkin( daliasskintype_t *pskintype, int skinnum, int size ) { Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, skinnum, i ); pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); - m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0, false ); + m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0 ); FS_FreeImage( pic ); if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags & TF_HAS_LUMA ) { Q_snprintf( lumaname, sizeof( lumaname ), "%s_%i_%i_luma", loadmodel->name, skinnum, i ); pic = Mod_CreateSkinData( NULL, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); - m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA, false ); + m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA ); FS_FreeImage( pic ); } diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index 71a94888..003c4683 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -185,7 +185,7 @@ void GL_SelectTexture( GLint tmu ) if( tmu >= GL_MaxTextureUnits( )) { - MsgDev( D_ERROR, "GL_SelectTexture: bad tmu state %i\n", tmu ); + Con_Reportf( S_ERROR "GL_SelectTexture: bad tmu state %i\n", tmu ); return; } @@ -249,6 +249,7 @@ GL_CleanupAllTextureUnits */ void GL_CleanupAllTextureUnits( void ) { + if( !glw_state.initialized ) return; // force to cleanup all the units GL_SelectTexture( GL_MaxTextureUnits() - 1 ); GL_CleanUpTextureUnits( 0 ); @@ -277,7 +278,7 @@ void GL_TextureTarget( uint target ) { if( glState.activeTMU < 0 || glState.activeTMU >= GL_MaxTextureUnits( )) { - MsgDev( D_ERROR, "GL_TextureTarget: bad tmu state %i\n", glState.activeTMU ); + Con_Reportf( S_ERROR "GL_TextureTarget: bad tmu state %i\n", glState.activeTMU ); return; } @@ -644,7 +645,7 @@ was there. This is used to test for texture thrashing. */ void R_ShowTextures( void ) { - gltexture_t *image; + gl_texture_t *image; float x, y, w, h; int total, start, end; int i, j, k, base_w, base_h; diff --git a/engine/client/gl_beams.c b/engine/client/gl_beams.c index f73b53d7..a0b67d76 100644 --- a/engine/client/gl_beams.c +++ b/engine/client/gl_beams.c @@ -266,7 +266,7 @@ static qboolean R_BeamComputePoint( int beamEnt, vec3_t pt ) if( !ent ) { - MsgDev( D_ERROR, "R_BeamComputePoint: invalid entity %i\n", BEAMENT_ENTITY( beamEnt )); + Con_DPrintf( S_ERROR "R_BeamComputePoint: invalid entity %i\n", BEAMENT_ENTITY( beamEnt )); VectorClear( pt ); return false; } @@ -418,8 +418,6 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f div = 1.0f / (segments - 1); length *= 0.01f; - - // UNDONE: Expose texture length scale factor to control "fuzziness" vStep = length * div; // Texture length texels per space pixel // Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) @@ -432,22 +430,18 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f segments = 16; div = 1.0f / ( segments - 1 ); } - scale *= 100.0f; length = segments * 0.1f; } else { - scale *= length; + scale *= length * 2.0; } // Iterator to resample noise waveform (it needs to be generated in powers of 2) - noiseStep = noiseIndex = (int)((float)( NOISE_DIVISIONS - 1 ) * div * 65536.0f ); - - if( FBitSet( flags, FBEAM_SINENOISE )) - noiseIndex = 0; - + noiseStep = (int)((float)( NOISE_DIVISIONS - 1 ) * div * 65536.0f ); brightness = 1.0f; + noiseIndex = 0; if( FBitSet( flags, FBEAM_SHADEIN )) brightness = 0; @@ -468,20 +462,6 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f fraction = i * div; - if( FBitSet( flags, FBEAM_SHADEIN ) && FBitSet( flags, FBEAM_SHADEOUT )) - { - if( fraction < 0.5f ) brightness = 2.0f * fraction; - else brightness = 2.0f * ( 1.0f - fraction ); - } - else if( FBitSet( flags, FBEAM_SHADEIN )) - { - brightness = fraction; - } - else if( FBitSet( flags, FBEAM_SHADEOUT )) - { - brightness = 1.0f - fraction; - } - VectorMA( source, fraction, delta, nextSeg.pos ); // distort using noise @@ -549,6 +529,20 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f curSeg = nextSeg; segs_drawn++; + if( FBitSet( flags, FBEAM_SHADEIN ) && FBitSet( flags, FBEAM_SHADEOUT )) + { + if( fraction < 0.5f ) brightness = fraction; + else brightness = ( 1.0f - fraction ); + } + else if( FBitSet( flags, FBEAM_SHADEIN )) + { + brightness = fraction; + } + else if( FBitSet( flags, FBEAM_SHADEOUT )) + { + brightness = 1.0f - fraction; + } + if( segs_drawn == total_segs ) { // draw the last segment @@ -1377,7 +1371,7 @@ void CL_AddCustomBeam( cl_entity_t *pEnvBeam ) { if( tr.draw_list->num_beam_entities >= MAX_VISIBLE_PACKET ) { - MsgDev( D_ERROR, "Too many custom beams %d!\n", tr.draw_list->num_beam_entities ); + Con_Printf( S_ERROR "Too many beams %d!\n", tr.draw_list->num_beam_entities ); return; } @@ -1492,7 +1486,7 @@ void CL_DrawBeams( int fTrans ) BEAM *pPrev = NULL; int i, flags; - if( !cl_draw_beams->value ) + if( !CVAR_TO_BOOL( cl_draw_beams )) return; pglShadeModel( GL_SMOOTH ); @@ -1871,7 +1865,6 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType ) R_BeamEnts( startEnt, endEnt, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); break; case TE_BEAM: - MsgDev( D_ERROR, "TE_BEAM is obsolete\n" ); break; case TE_BEAMSPRITE: start[0] = MSG_ReadCoord( msg ); @@ -1934,7 +1927,6 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType ) R_BeamRing( startEnt, endEnt, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); break; case TE_BEAMHOSE: - MsgDev( D_ERROR, "TE_BEAMHOSE is obsolete\n" ); break; case TE_KILLBEAM: startEnt = MSG_ReadShort( msg ); diff --git a/engine/client/gl_decals.c b/engine/client/gl_decals.c index 0b4aa75a..69ab86ec 100644 --- a/engine/client/gl_decals.c +++ b/engine/client/gl_decals.c @@ -577,11 +577,7 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl decal_t *pdecal, *pold; int count, vertCount; - if( !surf ) - { - MsgDev( D_ERROR, "psurface NULL in R_DecalCreate!\n" ); - return; - } + if( !surf ) return; // ??? pold = R_DecalIntersect( decalinfo, surf, &count ); if( count < MAX_OVERLAP_DECALS ) pold = NULL; @@ -763,7 +759,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos if( textureIndex <= 0 || textureIndex >= MAX_TEXTURES ) { - MsgDev( D_ERROR, "Decal has invalid texture!\n" ); + Con_Printf( S_ERROR "Decal has invalid texture!\n" ); return; } @@ -783,7 +779,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos if( model->type != mod_brush ) { - MsgDev( D_ERROR, "Decals must hit mod_brush!\n" ); + Con_Printf( S_ERROR "Decals must hit mod_brush!\n" ); return; } @@ -988,7 +984,6 @@ void DrawSurfaceDecals( msurface_t *fa, qboolean single, qboolean reverse ) } } - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( reverse && e->curstate.rendermode == kRenderTransTexture ) @@ -1224,10 +1219,7 @@ void R_DecalRemoveAll( int textureIndex ) int i; if( textureIndex < 0 || textureIndex >= MAX_TEXTURES ) - { - MsgDev( D_ERROR, "Decal has invalid texture!\n" ); - return; - } + return; // out of bounds for( i = 0; i < gDecalCount; i++ ) { diff --git a/engine/client/gl_draw.c b/engine/client/gl_draw.c index eab1b3b7..f970e409 100644 --- a/engine/client/gl_draw.c +++ b/engine/client/gl_draw.c @@ -24,7 +24,7 @@ R_GetImageParms */ void R_GetTextureParms( int *w, int *h, int texnum ) { - gltexture_t *glt; + gl_texture_t *glt; glt = R_GetTexture( texnum ); if( w ) *w = glt->srcWidth; @@ -94,7 +94,7 @@ refresh window. void R_DrawTileClear( int x, int y, int w, int h ) { float tw, th; - gltexture_t *glt; + gl_texture_t *glt; GL_SetRenderMode( kRenderNormal ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); @@ -124,7 +124,7 @@ R_DrawStretchRaw void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) { byte *raw = NULL; - gltexture_t *tex; + gl_texture_t *tex; if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { @@ -196,7 +196,7 @@ R_UploadStretchRaw void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data ) { byte *raw = NULL; - gltexture_t *tex; + gl_texture_t *tex; if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { diff --git a/engine/client/gl_export.h b/engine/client/gl_export.h index 22ff3fdc..f75564c0 100644 --- a/engine/client/gl_export.h +++ b/engine/client/gl_export.h @@ -148,6 +148,7 @@ typedef float GLmatrix[16]; #define GL_2_BYTES 0x1407 #define GL_3_BYTES 0x1408 #define GL_4_BYTES 0x1409 +#define GL_HALF_FLOAT_ARB 0x140B #define GL_VERTEX_ARRAY 0x8074 #define GL_NORMAL_ARRAY 0x8075 @@ -390,6 +391,7 @@ typedef float GLmatrix[16]; #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD #define GL_COMPRESSED_ALPHA_ARB 0x84E9 #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 699cca8c..7006b0dc 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -16,18 +16,12 @@ GNU General Public License for more details. #include "common.h" #include "client.h" #include "gl_local.h" -#include "studio.h" #define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2) -static gltexture_t r_textures[MAX_TEXTURES]; -static gltexture_t *r_texturesHashTable[TEXTURES_HASH_SIZE]; -static byte data2D[1024]; // intermediate texbuffer -static int r_numTextures; -static rgbdata_t r_image; // generic pixelbuffer used for internal textures - -// internal tables -static vec3_t r_luminanceTable[256]; // RGB to luminance +static gl_texture_t gl_textures[MAX_TEXTURES]; +static gl_texture_t* gl_texturesHashTable[TEXTURES_HASH_SIZE]; +static uint gl_numTextures; #define IsLightMap( tex ) ( FBitSet(( tex )->flags, TF_ATLAS_PAGE )) /* @@ -37,10 +31,10 @@ R_GetTexture acess to array elem ================= */ -gltexture_t *R_GetTexture( GLenum texnum ) +gl_texture_t *R_GetTexture( GLenum texnum ) { ASSERT( texnum >= 0 && texnum < MAX_TEXTURES ); - return &r_textures[texnum]; + return &gl_textures[texnum]; } /* @@ -75,18 +69,20 @@ GL_Bind */ void GL_Bind( GLint tmu, GLenum texnum ) { - gltexture_t *texture; + gl_texture_t *texture; GLuint glTarget; - // missed texture ? - if( texnum <= 0 ) texnum = tr.defaultTexture; - Assert( texnum > 0 && texnum < MAX_TEXTURES ); + Assert( texnum >= 0 && texnum < MAX_TEXTURES ); + + // missed or invalid texture? + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + texnum = tr.defaultTexture; if( tmu != GL_KEEP_UNIT ) GL_SelectTexture( tmu ); else tmu = glState.activeTMU; - texture = &r_textures[texnum]; + texture = &gl_textures[texnum]; glTarget = texture->target; if( glTarget == GL_TEXTURE_2D_ARRAY_EXT ) @@ -112,7 +108,7 @@ void GL_Bind( GLint tmu, GLenum texnum ) GL_ApplyTextureParams ================= */ -void GL_ApplyTextureParams( gltexture_t *tex ) +void GL_ApplyTextureParams( gl_texture_t *tex ) { vec4_t border = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -247,7 +243,7 @@ GL_UpdateTextureParams */ static void GL_UpdateTextureParams( int iTexture ) { - gltexture_t *tex = &r_textures[iTexture]; + gl_texture_t *tex = &gl_textures[iTexture]; Assert( tex != NULL ); @@ -322,7 +318,7 @@ void R_SetTextureParameters( void ) ClearBits( gl_lightmap_nearest->flags, FCVAR_CHANGED ); // change all the existing mipmapped texture objects - for( i = 0; i < r_numTextures; i++ ) + for( i = 0; i < gl_numTextures; i++ ) GL_UpdateTextureParams( i ); } @@ -365,6 +361,7 @@ static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int d break; case PF_DXT3: case PF_DXT5: + case PF_ATI2: size = (((width + 3) >> 2) * ((height + 3) >> 2) * 16) * depth; break; } @@ -392,6 +389,7 @@ static size_t GL_CalcTextureSize( GLenum format, int width, int height, int dept break; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: size = (((width + 3) >> 2) * ((height + 3) >> 2) * 16) * depth; break; case GL_RGBA8: @@ -458,7 +456,7 @@ static size_t GL_CalcTextureSize( GLenum format, int width, int height, int dept size = width * height * depth * 2; break; case GL_DEPTH_COMPONENT24: - size = width * height * depth * 4; + size = width * height * depth * 3; break; case GL_DEPTH_COMPONENT32F: size = width * height * depth * 4; @@ -471,7 +469,7 @@ static size_t GL_CalcTextureSize( GLenum format, int width, int height, int dept return size; } -static int GL_CalcMipmapCount( gltexture_t *tex, qboolean haveBuffer ) +static int GL_CalcMipmapCount( gl_texture_t *tex, qboolean haveBuffer ) { int width, height; int mipcount; @@ -502,7 +500,7 @@ static int GL_CalcMipmapCount( gltexture_t *tex, qboolean haveBuffer ) GL_SetTextureDimensions ================ */ -static void GL_SetTextureDimensions( gltexture_t *tex, int width, int height, int depth ) +static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height, int depth ) { int maxTextureSize; int maxDepthSize = 1; @@ -591,7 +589,7 @@ static void GL_SetTextureDimensions( gltexture_t *tex, int width, int height, in GL_SetTextureTarget =============== */ -static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) +static void GL_SetTextureTarget( gl_texture_t *tex, rgbdata_t *pic ) { Assert( pic != NULL ); Assert( tex != NULL ); @@ -612,7 +610,7 @@ static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) tex->target = GL_TEXTURE_2D_ARRAY_EXT; else if( pic->width > 1 && pic->height > 1 && pic->depth > 1 ) tex->target = GL_TEXTURE_3D; - else if( FBitSet( tex->flags, TF_TEXTURE_RECTANGLE ) && pic->width == glState.width && pic->height == glState.height ) + else if( FBitSet( tex->flags, TF_RECTANGLE )) tex->target = GL_TEXTURE_RECTANGLE_EXT; else tex->target = GL_TEXTURE_2D; // default case @@ -636,9 +634,6 @@ static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) // depth cubemaps only allowed when GL_EXT_gpu_shader4 is supported if( tex->target == GL_TEXTURE_CUBE_MAP_ARB && !GL_Support( GL_EXT_GPU_SHADER4 ) && FBitSet( tex->flags, TF_DEPTHMAP )) tex->target = GL_NONE; - - if( tex->target == GL_TEXTURE_CUBE_MAP_ARB ) - tex->flags |= TF_CUBEMAP; // it's cubemap! } /* @@ -646,7 +641,7 @@ static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) GL_SetTextureFormat =============== */ -static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int channelMask ) +static void GL_SetTextureFormat( gl_texture_t *tex, pixformat_t format, int channelMask ) { qboolean haveColor = ( channelMask & IMAGE_HAS_COLOR ); qboolean haveAlpha = ( channelMask & IMAGE_HAS_ALPHA ); @@ -660,6 +655,7 @@ static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int chann case PF_DXT1: tex->format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; // never use DXT1 with 1-bit alpha case PF_DXT3: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case PF_DXT5: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; + case PF_ATI2: tex->format = GL_COMPRESSED_RED_GREEN_RGTC2_EXT; break; } return; } @@ -671,7 +667,7 @@ static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int chann tex->format = GL_DEPTH_COMPONENT32F; else tex->format = GL_DEPTH_COMPONENT24; } - else if( FBitSet( tex->flags, TF_ARB_FLOAT ) && GL_Support( GL_ARB_TEXTURE_FLOAT_EXT )) + else if( FBitSet( tex->flags, TF_ARB_FLOAT|TF_ARB_16BIT ) && GL_Support( GL_ARB_TEXTURE_FLOAT_EXT )) { if( haveColor && haveAlpha ) { @@ -895,31 +891,6 @@ byte *GL_ApplyFilter( const byte *source, int width, int height ) return out; } -/* -================= -GL_ApplyGamma - -Assume input buffer is RGBA -================= -*/ -byte *GL_ApplyGamma( const byte *source, int pixels, qboolean isNormalMap ) -{ - byte *in = (byte *)source; - byte *out = (byte *)source; - int i; - - if( source && !isNormalMap ) - { - for( i = 0; i < pixels; i++, in += 4 ) - { - in[0] = TextureToGamma( in[0] ); - in[1] = TextureToGamma( in[1] ); - in[2] = TextureToGamma( in[2] ); - } - } - return out; -} - /* ================= GL_BuildMipMap @@ -974,7 +945,6 @@ static void GL_BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, normal[2] = MAKE_SIGNED( in[row+2] ) + MAKE_SIGNED( next[row+2] ); } - if( !VectorNormalizeLength( normal )) VectorSet( normal, 0.5f, 0.5f, 1.0f ); @@ -1012,48 +982,23 @@ static void GL_BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, } } -/* -================= -GL_MakeLuminance - -Converts the given image to luminance -================= -*/ -void GL_MakeLuminance( rgbdata_t *in ) -{ - byte luminance; - float r, g, b; - int x, y; - - for( y = 0; y < in->height; y++ ) - { - for( x = 0; x < in->width; x++ ) - { - r = r_luminanceTable[in->buffer[4*(y*in->width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*in->width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*in->width+x)+2]][2]; - - luminance = (byte)(r + g + b); - - in->buffer[4*(y*in->width+x)+0] = luminance; - in->buffer[4*(y*in->width+x)+1] = luminance; - in->buffer[4*(y*in->width+x)+2] = luminance; - } - } -} - -static void GL_TextureImageRAW( gltexture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, GLint type, const void *data ) +static void GL_TextureImageRAW( gl_texture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, GLint type, const void *data ) { GLuint cubeTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - qboolean subImage = ( tex->flags & TF_IMG_UPLOADED ); + qboolean subImage = FBitSet( tex->flags, TF_IMG_UPLOADED ); GLenum inFormat = PFDesc[type].glFormat; GLint dataType = GL_UNSIGNED_BYTE; Assert( tex != NULL ); - if( tex->flags & TF_DEPTHMAP ) + if( FBitSet( tex->flags, TF_DEPTHMAP )) inFormat = GL_DEPTH_COMPONENT; + if( FBitSet( tex->flags, TF_ARB_16BIT )) + dataType = GL_HALF_FLOAT_ARB; + else if( FBitSet( tex->flags, TF_ARB_FLOAT )) + dataType = GL_FLOAT; + if( tex->target == GL_TEXTURE_1D ) { if( subImage ) pglTexSubImage1D( tex->target, level, 0, width, inFormat, dataType, data ); @@ -1076,10 +1021,10 @@ static void GL_TextureImageRAW( gltexture_t *tex, GLint side, GLint level, GLint } } -static void GL_TextureImageDXT( gltexture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, size_t size, const void *data ) +static void GL_TextureImageDXT( gl_texture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, size_t size, const void *data ) { GLuint cubeTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - qboolean subImage = ( tex->flags & TF_IMG_UPLOADED ); + qboolean subImage = FBitSet( tex->flags, TF_IMG_UPLOADED ); Assert( tex != NULL ); @@ -1112,15 +1057,15 @@ GL_CheckTexImageError show GL-errors on load images =============== */ -static void GL_CheckTexImageError( gltexture_t *tex ) +static void GL_CheckTexImageError( gl_texture_t *tex ) { int err; Assert( tex != NULL ); // catch possible errors - if(( err = pglGetError()) != GL_NO_ERROR ) - MsgDev( D_ERROR, "GL_UploadTexture: error %x while uploading %s [%s]\n", err, tex->name, GL_TargetToString( tex->target )); + if( CVAR_TO_BOOL( gl_check_errors ) && ( err = pglGetError()) != GL_NO_ERROR ) + Con_Printf( S_OPENGL_ERROR "%s while uploading %s [%s]\n", GL_ErrorString( err ), tex->name, GL_TargetToString( tex->target )); } /* @@ -1130,7 +1075,7 @@ GL_UploadTexture upload texture into video memory =============== */ -static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) +static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) { byte *buf, *data; size_t texsize, size; @@ -1148,7 +1093,7 @@ static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) // make sure what target is correct if( tex->target == GL_NONE ) { - MsgDev( D_ERROR, "GL_UploadTexture: %s is not supported by your hardware\n", tex->name ); + Con_DPrintf( S_ERROR "GL_UploadTexture: %s is not supported by your hardware\n", tex->name ); return false; } @@ -1224,10 +1169,7 @@ static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) if(( tex->depth == 1 ) && ( pic->width != tex->width ) || ( pic->height != tex->height )) data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap ); else data = buf; -#if 0 // g-cont. we can't apply gamma to each texture so we shouldn't do it at all - if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP|TF_SKYSIDE )) - data = GL_ApplyGamma( data, tex->width * tex->height * tex->depth, FBitSet( tex->flags, TF_NORMALMAP )); -#endif + if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA )) data = GL_ApplyFilter( data, tex->width, tex->height ); @@ -1253,7 +1195,7 @@ static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) } } - tex->flags |= TF_IMG_UPLOADED; // done + SetBits( tex->flags, TF_IMG_UPLOADED ); // done tex->numMips /= numSides; return true; @@ -1266,7 +1208,7 @@ GL_ProcessImage do specified actions on pixels =============== */ -static void GL_ProcessImage( gltexture_t *tex, rgbdata_t *pic, imgfilter_t *filter ) +static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic, imgfilter_t *filter ) { uint img_flags = 0; @@ -1310,14 +1252,166 @@ static void GL_ProcessImage( gltexture_t *tex, rgbdata_t *pic, imgfilter_t *filt // processing image before uploading (force to rgba, make luma etc) if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags, filter ); - if( tex->flags & TF_LUMINANCE ) + if( FBitSet( tex->flags, TF_LUMINANCE )) + ClearBits( pic->flags, IMAGE_HAS_COLOR ); + } +} + +/* +================ +GL_CheckTexName +================ +*/ +qboolean GL_CheckTexName( const char *name ) +{ + if( !COM_CheckString( name ) || !glw_state.initialized ) + return false; + + // because multi-layered textures can exceed name string + if( Q_strlen( name ) >= sizeof( gl_textures->name )) + { + Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); + return false; + } + + return true; +} + +/* +================ +GL_TextureForName +================ +*/ +static gl_texture_t *GL_TextureForName( const char *name ) +{ + gl_texture_t *tex; + uint hash; + + // find the texture in array + hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); + + for( tex = gl_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) + { + if( !Q_stricmp( tex->name, name )) + return tex; + } + + return NULL; +} + +/* +================ +GL_AllocTexture +================ +*/ +static gl_texture_t *GL_AllocTexture( const char *name, texFlags_t flags ) +{ + gl_texture_t *tex; + uint i; + + // find a free texture_t slot + for( i = 0, tex = gl_textures; i < gl_numTextures; i++, tex++ ) + if( !tex->name[0] ) break; + + if( i == gl_numTextures ) + { + if( gl_numTextures == MAX_TEXTURES ) + Host_Error( "GL_AllocTexture: MAX_TEXTURES limit exceeds\n" ); + gl_numTextures++; + } + + tex = &gl_textures[i]; + + // copy initial params + Q_strncpy( tex->name, name, sizeof( tex->name )); + if( FBitSet( flags, TF_SKYSIDE )) + tex->texnum = tr.skyboxbasenum++; + else tex->texnum = i; // texnum is used for fast acess into gl_textures array too + tex->flags = flags; + + // add to hash table + tex->hashValue = COM_HashKey( name, TEXTURES_HASH_SIZE ); + tex->nextHash = gl_texturesHashTable[tex->hashValue]; + gl_texturesHashTable[tex->hashValue] = tex; + + return tex; +} + +/* +================ +GL_DeleteTexture +================ +*/ +static void GL_DeleteTexture( gl_texture_t *tex ) +{ + gl_texture_t **prev; + gl_texture_t *cur; + + ASSERT( tex != NULL ); + + // already freed? + if( !tex->texnum ) return; + + // debug + if( !tex->name[0] ) + { + Con_Printf( S_ERROR "GL_DeleteTexture: trying to free unnamed texture with texnum %i\n", tex->texnum ); + return; + } + + // remove from hash table + prev = &gl_texturesHashTable[tex->hashValue]; + + while( 1 ) + { + cur = *prev; + if( !cur ) break; + + if( cur == tex ) { - if( !( tex->flags & TF_DEPTHMAP )) - { - GL_MakeLuminance( pic ); - tex->flags &= ~TF_LUMINANCE; - } - pic->flags &= ~IMAGE_HAS_COLOR; + *prev = cur->nextHash; + break; + } + prev = &cur->nextHash; + } + + // release source + if( tex->original ) + FS_FreeImage( tex->original ); + + pglDeleteTextures( 1, &tex->texnum ); + memset( tex, 0, sizeof( *tex )); +} + +/* +================ +GL_UpdateTexSize + +recalc image room +================ +*/ +void GL_UpdateTexSize( int texnum, int width, int height, int depth ) +{ + int i, j, texsize; + int numSides; + gl_texture_t *tex; + + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + return; + + tex = &gl_textures[texnum]; + numSides = FBitSet( tex->flags, TF_CUBEMAP ) ? 6 : 1; + GL_SetTextureDimensions( tex, width, height, depth ); + tex->size = 0; // recompute now + + for( i = 0; i < numSides; i++ ) + { + for( j = 0; j < Q_max( 1, tex->numMips ); j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( tex->format, width, height, tex->depth ); + tex->size += texsize; } } } @@ -1329,34 +1423,22 @@ GL_LoadTexture */ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, imgfilter_t *filter ) { - gltexture_t *tex; + gl_texture_t *tex; rgbdata_t *pic; - uint i, hash; uint picFlags = 0; - if( !COM_CheckString( name ) || !glw_state.initialized ) + if( !GL_CheckTexName( name )) return 0; - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return 0; - } - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); + if(( tex = GL_TextureForName( name ))) + return (tex - gl_textures); - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - return (tex - r_textures); - } - - if( flags & TF_NOFLIP_TGA ) - picFlags |= IL_DONTFLIP_TGA; + if( FBitSet( flags, TF_NOFLIP_TGA )) + SetBits( picFlags, IL_DONTFLIP_TGA ); if( FBitSet( flags, TF_KEEP_SOURCE ) && !FBitSet( flags, TF_EXPAND_SOURCE )) - picFlags |= IL_KEEP_8BIT; + SetBits( picFlags, IL_KEEP_8BIT ); // set some image flags Image_SetForceFlags( picFlags ); @@ -1364,34 +1446,13 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, i pic = FS_LoadImage( name, buf, size ); if( !pic ) return 0; // couldn't loading image - // find a free texture slot - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - // find a free texture_t slot - for( i = 0, tex = r_textures; i < r_numTextures; i++, tex++ ) - if( !tex->name[0] ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - r_numTextures++; - } - - tex = &r_textures[i]; - Q_strncpy( tex->name, name, sizeof( tex->name )); - tex->flags = flags; - - if( flags & TF_SKYSIDE ) - tex->texnum = tr.skyboxbasenum++; - else tex->texnum = i; // texnum is used for fast acess into r_textures array too - + // allocate the new one + tex = GL_AllocTexture( name, flags ); GL_ProcessImage( tex, pic, filter ); if( !GL_UploadTexture( tex, pic )) { - memset( tex, 0, sizeof( gltexture_t )); + memset( tex, 0, sizeof( gl_texture_t )); FS_FreeImage( pic ); // release source texture return 0; } @@ -1399,13 +1460,8 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, i GL_ApplyTextureParams( tex ); // update texture filter, wrap etc FS_FreeImage( pic ); // release source texture - // add to hash table - tex->hashValue = COM_HashKey( tex->name, TEXTURES_HASH_SIZE ); - tex->nextHash = r_texturesHashTable[tex->hashValue]; - r_texturesHashTable[tex->hashValue] = tex; - // NOTE: always return texnum as index in array or engine will stop work !!! - return i; + return tex - gl_textures; } /* @@ -1415,13 +1471,13 @@ GL_LoadTextureArray */ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) { - gltexture_t *tex; rgbdata_t *pic, *src; char basename[256]; uint numLayers = 0; uint picFlags = 0; char name[256]; - uint i, j, hash; + gl_texture_t *tex; + uint i, j; if( !names || !names[0] || !glw_state.initialized ) return 0; @@ -1443,20 +1499,12 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) Q_strncat( name, va( "[%i]", numLayers ), sizeof( name )); - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "LoadTextureArray: too long name %s (%d)\n", name, Q_strlen( name )); + if( !GL_CheckTexName( name )) return 0; - } // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - return (tex - r_textures); - } + if(( tex = GL_TextureForName( name ))) + return (tex - gl_textures); // load all the images and pack it into single image for( i = 0, pic = NULL; i < numLayers; i++ ) @@ -1471,20 +1519,20 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) // mixed mode: DXT + RGB if( pic->type != src->type ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch image format for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch image format for %s and %s\n", names[0], names[i] ); break; } // different mipcount if( pic->numMips != src->numMips ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch mip count for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch mip count for %s and %s\n", names[0], names[i] ); break; } if( pic->encode != src->encode ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch custom encoding for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch custom encoding for %s and %s\n", names[0], names[i] ); break; } @@ -1494,7 +1542,7 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) if( pic->size != src->size ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch image size for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch image size for %s and %s\n", names[0], names[i] ); break; } } @@ -1513,8 +1561,8 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) for( j = 0; j < max( 1, pic->numMips ); j++ ) { - int width = max( 1, ( pic->width >> j )); - int height = max( 1, ( pic->height >> j )); + int width = Q_max( 1, ( pic->width >> j )); + int height = Q_max( 1, ( pic->height >> j )); mipsize = GL_CalcImageSize( pic->type, width, height, 1 ); memcpy( pic->buffer + dstsize + mipsize * i, src->buffer + srcsize, mipsize ); dstsize += mipsize * numLayers; @@ -1530,39 +1578,22 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) // there were errors if( !pic || ( pic->depth != numLayers )) { - MsgDev( D_ERROR, "GL_LoadTextureArray: not all layers were loaded. Texture array is not created\n" ); + Con_Printf( S_ERROR "GL_LoadTextureArray: not all layers were loaded. Texture array is not created\n" ); if( pic ) FS_FreeImage( pic ); return 0; } // it's multilayer image! - pic->flags |= IMAGE_MULTILAYER; + SetBits( pic->flags, IMAGE_MULTILAYER ); pic->size *= numLayers; - // find a free texture slot - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - // find a free texture_t slot - for( i = 0, tex = r_textures; i < r_numTextures; i++, tex++ ) - if( !tex->name[0] ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - r_numTextures++; - } - - tex = &r_textures[i]; - Q_strncpy( tex->name, name, sizeof( tex->name )); - tex->flags = flags; - tex->texnum = i; // texnum is used for fast acess into r_textures array too - + // allocate the new one + tex = GL_AllocTexture( name, flags ); GL_ProcessImage( tex, pic, filter ); + if( !GL_UploadTexture( tex, pic )) { - memset( tex, 0, sizeof( gltexture_t )); + memset( tex, 0, sizeof( gl_texture_t )); FS_FreeImage( pic ); // release source texture return 0; } @@ -1570,98 +1601,50 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) GL_ApplyTextureParams( tex ); // update texture filter, wrap etc FS_FreeImage( pic ); // release source texture - // add to hash table - tex->hashValue = COM_HashKey( tex->name, TEXTURES_HASH_SIZE ); - tex->nextHash = r_texturesHashTable[tex->hashValue]; - r_texturesHashTable[tex->hashValue] = tex; - // NOTE: always return texnum as index in array or engine will stop work !!! - return i; + return tex - gl_textures; } /* ================ -GL_LoadTextureInternal +GL_LoadTextureFromBuffer ================ */ -int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) +int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) { - gltexture_t *tex; - uint i, hash; + gl_texture_t *tex; - if( !COM_CheckString( name ) || !glw_state.initialized ) + if( !GL_CheckTexName( name )) return 0; - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return 0; - } - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); + if(( tex = GL_TextureForName( name )) && !update ) + return (tex - gl_textures); - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) + // couldn't loading image + if( !pic ) return 0; + + if( update ) { - if( !Q_stricmp( tex->name, name )) - { - if( update ) break; - return (tex - r_textures); - } - } - - if( !pic ) return 0; // couldn't loading image - if( update && !tex ) - { - Host_Error( "Couldn't find texture %s for update\n", name ); - } - - // find a free texture slot - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - if( !update ) - { - // find a free texture_t slot - for( i = 0, tex = r_textures; i < r_numTextures; i++, tex++ ) - if( !tex->name[0] ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - r_numTextures++; - } - - tex = &r_textures[i]; - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - Q_strncpy( tex->name, name, sizeof( tex->name )); - tex->texnum = i; // texnum is used for fast acess into r_textures array too - tex->flags = flags; + if( tex == NULL ) + Host_Error( "GL_LoadTextureFromBuffer: couldn't find texture %s for update\n", name ); + SetBits( tex->flags, flags ); } else { - tex->flags |= flags; + // allocate the new one + tex = GL_AllocTexture( name, flags ); } GL_ProcessImage( tex, pic, NULL ); if( !GL_UploadTexture( tex, pic )) { - memset( tex, 0, sizeof( gltexture_t )); + memset( tex, 0, sizeof( gl_texture_t )); return 0; } GL_ApplyTextureParams( tex ); // update texture filter, wrap etc - - if( !update ) - { - // add to hash table - tex->hashValue = COM_HashKey( tex->name, TEXTURES_HASH_SIZE ); - tex->nextHash = r_texturesHashTable[tex->hashValue]; - r_texturesHashTable[tex->hashValue] = tex; - } - - return (tex - r_textures); + return (tex - gl_textures); } /* @@ -1673,43 +1656,40 @@ creates texture from buffer */ int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ) { + int datasize = 1; rgbdata_t r_empty; - int texture; + + if( FBitSet( flags, TF_ARB_16BIT )) + datasize = 2; + else if( FBitSet( flags, TF_ARB_FLOAT )) + datasize = 4; memset( &r_empty, 0, sizeof( r_empty )); r_empty.width = width; r_empty.height = height; r_empty.type = PF_RGBA_32; - r_empty.size = r_empty.width * r_empty.height * 4; - r_empty.flags = IMAGE_HAS_COLOR | (( flags & TF_HAS_ALPHA ) ? IMAGE_HAS_ALPHA : 0 ); + r_empty.size = r_empty.width * r_empty.height * datasize * 4; r_empty.buffer = (byte *)buffer; - if( FBitSet( flags, TF_ALPHACONTRAST )) - ClearBits( r_empty.flags, IMAGE_HAS_COLOR ); + // clear invalid combinations + ClearBits( flags, TF_TEXTURE_3D ); - if( FBitSet( flags, TF_TEXTURE_1D )) + // if image not luminance and not alphacontrast it will have color + if( !FBitSet( flags, TF_LUMINANCE ) && !FBitSet( flags, TF_ALPHACONTRAST )) + SetBits( r_empty.flags, IMAGE_HAS_COLOR ); + + if( FBitSet( flags, TF_HAS_ALPHA )) + SetBits( r_empty.flags, IMAGE_HAS_ALPHA ); + + if( FBitSet( flags, TF_CUBEMAP )) { - r_empty.height = 1; - r_empty.size = r_empty.width * 4; - } - else if( FBitSet( flags, TF_TEXTURE_3D )) - { - if( !GL_Support( GL_TEXTURE_3D_EXT )) + if( !GL_Support( GL_TEXTURE_CUBEMAP_EXT )) return 0; - - r_empty.depth = r_empty.width; // assume 3D texture as cube - r_empty.size = r_empty.width * r_empty.height * r_empty.depth * 4; - } - else if( FBitSet( flags, TF_CUBEMAP )) - { SetBits( r_empty.flags, IMAGE_CUBEMAP ); - ClearBits( flags, TF_CUBEMAP ); // will be set later r_empty.size *= 6; } - texture = GL_LoadTextureInternal( name, &r_empty, flags, false ); - - return texture; + return GL_LoadTextureInternal( name, &r_empty, flags ); } /* @@ -1722,17 +1702,25 @@ creates texture array from buffer int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ) { rgbdata_t r_empty; - int texture; memset( &r_empty, 0, sizeof( r_empty )); - r_empty.width = width; - r_empty.height = height; - r_empty.depth = depth; + r_empty.width = Q_max( width, 1 ); + r_empty.height = Q_max( height, 1 ); + r_empty.depth = Q_max( depth, 1 ); r_empty.type = PF_RGBA_32; r_empty.size = r_empty.width * r_empty.height * r_empty.depth * 4; - r_empty.flags = IMAGE_HAS_COLOR | (( flags & TF_HAS_ALPHA ) ? IMAGE_HAS_ALPHA : 0 ); r_empty.buffer = (byte *)buffer; + // clear invalid combinations + ClearBits( flags, TF_CUBEMAP|TF_SKYSIDE|TF_HAS_LUMA|TF_MAKELUMA|TF_ALPHACONTRAST ); + + // if image not luminance it will have color + if( !FBitSet( flags, TF_LUMINANCE )) + SetBits( r_empty.flags, IMAGE_HAS_COLOR ); + + if( FBitSet( flags, TF_HAS_ALPHA )) + SetBits( r_empty.flags, IMAGE_HAS_ALPHA ); + if( FBitSet( flags, TF_TEXTURE_3D )) { if( !GL_Support( GL_TEXTURE_3D_EXT )) @@ -1745,9 +1733,55 @@ int GL_CreateTextureArray( const char *name, int width, int height, int depth, c SetBits( r_empty.flags, IMAGE_MULTILAYER ); } - texture = GL_LoadTextureInternal( name, &r_empty, flags, false ); + return GL_LoadTextureInternal( name, &r_empty, flags ); +} - return texture; +/* +================ +GL_FindTexture +================ +*/ +int GL_FindTexture( const char *name ) +{ + gl_texture_t *tex; + + if( !GL_CheckTexName( name )) + return 0; + + // see if already loaded + if(( tex = GL_TextureForName( name ))) + return (tex - gl_textures); + + return 0; +} + +/* +================ +GL_FreeImage + +Frees image by name +================ +*/ +void GL_FreeImage( const char *name ) +{ + int texnum; + + if(( texnum = GL_FindTexture( name )) != 0 ) + GL_FreeTexture( texnum ); +} + +/* +================ +GL_FreeTexture +================ +*/ +void GL_FreeTexture( GLenum texnum ) +{ + // number 0 it's already freed + if( texnum <= 0 || !glw_state.initialized ) + return; + + GL_DeleteTexture( &gl_textures[texnum] ); } /* @@ -1757,13 +1791,13 @@ GL_ProcessTexture */ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) { - gltexture_t *image; + gl_texture_t *image; rgbdata_t *pic; int flags = 0; - if( texnum <= 0 ) return; // missed image - Assert( texnum > 0 && texnum < MAX_TEXTURES ); - image = &r_textures[texnum]; + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + return; // missed image + image = &gl_textures[texnum]; // select mode if( gamma != -1.0f ) @@ -1776,19 +1810,19 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) } else { - MsgDev( D_ERROR, "GL_ProcessTexture: bad operation for %s\n", image->name ); + Con_Printf( S_ERROR "GL_ProcessTexture: bad operation for %s\n", image->name ); return; } if( !image->original ) { - MsgDev( D_ERROR, "GL_ProcessTexture: no input data for %s\n", image->name ); + Con_Printf( S_ERROR "GL_ProcessTexture: no input data for %s\n", image->name ); return; } if( ImageDXT( image->original->type )) { - MsgDev( D_ERROR, "GL_ProcessTexture: can't process compressed texture %s\n", image->name ); + Con_Printf( S_ERROR "GL_ProcessTexture: can't process compressed texture %s\n", image->name ); return; } @@ -1802,129 +1836,6 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) FS_FreeImage( pic ); } -/* -================ -GL_LoadTexture -================ -*/ -int GL_FindTexture( const char *name ) -{ - gltexture_t *tex; - uint hash; - - if( !COM_CheckString( name ) || !glw_state.initialized ) - return 0; - - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "FindTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return 0; - } - - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - return (tex - r_textures); - } - - return 0; -} - -/* -================ -GL_FreeImage - -Frees image by name -================ -*/ -void GL_FreeImage( const char *name ) -{ - gltexture_t *tex; - uint hash; - - if( !COM_CheckString( name ) || !glw_state.initialized ) - return; - - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "FreeTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return; - } - - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - { - R_FreeImage( tex ); - return; - } - } -} - -/* -================ -GL_FreeTexture -================ -*/ -void GL_FreeTexture( GLenum texnum ) -{ - // number 0 it's already freed - if( texnum <= 0 || !glw_state.initialized ) - return; - - Assert( texnum > 0 && texnum < MAX_TEXTURES ); - R_FreeImage( &r_textures[texnum] ); -} - -/* -================ -R_FreeImage -================ -*/ -void R_FreeImage( gltexture_t *image ) -{ - gltexture_t *cur; - gltexture_t **prev; - - Assert( image != NULL ); - - if( !image->name[0] ) - { - if( image->texnum != 0 ) - MsgDev( D_ERROR, "trying to free unnamed texture with texnum %i\n", image->texnum ); - return; - } - - // remove from hash table - prev = &r_texturesHashTable[image->hashValue]; - - while( 1 ) - { - cur = *prev; - if( !cur ) break; - - if( cur == image ) - { - *prev = cur->nextHash; - break; - } - prev = &cur->nextHash; - } - - // release source - if( image->original ) - FS_FreeImage( image->original ); - - pglDeleteTextures( 1, &image->texnum ); - memset( image, 0, sizeof( *image )); -} - /* ============================================================================== @@ -1934,53 +1845,83 @@ INTERNAL TEXTURES */ /* ================== -R_InitDefaultTexture +GL_FakeImage ================== */ -static rgbdata_t *R_InitDefaultTexture( texFlags_t *flags ) +static rgbdata_t *GL_FakeImage( int width, int height, int depth, int flags ) { - int x, y; + static byte data2D[1024]; // 16x16x4 + static rgbdata_t r_image; // also use this for bad textures, but without alpha - r_image.width = r_image.height = 16; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; + r_image.width = Q_max( 1, width ); + r_image.height = Q_max( 1, height ); + r_image.depth = Q_max( 1, depth ); + r_image.flags = flags; r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; + r_image.size = r_image.width * r_image.height * r_image.depth * 4; + r_image.buffer = (r_image.size > sizeof( data2D )) ? NULL : data2D; + r_image.palette = NULL; + r_image.numMips = 1; + r_image.encode = 0; - *flags = 0; + if( FBitSet( r_image.flags, IMAGE_CUBEMAP )) + r_image.size *= 6; + memset( data2D, 0xFF, sizeof( data2D )); - // emo-texture from quake1 - for( y = 0; y < 16; y++ ) - { - for( x = 0; x < 16; x++ ) - { - if(( y < 8 ) ^ ( x < 8 )) - ((uint *)&data2D)[y*16+x] = 0xFFFF00FF; - else ((uint *)&data2D)[y*16+x] = 0xFF000000; - } - } return &r_image; } /* ================== -R_InitParticleTexture +R_InitDlightTexture ================== */ -static rgbdata_t *R_InitParticleTexture( texFlags_t *flags ) +void R_InitDlightTexture( void ) { - int x, y; - int dx2, dy, d; + rgbdata_t r_image; - // particle texture - r_image.width = r_image.height = 16; - r_image.buffer = data2D; - r_image.flags = (IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA); + if( tr.dlightTexture != 0 ) + return; // already initialized + + memset( &r_image, 0, sizeof( r_image )); + r_image.width = BLOCK_SIZE; + r_image.height = BLOCK_SIZE; + r_image.flags = IMAGE_HAS_COLOR; r_image.type = PF_RGBA_32; r_image.size = r_image.width * r_image.height * 4; - *flags = TF_CLAMP; + tr.dlightTexture = GL_LoadTextureInternal( "*dlight", &r_image, TF_NOMIPMAP|TF_CLAMP|TF_ATLAS_PAGE ); +} + +/* +================== +GL_CreateInternalTextures +================== +*/ +static void GL_CreateInternalTextures( void ) +{ + int dx2, dy, d; + int x, y; + rgbdata_t *pic; + + // emo-texture from quake1 + pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR ); + + for( y = 0; y < 16; y++ ) + { + for( x = 0; x < 16; x++ ) + { + if(( y < 8 ) ^ ( x < 8 )) + ((uint *)pic->buffer)[y*16+x] = 0xFFFF00FF; + else ((uint *)pic->buffer)[y*16+x] = 0xFF000000; + } + } + + tr.defaultTexture = GL_LoadTextureInternal( "*default", pic, TF_COLORMAP ); + + // particle texture from quake1 + pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA ); for( x = 0; x < 16; x++ ) { @@ -1991,139 +1932,33 @@ static rgbdata_t *R_InitParticleTexture( texFlags_t *flags ) { dy = y - 8; d = 255 - 35 * sqrt( dx2 + dy * dy ); - data2D[( y*16 + x ) * 4 + 3] = bound( 0, d, 255 ); + pic->buffer[( y * 16 + x ) * 4 + 3] = bound( 0, d, 255 ); } } - return &r_image; -} -/* -================== -R_InitCinematicTexture -================== -*/ -static rgbdata_t *R_InitCinematicTexture( texFlags_t *flags ) -{ - r_image.type = PF_RGBA_32; - r_image.flags = IMAGE_HAS_COLOR; - r_image.width = 640; // same as menu head - r_image.height = 100; - r_image.size = r_image.width * r_image.height * 4; - r_image.buffer = NULL; + tr.particleTexture = GL_LoadTextureInternal( "*particle", pic, TF_CLAMP ); - *flags = TF_NOMIPMAP|TF_CLAMP; + // white texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFFFFFFFF; + tr.whiteTexture = GL_LoadTextureInternal( "*white", pic, TF_COLORMAP ); - return &r_image; -} + // gray texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFF7F7F7F; + tr.grayTexture = GL_LoadTextureInternal( "*gray", pic, TF_COLORMAP ); -/* -================== -R_InitSolidColorTexture -================== -*/ -static rgbdata_t *R_InitSolidColorTexture( texFlags_t *flags, int color ) -{ - // solid color texture - r_image.width = r_image.height = 1; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGB_24; - r_image.size = r_image.width * r_image.height * 3; + // black texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFF000000; + tr.blackTexture = GL_LoadTextureInternal( "*black", pic, TF_COLORMAP ); - *flags = 0; - - data2D[0] = data2D[1] = data2D[2] = color; - return &r_image; -} - -/* -================== -R_InitWhiteTexture -================== -*/ -static rgbdata_t *R_InitWhiteTexture( texFlags_t *flags ) -{ - return R_InitSolidColorTexture( flags, 255 ); -} - -/* -================== -R_InitGrayTexture -================== -*/ -static rgbdata_t *R_InitGrayTexture( texFlags_t *flags ) -{ - return R_InitSolidColorTexture( flags, 127 ); -} - -/* -================== -R_InitBlackTexture -================== -*/ -static rgbdata_t *R_InitBlackTexture( texFlags_t *flags ) -{ - return R_InitSolidColorTexture( flags, 0 ); -} - -/* -================== -R_InitDlightTexture -================== -*/ -void R_InitDlightTexture( void ) -{ - if( tr.dlightTexture != 0 ) - return; // already initialized - - r_image.width = BLOCK_SIZE; - r_image.height = BLOCK_SIZE; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - r_image.buffer = NULL; - - tr.dlightTexture = GL_LoadTextureInternal( "*dlight", &r_image, TF_NOMIPMAP|TF_CLAMP|TF_ATLAS_PAGE, false ); -} - -/* -================== -R_InitBuiltinTextures -================== -*/ -static void R_InitBuiltinTextures( void ) -{ - rgbdata_t *pic; - texFlags_t flags; - - const struct - { - char *name; - int *texnum; - rgbdata_t *(*init)( texFlags_t *flags ); - } - - textures[] = - { - { "*default", &tr.defaultTexture, R_InitDefaultTexture }, - { "*particle", &tr.particleTexture, R_InitParticleTexture }, - { "*white", &tr.whiteTexture, R_InitWhiteTexture }, - { "*gray", &tr.grayTexture, R_InitGrayTexture }, - { "*black", &tr.blackTexture, R_InitBlackTexture }, // not used by engine - { "*cintexture", &tr.cinTexture, R_InitCinematicTexture }, // intermediate buffer to renderer cinematic textures - { NULL, NULL, NULL } - }; - size_t i, num_builtin_textures = ARRAYSIZE( textures ) - 1; - - for( i = 0; i < num_builtin_textures; i++ ) - { - memset( &r_image, 0, sizeof( rgbdata_t )); - memset( data2D, 0xFF, sizeof( data2D )); - - pic = textures[i].init( &flags ); - if( pic == NULL ) continue; - *textures[i].texnum = GL_LoadTextureInternal( textures[i].name, pic, flags, false ); - } + // cinematic dummy + pic = GL_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR ); + tr.cinTexture = GL_LoadTextureInternal( "*cintexture", pic, TF_NOMIPMAP|TF_CLAMP ); } /* @@ -2133,13 +1968,13 @@ R_TextureList_f */ void R_TextureList_f( void ) { - gltexture_t *image; + gl_texture_t *image; int i, texCount, bytes = 0; Con_Printf( "\n" ); Con_Printf( " -id- -w- -h- -size- -fmt- -type- -data- -encode- -wrap- -depth- -name--------\n" ); - for( i = texCount = 0, image = r_textures; i < r_numTextures; i++, image++ ) + for( i = texCount = 0, image = gl_textures; i < gl_numTextures; i++, image++ ) { if( !image->texnum ) continue; @@ -2182,6 +2017,9 @@ void R_TextureList_f( void ) case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: Con_Printf( "DXT5 " ); break; + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: + Con_Printf( "ATI2 " ); + break; case GL_RGBA: Con_Printf( "RGBA " ); break; @@ -2332,32 +2170,20 @@ R_InitImages */ void R_InitImages( void ) { - float f; - uint i; - - memset( r_textures, 0, sizeof( r_textures )); - memset( r_texturesHashTable, 0, sizeof( r_texturesHashTable )); - r_numTextures = 0; + memset( gl_textures, 0, sizeof( gl_textures )); + memset( gl_texturesHashTable, 0, sizeof( gl_texturesHashTable )); + gl_numTextures = 0; // create unused 0-entry - Q_strncpy( r_textures->name, "*unused*", sizeof( r_textures->name )); - r_textures->hashValue = COM_HashKey( r_textures->name, TEXTURES_HASH_SIZE ); - r_textures->nextHash = r_texturesHashTable[r_textures->hashValue]; - r_texturesHashTable[r_textures->hashValue] = r_textures; - r_numTextures = 1; + Q_strncpy( gl_textures->name, "*unused*", sizeof( gl_textures->name )); + gl_textures->hashValue = COM_HashKey( gl_textures->name, TEXTURES_HASH_SIZE ); + gl_textures->nextHash = gl_texturesHashTable[gl_textures->hashValue]; + gl_texturesHashTable[gl_textures->hashValue] = gl_textures; + gl_numTextures = 1; - // build luminance table - for( i = 0; i < 256; i++ ) - { - f = (float)i; - r_luminanceTable[i][0] = f * 0.299f; - r_luminanceTable[i][1] = f * 0.587f; - r_luminanceTable[i][2] = f * 0.114f; - } - - // set texture parameters + // validate cvars R_SetTextureParameters(); - R_InitBuiltinTextures(); + GL_CreateInternalTextures(); R_ParseTexFilters( "scripts/texfilter.txt" ); Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); @@ -2370,19 +2196,17 @@ R_ShutdownImages */ void R_ShutdownImages( void ) { - gltexture_t *image; + gl_texture_t *tex; int i; - if( !glw_state.initialized ) return; - Cmd_RemoveCommand( "texturelist" ); GL_CleanupAllTextureUnits(); - for( i = 0, image = r_textures; i < r_numTextures; i++, image++ ) - R_FreeImage( image ); + for( i = 0, tex = gl_textures; i < gl_numTextures; i++, tex++ ) + GL_DeleteTexture( tex ); memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); - memset( r_texturesHashTable, 0, sizeof( r_texturesHashTable )); - memset( r_textures, 0, sizeof( r_textures )); - r_numTextures = 0; + memset( gl_texturesHashTable, 0, sizeof( gl_texturesHashTable )); + memset( gl_textures, 0, sizeof( gl_textures )); + gl_numTextures = 0; } \ No newline at end of file diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index a92b740a..3ec2c89d 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -93,7 +93,7 @@ typedef struct gltexture_s int servercount; uint hashValue; struct gltexture_s *nextHash; -} gltexture_t; +} gl_texture_t; typedef struct { @@ -306,16 +306,18 @@ void R_DrawModelHull( void ); // gl_image.c // void R_SetTextureParameters( void ); -gltexture_t *R_GetTexture( GLenum texnum ); +gl_texture_t *R_GetTexture( GLenum texnum ); +#define GL_LoadTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, false ) +#define GL_UpdateTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, true ) int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, imgfilter_t *filter ); int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ); -int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); +int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap ); int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ); int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ); void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ); -void GL_ApplyTextureParams( gltexture_t *tex ); -void R_FreeImage( gltexture_t *image ); +void GL_UpdateTexSize( int texnum, int width, int height, int depth ); +void GL_ApplyTextureParams( gl_texture_t *tex ); int GL_FindTexture( const char *name ); void GL_FreeTexture( GLenum texnum ); void GL_FreeImage( const char *name ); @@ -452,6 +454,7 @@ void EmitWaterPolys( msurface_t *warp, qboolean reverse ); void GL_CheckForErrors_( const char *filename, const int fileline ); const char *VID_GetModeString( int vid_mode ); void *GL_GetProcAddress( const char *name ); +const char *GL_ErrorString( int err ); void GL_UpdateSwapInterval( void ); qboolean GL_DeleteContext( void ); qboolean GL_Support( int r_ext ); diff --git a/engine/client/gl_refrag.c b/engine/client/gl_refrag.c index 86e4d835..da73f149 100644 --- a/engine/client/gl_refrag.c +++ b/engine/client/gl_refrag.c @@ -140,6 +140,8 @@ R_AddEfrags */ void R_AddEfrags( cl_entity_t *ent ) { + matrix3x4 transform; + vec3_t outmins, outmaxs; int i; if( !ent->model ) @@ -149,10 +151,14 @@ void R_AddEfrags( cl_entity_t *ent ) lastlink = &ent->efrag; r_pefragtopnode = NULL; + // handle entity rotation for right bbox expanding + Matrix3x4_CreateFromEntity( transform, ent->angles, vec3_origin, 1.0f ); + Matrix3x4_TransformAABB( transform, ent->model->mins, ent->model->maxs, outmins, outmaxs ); + for( i = 0; i < 3; i++ ) { - r_emins[i] = ent->origin[i] + ent->model->mins[i]; - r_emaxs[i] = ent->origin[i] + ent->model->maxs[i]; + r_emins[i] = ent->origin[i] + outmins[i]; + r_emaxs[i] = ent->origin[i] + outmaxs[i]; } R_SplitEntityOnNode( cl.worldmodel->nodes ); @@ -189,6 +195,7 @@ void R_StoreEfrags( efrag_t **ppefrag, int framecount ) if( CL_AddVisibleEntity( pent, ET_FRAGMENTED )) { // mark that we've recorded this entity for this frame + pent->curstate.messagenum = cl.parsecount; pent->visframe = framecount; } } @@ -196,7 +203,6 @@ void R_StoreEfrags( efrag_t **ppefrag, int framecount ) ppefrag = &pefrag->leafnext; break; default: - Host_Error( "R_StoreEfrags: bad entity type %d\n", clmodel->type ); break; } } diff --git a/engine/client/gl_rlight.c b/engine/client/gl_rlight.c index 223abdf9..a60485de 100644 --- a/engine/client/gl_rlight.c +++ b/engine/client/gl_rlight.c @@ -74,7 +74,7 @@ void CL_RunLightStyles( void ) tr.lightstylevalue[i] = ls->map[0] * 22 * scale; continue; } - else if( !ls->interp || !cl_lightstyle_lerping->value ) + else if( !ls->interp || !CVAR_TO_BOOL( cl_lightstyle_lerping )) { tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale; continue; @@ -379,7 +379,7 @@ R_LightVec check bspmodels to get light from ================= */ -colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) +colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) { float last_fraction; int i, maxEnts = 1; @@ -437,6 +437,9 @@ colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t light.g = Q_min(( cv.g >> 7 ), 255 ); light.b = Q_min(( cv.b >> 7 ), 255 ); last_fraction = g_trace_fraction; + + if(( light.r + light.g + light.b ) != 0 ) + break; // we get light now } } } @@ -449,6 +452,27 @@ colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t return light; } +/* +================= +R_LightVec + +check bspmodels to get light from +================= +*/ +colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) +{ + colorVec light = R_LightVecInternal( start, end, lspot, lvec ); + + if( CVAR_TO_BOOL( r_lighting_extended ) && lspot != NULL && lvec != NULL ) + { + // trying to get light from ceiling (but ignore gradient analyze) + if(( light.r + light.g + light.b ) == 0 ) + return R_LightVecInternal( end, start, lspot, lvec ); + } + + return light; +} + /* ================= R_LightPoint @@ -463,4 +487,4 @@ colorVec R_LightPoint( const vec3_t p0 ) VectorSet( p1, p0[0], p0[1], p0[2] - 2048.0f ); return R_LightVec( p0, p1, NULL, NULL ); -} +} \ No newline at end of file diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index fa9b4380..c4b64023 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -579,9 +579,9 @@ using to find source waterleaf with watertexture to grab fog values from it ============= */ -static gltexture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) +static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) { - gltexture_t *tex = NULL; + gl_texture_t *tex = NULL; // assure the initial node is not null // we could check it here, but we would rather check it @@ -654,7 +654,7 @@ from underwater leaf (idea: XaeroX) static void R_CheckFog( void ) { cl_entity_t *ent; - gltexture_t *tex; + gl_texture_t *tex; int i, cnt, count; // quake global fog @@ -673,15 +673,6 @@ static void R_CheckFog( void ) return; } -#ifdef HACKS_RELATED_HLMODS - // special condition for Spirit 1.9 that used direct calls of glFog-functions - if(( !RI.fogEnabled && !RI.fogCustom ) && pglIsEnabled( GL_FOG ) && VectorIsNull( RI.fogColor )) - { - // fill the fog color from GL-state machine - pglGetFloatv( GL_FOG_COLOR, RI.fogColor ); - RI.fogSkybox = true; - } -#endif RI.fogEnabled = false; if( RI.onlyClientDraw || cl.local.waterlevel < 3 || !RI.drawWorld || !RI.viewleaf ) @@ -751,6 +742,26 @@ static void R_CheckFog( void ) } } +/* +============= +R_CheckGLFog + +special condition for Spirit 1.9 +that used direct calls of glFog-functions +============= +*/ +static void R_CheckGLFog( void ) +{ +#ifdef HACKS_RELATED_HLMODS + if(( !RI.fogEnabled && !RI.fogCustom ) && pglIsEnabled( GL_FOG ) && VectorIsNull( RI.fogColor )) + { + // fill the fog color from GL-state machine + pglGetFloatv( GL_FOG_COLOR, RI.fogColor ); + RI.fogSkybox = true; + } +#endif +} + /* ============= R_DrawFog @@ -937,7 +948,8 @@ void R_RenderScene( void ) R_MarkLeaves(); R_DrawFog (); - + + R_CheckGLFog(); R_DrawWorld(); R_CheckFog(); @@ -1085,17 +1097,8 @@ void R_RenderFrame( const ref_viewpass_t *rvp ) if( glConfig.max_multisamples > 1 && FBitSet( gl_msaa->flags, FCVAR_CHANGED )) { if( CVAR_TO_BOOL( gl_msaa )) - { pglEnable( GL_MULTISAMPLE_ARB ); - if( gl_msaa->value > 1.0f ) - pglEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); - else pglDisable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); - } - else - { - pglDisable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); - pglDisable( GL_MULTISAMPLE_ARB ); - } + else pglDisable( GL_MULTISAMPLE_ARB ); ClearBits( gl_msaa->flags, FCVAR_CHANGED ); } @@ -1164,7 +1167,7 @@ void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ) static int GL_RenderGetParm( int parm, int arg ) { - gltexture_t *glt; + gl_texture_t *glt; switch( parm ) { @@ -1265,7 +1268,7 @@ static int GL_RenderGetParm( int parm, int arg ) static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) { - gltexture_t *glt = R_GetTexture( texture ); + gl_texture_t *glt = R_GetTexture( texture ); if( xScale ) *xScale = glt->xscale; if( yScale ) *yScale = glt->yscale; @@ -1273,7 +1276,7 @@ static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScal static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) { - gltexture_t *glt = R_GetTexture( texture ); + gl_texture_t *glt = R_GetTexture( texture ); if( red ) *red = glt->fogParams[0]; if( green ) *green = glt->fogParams[1]; @@ -1291,16 +1294,13 @@ static void R_EnvShot( const float *vieworg, const char *name, int skyshot, int { static vec3_t viewPoint; - if( !name ) - { - MsgDev( D_ERROR, "R_%sShot: bad name\n", skyshot ? "Sky" : "Env" ); + if( !COM_CheckString( name )) return; - } if( cls.scrshot_action != scrshot_inactive ) { if( cls.scrshot_action != scrshot_skyshot && cls.scrshot_action != scrshot_envshot ) - MsgDev( D_ERROR, "R_%sShot: subsystem is busy, try later.\n", skyshot ? "Sky" : "Env" ); + Con_Printf( S_ERROR "R_%sShot: subsystem is busy, try for next frame.\n", skyshot ? "Sky" : "Env" ); return; } @@ -1500,7 +1500,7 @@ static render_api_t gRenderAPI = GL_TextureTarget, GL_SetTexCoordArrayMode, GL_GetProcAddress, - NULL, + GL_UpdateTexSize, NULL, NULL, CL_DrawParticlesExternal, @@ -1541,7 +1541,7 @@ qboolean R_InitRenderAPI( void ) { if( clgame.dllFuncs.pfnGetRenderInterface( CL_RENDER_INTERFACE_VERSION, &gRenderAPI, &clgame.drawFuncs )) { - MsgDev( D_REPORT, "CL_LoadProgs: ^2initailized extended RenderAPI ^7ver. %i\n", CL_RENDER_INTERFACE_VERSION ); + Con_Reportf( "CL_LoadProgs: ^2initailized extended RenderAPI ^7ver. %i\n", CL_RENDER_INTERFACE_VERSION ); return true; } diff --git a/engine/client/gl_rmath.c b/engine/client/gl_rmath.c index d21adfa3..30e591b4 100644 --- a/engine/client/gl_rmath.c +++ b/engine/client/gl_rmath.c @@ -27,12 +27,8 @@ float V_CalcFov( float *fov_x, float width, float height ) { float x, half_fov_y; - if( *fov_x < 1.0f || *fov_x > 170.0f ) - { - if( !cls.demoplayback ) - MsgDev( D_ERROR, "V_CalcFov: bad fov %g!\n", *fov_x ); - *fov_x = 90.0f; - } + if( *fov_x < 1.0f || *fov_x > 179.0f ) + *fov_x = 90.0f; // default value x = width / tan( DEG2RAD( *fov_x ) * 0.5f ); half_fov_y = atan( height / x ); diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index 96ef53c6..ee8cd302 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -19,15 +19,6 @@ GNU General Public License for more details. #include "mod_local.h" #include "shake.h" -typedef struct -{ - const char *texname; - const char *detail; - const char material; - int lMin; - int lMax; -} dmaterial_t; - typedef struct { char texname[64]; // shortname @@ -37,188 +28,6 @@ typedef struct dfilter_t *tex_filters[MAX_TEXTURES]; int num_texfilters; -// default rules for apply detail textures. -// maybe move this to external script? -static const dmaterial_t detail_table[] = -{ -{ "crt", "dt_conc", 'C', 0, 0 }, // concrete -{ "rock", "dt_rock1", 'C', 0, 0 }, -{ "conc", "dt_conc", 'C', 0, 0 }, -{ "brick", "dt_brick", 'C', 0, 0 }, -{ "wall", "dt_brick", 'C', 0, 0 }, -{ "city", "dt_conc", 'C', 0, 0 }, -{ "crete", "dt_conc", 'C', 0, 0 }, -{ "generic", "dt_brick", 'C', 0, 0 }, -{ "floor", "dt_conc", 'C', 0, 0 }, -{ "metal", "dt_metal%i", 'M', 1, 2 }, // metal -{ "mtl", "dt_metal%i", 'M', 1, 2 }, -{ "pipe", "dt_metal%i", 'M', 1, 2 }, -{ "elev", "dt_metal%i", 'M', 1, 2 }, -{ "sign", "dt_metal%i", 'M', 1, 2 }, -{ "barrel", "dt_metal%i", 'M', 1, 2 }, -{ "bath", "dt_ssteel1", 'M', 1, 2 }, -{ "tech", "dt_ssteel1", 'M', 1, 2 }, -{ "refbridge", "dt_metal%i", 'M', 1, 2 }, -{ "panel", "dt_ssteel1", 'M', 0, 0 }, -{ "brass", "dt_ssteel1", 'M', 0, 0 }, -{ "rune", "dt_metal%i", 'M', 1, 2 }, -{ "car", "dt_metal%i", 'M', 1, 2 }, -{ "circuit", "dt_metal%i", 'M', 1, 2 }, -{ "steel", "dt_ssteel1", 'M', 0, 0 }, -{ "dirt", "dt_ground%i", 'D', 1, 5 }, // dirt -{ "drt", "dt_ground%i", 'D', 1, 5 }, -{ "out", "dt_ground%i", 'D', 1, 5 }, -{ "grass", "dt_grass1", 'D', 0, 0 }, -{ "mud", "dt_carpet1", 'D', 0, 0 }, -{ "vent", "dt_ssteel1", 'V', 1, 4 }, // vent -{ "duct", "dt_ssteel1", 'V', 1, 4 }, -{ "tile", "dt_smooth%i", 'T', 1, 2 }, -{ "labflr", "dt_smooth%i", 'T', 1, 2 }, -{ "bath", "dt_smooth%i", 'T', 1, 2 }, -{ "grate", "dt_stone%i", 'G', 1, 4 }, // vent -{ "stone", "dt_stone%i", 'G', 1, 4 }, -{ "grt", "dt_stone%i", 'G', 1, 4 }, -{ "wiz", "dt_wood%i", 'W', 1, 3 }, -{ "wood", "dt_wood%i", 'W', 1, 3 }, -{ "wizwood", "dt_wood%i", 'W', 1, 3 }, -{ "wd", "dt_wood%i", 'W', 1, 3 }, -{ "table", "dt_wood%i", 'W', 1, 3 }, -{ "board", "dt_wood%i", 'W', 1, 3 }, -{ "chair", "dt_wood%i", 'W', 1, 3 }, -{ "brd", "dt_wood%i", 'W', 1, 3 }, -{ "carp", "dt_carpet1", 'W', 1, 3 }, -{ "book", "dt_wood%i", 'W', 1, 3 }, -{ "box", "dt_wood%i", 'W', 1, 3 }, -{ "cab", "dt_wood%i", 'W', 1, 3 }, -{ "couch", "dt_wood%i", 'W', 1, 3 }, -{ "crate", "dt_wood%i", 'W', 1, 3 }, -{ "poster", "dt_plaster%i", 'W', 1, 2 }, -{ "sheet", "dt_plaster%i", 'W', 1, 2 }, -{ "stucco", "dt_plaster%i", 'W', 1, 2 }, -{ "comp", "dt_smooth1", 'P', 0, 0 }, -{ "cmp", "dt_smooth1", 'P', 0, 0 }, -{ "elec", "dt_smooth1", 'P', 0, 0 }, -{ "vend", "dt_smooth1", 'P', 0, 0 }, -{ "monitor", "dt_smooth1", 'P', 0, 0 }, -{ "phone", "dt_smooth1", 'P', 0, 0 }, -{ "glass", "dt_ssteel1", 'Y', 0, 0 }, -{ "window", "dt_ssteel1", 'Y', 0, 0 }, -{ "flesh", "dt_rough1", 'F', 0, 0 }, -{ "meat", "dt_rough1", 'F', 0, 0 }, -{ "fls", "dt_rough1", 'F', 0, 0 }, -{ "ground", "dt_ground%i", 'D', 1, 5 }, -{ "gnd", "dt_ground%i", 'D', 1, 5 }, -{ "snow", "dt_snow%i", 'O', 1, 2 }, // snow -{ "wswamp", "dt_smooth1", 'W', 0, 0 }, -{ NULL, NULL, 0, 0, 0 } -}; - -static const char *R_DetailTextureForName( const char *name ) -{ - const dmaterial_t *table; - - if( !name || !*name ) return NULL; - if( !Q_strnicmp( name, "sky", 3 )) - return NULL; // never details for sky - - // never apply details for liquids - if( !Q_strnicmp( name + 1, "!lava", 5 )) - return NULL; - if( !Q_strnicmp( name + 1, "!slime", 6 )) - return NULL; - if( !Q_strnicmp( name, "!cur_90", 7 )) - return NULL; - if( !Q_strnicmp( name, "!cur_0", 6 )) - return NULL; - if( !Q_strnicmp( name, "!cur_270", 8 )) - return NULL; - if( !Q_strnicmp( name, "!cur_180", 8 )) - return NULL; - if( !Q_strnicmp( name, "!cur_up", 7 )) - return NULL; - if( !Q_strnicmp( name, "!cur_dwn", 8 )) - return NULL; - if( name[0] == '!' ) - return NULL; - - // never apply details to the special textures - if( !Q_strnicmp( name, "origin", 6 )) - return NULL; - if( !Q_strnicmp( name, "clip", 4 )) - return NULL; - if( !Q_strnicmp( name, "hint", 4 )) - return NULL; - if( !Q_strnicmp( name, "skip", 4 )) - return NULL; - if( !Q_strnicmp( name, "translucent", 11 )) - return NULL; - if( !Q_strnicmp( name, "3dsky", 5 )) // xash-mod support :-) - return NULL; - if( !Q_strnicmp( name, "scroll", 6 )) - return NULL; - if( name[0] == '@' ) - return NULL; - - // last check ... - if( !Q_strnicmp( name, "null", 4 )) - return NULL; - - for( table = detail_table; table && table->texname; table++ ) - { - if( Q_stristr( name, table->texname )) - { - if(( table->lMin + table->lMax ) > 0 ) - return va( table->detail, COM_RandomLong( table->lMin, table->lMax )); - return table->detail; - } - } - - return NULL; -} - -void R_CreateDetailTexturesList( const char *filename ) -{ - file_t *detail_txt = NULL; - float xScale, yScale; - const char *detail_name; - texture_t *tex; - rgbdata_t *pic; - int i; - - for( i = 0; i < cl.worldmodel->numtextures; i++ ) - { - tex = cl.worldmodel->textures[i]; - detail_name = R_DetailTextureForName( tex->name ); - if( !detail_name ) continue; - - // detailtexture detected - if( detail_name ) - { - if( !detail_txt ) detail_txt = FS_Open( filename, "w", false ); - if( !detail_txt ) - { - MsgDev( D_ERROR, "Can't write %s\n", filename ); - break; - } - - pic = FS_LoadImage( va( "gfx/detail/%s", detail_name ), NULL, 0 ); - - if( pic ) - { - xScale = (pic->width / (float)tex->width) * gl_detailscale->value; - yScale = (pic->height / (float)tex->height) * gl_detailscale->value; - FS_FreeImage( pic ); - } - else xScale = yScale = 10.0f; - - // store detailtexture description - FS_Printf( detail_txt, "%s detail/%s %.2f %.2f\n", tex->name, detail_name, xScale, yScale ); - } - } - - if( detail_txt ) FS_Close( detail_txt ); -} - void R_ParseDetailTextures( const char *filename ) { char *afile, *pfile; @@ -229,12 +38,6 @@ void R_ParseDetailTextures( const char *filename ) texture_t *tex; int i; - if( r_detailtextures->value >= 2 && !FS_FileExists( filename, false )) - { - // use built-in generator for detail textures - R_CreateDetailTexturesList( filename ); - } - afile = FS_LoadFile( filename, NULL, false ); if( !afile ) return; @@ -297,7 +100,7 @@ void R_ParseDetailTextures( const char *filename ) // texture is loaded if( tex->dt_texturenum ) { - gltexture_t *glt; + gl_texture_t *glt; glt = R_GetTexture( tex->gl_texturenum ); glt->xscale = xScale; @@ -363,7 +166,7 @@ void R_ParseTexFilters( const char *filename ) filter.blendFunc = GL_BLEND; else if( !Q_stricmp( token, "add_signed" ) || !Q_stricmp( token, "GL_ADD_SIGNED" )) filter.blendFunc = GL_ADD_SIGNED; - else MsgDev( D_WARN, "unknown blendFunc '%s' specified for texture '%s'\n", texname, token ); + else filter.blendFunc = GL_REPLACE; // defaulting to replace // reading flags pfile = COM_ParseFile( pfile, token ); @@ -371,10 +174,7 @@ void R_ParseTexFilters( const char *filename ) // make sure what factor is not zeroed if( filter.factor == 0.0f ) - { - MsgDev( D_WARN, "texfilter for texture %s has factor 0! Ignored\n", texname ); continue; - } // check if already existed for( i = 0; i < num_texfilters; i++ ) @@ -382,10 +182,7 @@ void R_ParseTexFilters( const char *filename ) tf = tex_filters[i]; if( !Q_stricmp( tf->texname, texname )) - { - MsgDev( D_WARN, "texture %s has specified multiple filters! Ignored\n", texname ); break; - } } if( i != num_texfilters ) @@ -399,7 +196,7 @@ void R_ParseTexFilters( const char *filename ) tf->filter = filter; } - MsgDev( D_INFO, "%i texture filters parsed\n", num_texfilters ); + Con_Reportf( "%i texture filters parsed\n", num_texfilters ); Mem_Free( afile ); } @@ -451,7 +248,7 @@ void R_NewMap( void ) R_ClearDecals(); // clear all level decals // upload detailtextures - if( r_detailtextures->value ) + if( CVAR_TO_BOOL( r_detailtextures )) { string mapname, filepath; @@ -462,7 +259,7 @@ void R_NewMap( void ) R_ParseDetailTextures( filepath ); } - if( v_dark->value ) + if( CVAR_TO_BOOL( v_dark )) { screenfade_t *sf = &clgame.fade; float fadetime = 5.0f; @@ -505,7 +302,7 @@ void R_NewMap( void ) tx = cl.worldmodel->textures[i]; - if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == 256 && tx->height == 128 ) + if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 )) tr.skytexturenum = i; tx->texturechain = NULL; diff --git a/engine/client/gl_rpart.c b/engine/client/gl_rpart.c index cb46866d..a00e9322 100644 --- a/engine/client/gl_rpart.c +++ b/engine/client/gl_rpart.c @@ -225,7 +225,7 @@ particle_t *R_AllocParticle( void (*callback)( particle_t*, float )) if( cl_lasttimewarn < host.realtime ) { // don't spam about overflow - MsgDev( D_ERROR, "Overflow %d particles\n", GI->max_particles ); + Con_DPrintf( S_ERROR "Overflow %d particles\n", GI->max_particles ); cl_lasttimewarn = host.realtime + 1.0f; } return NULL; @@ -276,7 +276,7 @@ particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life ) if( cl_lasttimewarn < host.realtime ) { // don't spam about overflow - MsgDev( D_ERROR, "Overflow %d tracers\n", GI->max_particles ); + Con_DPrintf( S_ERROR "Overflow %d tracers\n", GI->max_particles ); cl_lasttimewarn = host.realtime + 1.0f; } return NULL; @@ -1501,14 +1501,11 @@ void R_UserTracerParticle( float *org, float *vel, float life, int colorIndex, f particle_t *p; if( colorIndex < 0 ) - { - MsgDev( D_ERROR, "UserTracer with color < 0\n" ); return; - } if( colorIndex > ARRAYSIZE( gTracerColors )) { - MsgDev( D_ERROR, "UserTracer with color > %d\n", ARRAYSIZE( gTracerColors )); + Con_Printf( S_ERROR "UserTracer with color > %d\n", ARRAYSIZE( gTracerColors )); return; } diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index 9feef4cc..7b69ae21 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -273,9 +273,8 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ) medge_t *pedges, *r_pedge; mextrasurf_t *info = fa->info; float sample_size; - int vertpage; texture_t *tex; - gltexture_t *glt; + gl_texture_t *glt; float *vec; float s, t; glpoly_t *poly; @@ -299,7 +298,6 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ) // reconstruct the polygon pedges = mod->edges; lnumverts = fa->numedges; - vertpage = 0; // detach if already created, reconstruct again poly = fa->polys; @@ -341,13 +339,13 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ) s = DotProduct( vec, info->lmvecs[0] ) + info->lmvecs[0][3]; s -= info->lightmapmins[0]; s += fa->light_s * sample_size; - s += sample_size / 2.0; + s += sample_size * 0.5f; s /= BLOCK_SIZE * sample_size; //fa->texinfo->texture->width; t = DotProduct( vec, info->lmvecs[1] ) + info->lmvecs[1][3]; t -= info->lightmapmins[1]; t += fa->light_t * sample_size; - t += sample_size / 2.0; + t += sample_size * 0.5f; t /= BLOCK_SIZE * sample_size; //fa->texinfo->texture->height; poly->verts[i][5] = s; @@ -355,7 +353,7 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ) } // remove co-linear points - Ed - if( !gl_keeptjunctions->value && !( fa->flags & SURF_UNDERWATER )) + if( !CVAR_TO_BOOL( gl_keeptjunctions ) && !FBitSet( fa->flags, SURF_UNDERWATER )) { for( i = 0; i < lnumverts; i++ ) { @@ -439,17 +437,8 @@ texture_t *R_TextureAnimation( msurface_t *s ) { base = base->anim_next; - if( !base ) - { - MsgDev( D_ERROR, "R_TextureAnimation: broken loop\n" ); + if( !base || ++count > MOD_FRAMES ) return s->texinfo->texture; - } - - if( ++count > MOD_FRAMES ) - { - MsgDev( D_ERROR, "R_TextureAnimation: infinite loop\n" ); - return s->texinfo->texture; - } } return base; @@ -645,7 +634,7 @@ static void LM_UploadBlock( qboolean dynamic ) r_lightmap.size = r_lightmap.width * r_lightmap.height * 4; r_lightmap.flags = IMAGE_HAS_COLOR; r_lightmap.buffer = gl_lms.lightmap_buffer; - tr.lightmapTextures[i] = GL_LoadTextureInternal( lmName, &r_lightmap, TF_FONT|TF_ATLAS_PAGE, false ); + tr.lightmapTextures[i] = GL_LoadTextureInternal( lmName, &r_lightmap, TF_FONT|TF_ATLAS_PAGE ); if( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS ) Host_Error( "AllocBlock: full\n" ); @@ -703,9 +692,9 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride, qboolean { for( s = 0; s < smax; s++ ) { - dest[0] = min((bl[0] >> 7), 255 ); - dest[1] = min((bl[1] >> 7), 255 ); - dest[2] = min((bl[2] >> 7), 255 ); + dest[0] = Q_min((bl[0] >> 7), 255 ); + dest[1] = Q_min((bl[1] >> 7), 255 ); + dest[2] = Q_min((bl[2] >> 7), 255 ); dest[3] = 255; bl += 3; @@ -734,7 +723,7 @@ void DrawGLPoly( glpoly_t *p, float xScale, float yScale ) if( p->flags & SURF_CONVEYOR ) { - gltexture_t *texture; + gl_texture_t *texture; float flConveyorSpeed; float flRate, flAngle; @@ -824,7 +813,7 @@ void R_BlendLightmaps( void ) msurface_t *surf, *newsurf = NULL; int i; - if( r_fullbright->value || !cl.worldmodel->lightdata ) + if( CVAR_TO_BOOL( r_fullbright ) || !cl.worldmodel->lightdata ) return; if( RI.currententity ) @@ -845,7 +834,7 @@ void R_BlendLightmaps( void ) GL_SetupFogColorForSurfaces (); - if( !r_lightmap->value ) + if( !CVAR_TO_BOOL( r_lightmap )) pglEnable( GL_BLEND ); else pglDisable( GL_BLEND ); @@ -872,7 +861,7 @@ void R_BlendLightmaps( void ) } // render dynamic lightmaps - if( r_dynamic->value ) + if( CVAR_TO_BOOL( r_dynamic )) { LM_InitBlock(); @@ -1005,7 +994,7 @@ R_RenderDetails */ void R_RenderDetails( void ) { - gltexture_t *glt; + gl_texture_t *glt; mextrasurf_t *es, *p; msurface_t *fa; int i; @@ -1082,7 +1071,7 @@ void R_RenderBrushPoly( msurface_t *fa, int cull_type ) draw_fullbrights = true; } - if( r_detailtextures->value ) + if( CVAR_TO_BOOL( r_detailtextures )) { if( pglIsEnabled( GL_FOG )) { @@ -1125,7 +1114,7 @@ void R_RenderBrushPoly( msurface_t *fa, int cull_type ) DrawSurfaceDecals( fa, true, (cull_type == CULL_BACKSIDE)); } - if( fa->flags & SURF_DRAWTILED ) + if( FBitSet( fa->flags, SURF_DRAWTILED )) return; // no lightmaps anyway // check for lightmap modification @@ -1543,7 +1532,7 @@ void R_DrawBrushModel( cl_entity_t *e ) } // sort faces if needs - if( !FBitSet( clmodel->flags, MODEL_LIQUID ) && e->curstate.rendermode == kRenderTransTexture && !gl_nosort->value ) + if( !FBitSet( clmodel->flags, MODEL_LIQUID ) && e->curstate.rendermode == kRenderTransTexture && !CVAR_TO_BOOL( gl_nosort )) qsort( world.draw_surfaces, num_sorted, sizeof( sortedface_t ), R_SurfaceCompare ); // draw sorted translucent surfaces @@ -2180,9 +2169,6 @@ void GL_BuildLightmaps( void ) // now gamma and brightness are valid ClearBits( vid_brightness->flags, FCVAR_CHANGED ); ClearBits( vid_gamma->flags, FCVAR_CHANGED ); - - if( !gl_keeptjunctions->value ) - MsgDev( D_INFO, "Eliminate %i vertexes\n", nColinElim ); } void GL_InitRandomTable( void ) diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index 5532400e..23b05534 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -400,7 +400,7 @@ void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean pspriteframe->left = -( w >> 1 ); pspriteframe->down = ( h >> 1 ) - h; pspriteframe->right = w + -( w >> 1 ); - pspriteframe->gl_texturenum = GL_LoadTextureInternal( texname, &temp, TF_IMAGE, false ); + pspriteframe->gl_texturenum = GL_LoadTextureInternal( texname, &temp, TF_IMAGE ); xl += w; if( xl >= pix->width ) @@ -493,7 +493,7 @@ mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ) else if( frame >= psprite->numframes ) { if( frame > psprite->numframes ) - MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name ); + Con_Reportf( S_WARN "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name ); frame = psprite->numframes - 1; } @@ -561,7 +561,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, } else if( frame >= psprite->numframes ) { - MsgDev( D_WARN, "R_GetSpriteFrameInterpolant: no such frame %d (%s)\n", frame, ent->model->name ); + Con_Reportf( S_WARN "R_GetSpriteFrameInterpolant: no such frame %d (%s)\n", frame, ent->model->name ); frame = psprite->numframes - 1; } diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 58216213..38e4ee70 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -560,7 +560,7 @@ void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t an // Con_Printf( "%4.2f %.2f %.2f\n", f, e->curstate.animtime, g_studio.time ); VectorLerp( e->latched.prevorigin, f, e->curstate.origin, origin ); - if( !VectorCompare( e->curstate.angles, e->latched.prevangles )) + if( !VectorCompareEpsilon( e->curstate.angles, e->latched.prevangles, ON_EPSILON )) { vec4_t q, q1, q2; @@ -2417,6 +2417,7 @@ static void R_StudioDrawPoints( void ) pglBlendFunc( GL_ONE, GL_ONE ); pglDepthMask( GL_FALSE ); pglEnable( GL_BLEND ); + R_AllowFog( false ); } else pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); } @@ -2438,6 +2439,7 @@ static void R_StudioDrawPoints( void ) { pglDepthMask( GL_TRUE ); pglDisable( GL_BLEND ); + R_AllowFog( true ); } r_stats.c_studio_polys += pmesh->numtris; @@ -2718,11 +2720,11 @@ check for texture flags */ int R_GetEntityRenderMode( cl_entity_t *ent ) { - studiohdr_t *phdr; + int i, opaque, trans; mstudiotexture_t *ptexture; cl_entity_t *oldent; model_t *model; - int i; + studiohdr_t *phdr; oldent = RI.currententity; RI.currententity = ent; @@ -2735,21 +2737,27 @@ int R_GetEntityRenderMode( cl_entity_t *ent ) if(( phdr = Mod_StudioExtradata( model )) == NULL ) { - // forcing to choose right sorting type - if(( model && model->type == mod_brush ) && FBitSet( model->flags, MODEL_TRANSPARENT )) - return kRenderTransAlpha; + if( R_ModelOpaque( ent->curstate.rendermode )) + { + // forcing to choose right sorting type + if(( model && model->type == mod_brush ) && FBitSet( model->flags, MODEL_TRANSPARENT )) + return kRenderTransAlpha; + } return ent->curstate.rendermode; } ptexture = (mstudiotexture_t *)((byte *)phdr + phdr->textureindex); - for( i = 0; i < phdr->numtextures; i++, ptexture++ ) + for( opaque = trans = i = 0; i < phdr->numtextures; i++, ptexture++ ) { - // g-cont. this is not fully proper but better than was - if( FBitSet( ptexture->flags, STUDIO_NF_ADDITIVE )) - return kRenderTransAdd; -// if( FBitSet( ptexture->flags, STUDIO_NF_MASKED )) -// return kRenderTransAlpha; + // ignore chrome & additive it's just a specular-like effect + if( FBitSet( ptexture->flags, STUDIO_NF_ADDITIVE ) && !FBitSet( ptexture->flags, STUDIO_NF_CHROME )) + trans++; + else opaque++; } + + // if model is more additive than opaque + if( trans > opaque ) + return kRenderTransAdd; return ent->curstate.rendermode; } @@ -3698,10 +3706,6 @@ void R_DrawViewModel( void ) pglFrontFace( GL_CW ); } - // FIXME: viewmodel is invisible when alpha to coverage is enabled - if( glConfig.max_multisamples > 1 && gl_msaa->value > 1.0f ) - pglDisable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); - switch( RI.currententity->model->type ) { case mod_alias: @@ -3713,9 +3717,6 @@ void R_DrawViewModel( void ) break; } - if( glConfig.max_multisamples > 1 && gl_msaa->value > 1.0f ) - pglEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); - // restore depth range pglDepthRange( gldepthmin, gldepthmax ); diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index 55e7693c..42212239 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -26,8 +26,7 @@ GNU General Public License for more details. #define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE) #define WINDOW_EX_STYLE (0) #define WINDOW_NAME "Xash3D Window" // Half-Life -#define FCONTEXT_CORE_PROFILE BIT( 0 ) -#define FCONTEXT_DEBUG_ARB BIT( 1 ) +#define FCONTEXT_DEBUG_ARB BIT( 0 ) convar_t *gl_extensions; convar_t *gl_texture_anisotropy; @@ -535,9 +534,6 @@ static void GL_SetDefaultState( void ) if( Sys_CheckParm( "-gldebug" )) SetBits( context_flags, FCONTEXT_DEBUG_ARB ); - if( Sys_CheckParm( "-glcore" )) - SetBits( context_flags, FCONTEXT_CORE_PROFILE ); - // init draw stack tr.draw_list = &tr.draw_stack[0]; tr.draw_stack_pos = 0; @@ -593,9 +589,7 @@ qboolean GL_CreateContext( void ) pwglCreateContextAttribsARB = GL_GetProcAddress( "wglCreateContextAttribsARB" ); - if( FBitSet( context_flags, FCONTEXT_CORE_PROFILE )) - profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - else profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; if( FBitSet( context_flags, FCONTEXT_DEBUG_ARB )) arb_flags = WGL_CONTEXT_DEBUG_BIT_ARB; @@ -1021,6 +1015,8 @@ void R_SaveVideoMode( int vid_mode ) glState.width = vidmode[mode].width; glState.height = vidmode[mode].height; glState.wideScreen = vidmode[mode].wideScreen; + Cvar_FullSet( "width", va( "%i", glState.width ), FCVAR_READ_ONLY ); + Cvar_FullSet( "height", va( "%i", glState.height ), FCVAR_READ_ONLY ); Cvar_SetValue( "vid_mode", mode ); // merge if it out of bounds MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[mode].desc, vidmode[mode].width, vidmode[mode].height ); @@ -1585,7 +1581,7 @@ void GL_InitCommands( void ) r_speeds = Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" ); r_fullbright = Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); - r_lighting_extended = Cvar_Get( "r_lighting_extended", "1", FCVAR_ARCHIVE, "allow to get lighting from world and bmodels" ); + r_lighting_extended = Cvar_Get( "r_lighting_extended", "1", FCVAR_ARCHIVE, "allow to get lighting from bmodels too" ); r_lighting_modulate = Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" ); r_lighting_ambient = Cvar_Get( "r_lighting_ambient", "0.3", FCVAR_ARCHIVE, "map ambient lighting scale" ); r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); @@ -1619,7 +1615,7 @@ void GL_InitCommands( void ) gl_test = Cvar_Get( "gl_test", "0", 0, "engine developer cvar for quick testing new features" ); gl_wireframe = Cvar_Get( "gl_wireframe", "0", FCVAR_ARCHIVE|FCVAR_SPONLY, "show wireframe overlay" ); gl_round_down = Cvar_Get( "gl_round_down", "2", FCVAR_RENDERINFO, "round texture sizes to nearest POT value" ); - gl_msaa = Cvar_Get( "gl_msaa", "2", FCVAR_ARCHIVE, "enable multi sample anti-aliasing" ); + gl_msaa = Cvar_Get( "gl_msaa", "1", FCVAR_ARCHIVE, "enable multi sample anti-aliasing" ); // these cvar not used by engine but some mods requires this gl_polyoffset = Cvar_Get( "gl_polyoffset", "2.0", FCVAR_ARCHIVE, "polygon offset for decals" ); @@ -1906,6 +1902,35 @@ void R_Shutdown( void ) R_Free_OpenGL(); } + +/* +================= +GL_ErrorString + +convert errorcode to string +================= +*/ +const char *GL_ErrorString( int err ) +{ + switch( err ) + { + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + default: + return "UNKNOWN ERROR"; + } +} + /* ================= GL_CheckForErrors @@ -1916,38 +1941,12 @@ obsolete void GL_CheckForErrors_( const char *filename, const int fileline ) { int err; - char *str; - if( !gl_check_errors->value ) + if( !CVAR_TO_BOOL( gl_check_errors )) return; if(( err = pglGetError( )) == GL_NO_ERROR ) return; - switch( err ) - { - case GL_STACK_OVERFLOW: - str = "GL_STACK_OVERFLOW"; - break; - case GL_STACK_UNDERFLOW: - str = "GL_STACK_UNDERFLOW"; - break; - case GL_INVALID_ENUM: - str = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - str = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - str = "GL_INVALID_OPERATION"; - break; - case GL_OUT_OF_MEMORY: - str = "GL_OUT_OF_MEMORY"; - break; - default: - str = "UNKNOWN ERROR"; - break; - } - - Con_Printf( S_OPENGL_ERROR "%s (called at %s:%i)\n", str, filename, fileline ); + Con_Printf( S_OPENGL_ERROR "%s (called at %s:%i)\n", GL_ErrorString( err ), filename, fileline ); } \ No newline at end of file diff --git a/engine/client/gl_warp.c b/engine/client/gl_warp.c index 15a6ed77..bb91e4a5 100644 --- a/engine/client/gl_warp.c +++ b/engine/client/gl_warp.c @@ -21,7 +21,7 @@ GNU General Public License for more details. #define SKYCLOUDS_QUALITY 12 #define MAX_CLIP_VERTS 128 // skybox clip vertices #define TURBSCALE ( 256.0f / ( M_PI2 )) -static const char* r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; +const char* r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; static const int r_skyTexOrder[6] = { 0, 2, 1, 3, 4, 5 }; static const vec3_t skyclip[6] = @@ -672,7 +672,7 @@ void R_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette ) // make sure what sky image is valid if( !r_sky || !r_sky->palette || r_sky->type != PF_INDEXED_32 || r_sky->height == 0 ) { - MsgDev( D_ERROR, "R_InitSky: unable to load sky texture %s\n", tx->name ); + Con_Reportf( S_ERROR "R_InitSky: unable to load sky texture %s\n", tx->name ); if( r_sky ) FS_FreeImage( r_sky ); return; } @@ -711,7 +711,7 @@ void R_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette ) r_temp.palette = NULL; // load it in - tr.solidskyTexture = GL_LoadTextureInternal( "solid_sky", &r_temp, TF_NOMIPMAP, false ); + tr.solidskyTexture = GL_LoadTextureInternal( "solid_sky", &r_temp, TF_NOMIPMAP ); for( i = 0; i < r_sky->width >> 1; i++ ) { @@ -734,7 +734,7 @@ void R_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette ) r_temp.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; // load it in - tr.alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", &r_temp, TF_NOMIPMAP, false ); + tr.alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", &r_temp, TF_NOMIPMAP ); // clean up FS_FreeImage( r_sky ); diff --git a/engine/client/s_dsp.c b/engine/client/s_dsp.c index b6144719..07ca7aee 100644 --- a/engine/client/s_dsp.c +++ b/engine/client/s_dsp.c @@ -33,7 +33,7 @@ GNU General Public License for more details. #define MAXDLY (STEREODLY + 1) #define MAXLP 10 -#define MAXPRESETS ARRAYSIZE( rgsxpre ) +#define MAXPRESETS 29 typedef struct sx_preset_s { @@ -79,7 +79,7 @@ typedef struct dly_s int *lpdelayline; } dly_t; -const sx_preset_t rgsxpre[] = +const sx_preset_t rgsxpre[MAXPRESETS] = { // -------reverb-------- -------delay-------- // lp mod size refl rvblp delay feedback dlylp left @@ -193,7 +193,7 @@ void SX_Init( void ) sxmod1cur = sxmod1 = 350 * ( idsp_dma_speed / SOUND_11k ); sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k ); - dsp_off = Cvar_Get( "dsp_off", "0", 0, "disable DSP processing" ); + dsp_off = Cvar_Get( "dsp_off", "0", FCVAR_ARCHIVE, "disable DSP processing" ); roomwater_type = Cvar_Get( "waterroom_type", "14", 0, "water room type" ); room_type = Cvar_Get( "room_type", "0", 0, "current room type preset" ); @@ -609,16 +609,15 @@ int RVB_DoReverbForOneDly( dly_t *dly, const int vlr, const portable_samplepair_ if( dly->xfade || delay || samplepair->left || samplepair->right ) { // modulate delay rate - if( !dly->mod ) + if( !dly->xfade && !dly->modcur && dly->mod ) { dly->idelayoutputxf = dly->idelayoutput + ((COM_RandomLong( 0, 255 ) * delay) >> 9 ); - if( dly->idelayoutputxf >= dly->cdelaysamplesmax ) - dly->idelayoutputxf -= dly->cdelaysamplesmax; - - dly->xfade = REVERB_XFADE; + //dly->xfade = 32; } + dly->idelayoutputxf %= dly->cdelaysamplesmax; + if( dly->xfade ) { samplexf = (dly->lpdelayline[dly->idelayoutputxf] * (REVERB_XFADE - dly->xfade)) / REVERB_XFADE; @@ -819,6 +818,9 @@ void CheckNewDspPresets( void ) idsp_room = roomwater_type->value; else idsp_room = room_type->value; + // don't pass invalid presets + idsp_room = bound( 0, idsp_room, MAXPRESETS - 1 ); + if( FBitSet( hisound->flags, FCVAR_CHANGED )) { sxhires = hisound->value; diff --git a/engine/client/s_load.c b/engine/client/s_load.c index 409909c8..92f52056 100644 --- a/engine/client/s_load.c +++ b/engine/client/s_load.c @@ -44,7 +44,7 @@ void S_SoundList_f( void ) for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ ) { - if( !sfx->servercount ) + if( !sfx->name[0] ) continue; sc = sfx->cache; @@ -54,7 +54,9 @@ void S_SoundList_f( void ) if( sc->loopStart >= 0 ) Con_Printf( "L" ); else Con_Printf( " " ); - Con_Printf( " (%2db) %s : sound/%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name ); + if( sfx->name[0] == '*' ) + Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name ); + else Con_Printf( " (%2db) %s : %s%s\n", sc->width * 8, Q_memprint( sc->size ), DEFAULT_SOUNDPATH, sfx->name ); totalSfx++; } } @@ -127,16 +129,21 @@ wavdata_t *S_LoadSound( sfx_t *sfx ) wavdata_t *sc = NULL; if( !sfx ) return NULL; - if( sfx->cache ) return sfx->cache; // see if still in memory - if( Q_stricmp( sfx->name, "*default" )) + // see if still in memory + if( sfx->cache ) + return sfx->cache; + + if( !COM_CheckString( sfx->name )) { - // load it from disk - if( sfx->name[0] == '*' ) - sc = FS_LoadSound( sfx->name + 1, NULL, 0 ); - else sc = FS_LoadSound( sfx->name, NULL, 0 ); + // debug + Con_Printf( "S_LoadSound: sfx %d has NULL name\n", sfx - s_knownSfx ); + return NULL; } + // load it from disk + if( Q_stricmp( sfx->name, "*default" )) + sc = FS_LoadSound( sfx->name, NULL, 0 ); if( !sc ) sc = S_CreateDefaultSound(); if( sc->rate < SOUND_11k ) // some bad sounds @@ -169,11 +176,8 @@ sfx_t *S_FindName( const char *pname, int *pfInCache ) if( !COM_CheckString( pname ) || !dma.initialized ) return NULL; - if( Q_strlen( pname ) >= MAX_STRING ) - { - MsgDev( D_ERROR, "S_FindSound: sound name too long: %s", pname ); + if( Q_strlen( pname ) >= sizeof( sfx->name )) return NULL; - } Q_strncpy( name, pname, sizeof( name )); COM_FixSlashes( name ); @@ -202,10 +206,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache ) if( i == s_numSfx ) { if( s_numSfx == MAX_SFX ) - { - MsgDev( D_ERROR, "S_FindName: MAX_SFX limit exceeded\n" ); return NULL; - } s_numSfx++; } @@ -233,7 +234,8 @@ void S_FreeSound( sfx_t *sfx ) sfx_t *hashSfx; sfx_t **prev; - if( !sfx || !sfx->name[0] ) return; + if( !sfx || !sfx->name[0] ) + return; // de-link it from the hash tree prev = &s_sfxHashList[sfx->hashValue]; @@ -251,7 +253,8 @@ void S_FreeSound( sfx_t *sfx ) prev = &hashSfx->hashNext; } - if( sfx->cache ) FS_FreeSound( sfx->cache ); + if( sfx->cache ) + FS_FreeSound( sfx->cache ); memset( sfx, 0, sizeof( *sfx )); } @@ -266,11 +269,6 @@ void S_BeginRegistration( void ) int i; s_registration_sequence++; - s_registering = true; - - // create unused 0-entry - S_RegisterSound( "*default" ); - snd_ambient = false; // check for automatic ambient sounds @@ -279,11 +277,11 @@ void S_BeginRegistration( void ) if( !GI->ambientsound[i][0] ) continue; // empty slot - if( !ambient_sfx[i] ) - MsgDev( D_NOTE, "Loading ambient[%i]: ^2%s^7\n", i, GI->ambientsound[i] ); ambient_sfx[i] = S_RegisterSound( GI->ambientsound[i] ); if( ambient_sfx[i] ) snd_ambient = true; // allow auto-ambients } + + s_registering = true; } /* @@ -303,7 +301,9 @@ void S_EndRegistration( void ) // free any sounds not from this registration sequence for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ ) { - if( !sfx->name[0] ) continue; + if( !sfx->name[0] || sfx->name[0] == '*' ) + continue; // don't release default sound + if( sfx->servercount != s_registration_sequence ) S_FreeSound( sfx ); // don't need this sound } @@ -311,7 +311,8 @@ void S_EndRegistration( void ) // load everything in for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ ) { - if( !sfx->name[0] ) continue; + if( !sfx->name[0] ) + continue; S_LoadSound( sfx ); } s_registering = false; @@ -351,23 +352,35 @@ sound_t S_RegisterSound( const char *name ) sfx_t *S_GetSfxByHandle( sound_t handle ) { - if( handle == -1 || !dma.initialized ) + if( !dma.initialized ) return NULL; + // create new sfx if( handle == SENTENCE_INDEX ) - { - // create new sfx return S_FindName( s_sentenceImmediateName, NULL ); - } if( handle < 0 || handle >= s_numSfx ) - { - MsgDev( D_ERROR, "S_GetSfxByHandle: handle %i out of range (%i)\n", handle, s_numSfx ); return NULL; - } + return &s_knownSfx[handle]; } +/* +================= +S_InitSounds +================= +*/ +void S_InitSounds( void ) +{ + // create unused 0-entry + Q_strncpy( s_knownSfx->name, "*default", MAX_QPATH ); + s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH ); + s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue]; + s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx; + s_knownSfx->cache = S_CreateDefaultSound(); + s_numSfx = 1; +} + /* ================= S_FreeSounds diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 49dc6bfd..78fd04a2 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -273,6 +273,28 @@ void SND_ChannelTraceReset( void ) channels[i].bTraced = false; } +/* +================= +SND_FStreamIsPlaying + +Select a channel from the dynamic channel allocation area. For the given entity, +override any other sound playing on the same channel (see code comments below for +exceptions). +================= +*/ +qboolean SND_FStreamIsPlaying( sfx_t *sfx ) +{ + int ch_idx; + + for( ch_idx = NUM_AMBIENTS; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++ ) + { + if( channels[ch_idx].sfx == sfx ) + return true; + } + + return false; +} + /* ================= SND_PickDynamicChannel @@ -294,6 +316,13 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean life_left = 0x7fffffff; if( ignore ) *ignore = false; + if( channel == CHAN_STREAM && SND_FStreamIsPlaying( sfx )) + { + if( ignore ) + *ignore = true; + return NULL; + } + for( ch_idx = NUM_AMBIENTS; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++ ) { channel_t *ch = &channels[ch_idx]; @@ -390,7 +419,7 @@ channel_t *SND_PickStaticChannel( const vec3_t pos, sfx_t *sfx ) // no empty slots, alloc a new static sound channel if( total_channels == MAX_CHANNELS ) { - MsgDev( D_ERROR, "S_PickStaticChannel: no free channels\n" ); + Con_DPrintf( S_ERROR "S_PickStaticChannel: no free channels\n" ); return NULL; } @@ -891,14 +920,11 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv // and we didn't find it (it's not playing), go ahead and start it up } - if( pitch == 0 ) - { - MsgDev( D_WARN, "S_StartSound: ( %s ) ignored, called with pitch 0\n", sfx->name ); - return; - } - if( !pos ) pos = RI.vieworg; + if( chan == CHAN_STREAM ) + SetBits( flags, SND_STOP_LOOPING ); + // pick a channel to play on if( chan == CHAN_STATIC ) target_chan = SND_PickStaticChannel( pos, sfx ); else target_chan = SND_PickDynamicChannel( ent, chan, sfx, &bIgnore ); @@ -1019,12 +1045,6 @@ void S_RestoreSound( const vec3_t pos, int ent, int chan, sound_t handle, float vol = bound( 0, fvol * 255, 255 ); if( pitch <= 1 ) pitch = PITCH_NORM; // Invasion issues - if( pitch == 0 ) - { - MsgDev( D_WARN, "S_RestoreSound: ( %s ) ignored, called with pitch 0\n", sfx->name ); - return; - } - // pick a channel to play on if( chan == CHAN_STATIC ) target_chan = SND_PickStaticChannel( pos, sfx ); else target_chan = SND_PickDynamicChannel( ent, chan, sfx, &bIgnore ); @@ -1152,12 +1172,6 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa return; if( flags & SND_STOP ) return; } - - if( pitch == 0 ) - { - MsgDev( D_WARN, "S_AmbientSound: ( %s ) ignored, called with pitch 0\n", sfx->name ); - return; - } // pick a channel to play on from the static area ch = SND_PickStaticChannel( pos, sfx ); @@ -1375,7 +1389,13 @@ void S_UpdateAmbientSounds( void ) chan = &channels[ambient_channel]; chan->sfx = S_GetSfxByHandle( ambient_sfx[ambient_channel] ); - if( !chan->sfx ) continue; + // ambient is unused + if( !chan->sfx ) + { + chan->rightvol = 0; + chan->leftvol = 0; + continue; + } vol = s_ambient_level->value * leaf->ambient_sound_level[ambient_channel]; if( vol < 0 ) vol = 0; @@ -1958,7 +1978,7 @@ void SND_UpdateSound( void ) S_SpatializeRawChannels(); // debugging output - if( s_show->value ) + if( CVAR_TO_BOOL( s_show )) { info.color[0] = 1.0f; info.color[1] = 0.6f; @@ -2174,7 +2194,7 @@ qboolean S_Init( void ) { if( Sys_CheckParm( "-nosound" )) { - MsgDev( D_INFO, "Audio: Disabled\n" ); + Con_Printf( "Audio: Disabled\n" ); return false; } @@ -2185,7 +2205,7 @@ qboolean S_Init( void ) s_lerping = Cvar_Get( "s_lerping", "0", FCVAR_ARCHIVE, "apply interpolation to sound output" ); s_ambient_level = Cvar_Get( "ambient_level", "0.3", FCVAR_ARCHIVE, "volume of environment noises (water and wind)" ); s_ambient_fade = Cvar_Get( "ambient_fade", "1000", FCVAR_ARCHIVE, "rate of volume fading when client is moving" ); - s_combine_sounds = Cvar_Get( "s_combine_channels", "1", FCVAR_ARCHIVE, "combine channels with same sounds" ); + s_combine_sounds = Cvar_Get( "s_combine_channels", "0", FCVAR_ARCHIVE, "combine channels with same sounds" ); snd_foliage_db_loss = Cvar_Get( "snd_foliage_db_loss", "4", 0, "foliage loss factor" ); snd_gain_max = Cvar_Get( "snd_gain_max", "1", 0, "gain maximal threshold" ); snd_gain_min = Cvar_Get( "snd_gain_min", "0.01", 0, "gain minimal threshold" ); @@ -2211,7 +2231,7 @@ qboolean S_Init( void ) if( !SNDDMA_Init( host.hWnd )) { - MsgDev( D_INFO, "S_Init: sound system can't be initialized\n" ); + Con_Printf( "Audio: sound system can't be initialized\n" ); return false; } @@ -2226,6 +2246,7 @@ qboolean S_Init( void ) SX_Init (); S_InitScaletable (); S_StopAllSounds ( true ); + S_InitSounds (); VOX_Init (); return true; diff --git a/engine/client/s_stream.c b/engine/client/s_stream.c index 40d0f99b..bc7a8acc 100644 --- a/engine/client/s_stream.c +++ b/engine/client/s_stream.c @@ -84,15 +84,16 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, long if( mainTrack && *mainTrack == '*' ) mainTrack = NULL; - if(( !introTrack || !*introTrack ) && ( !mainTrack || !*mainTrack )) + if( !COM_CheckString( introTrack ) && !COM_CheckString( mainTrack )) return; if( !introTrack ) introTrack = mainTrack; if( !*introTrack ) return; - if( !mainTrack || !*mainTrack ) s_bgTrack.loopName[0] = '\0'; + if( !COM_CheckString( mainTrack )) + s_bgTrack.loopName[0] = '\0'; else Q_strncpy( s_bgTrack.loopName, mainTrack, sizeof( s_bgTrack.loopName )); -if( fullpath ) Msg( "MP3:Playing: %s\n", introTrack ); + // open stream s_bgTrack.stream = FS_OpenStream( va( "media/%s", introTrack )); Q_strncpy( s_bgTrack.current, introTrack, sizeof( s_bgTrack.current )); diff --git a/engine/client/s_vox.c b/engine/client/s_vox.c index 4082f69a..bee8ae90 100644 --- a/engine/client/s_vox.c +++ b/engine/client/s_vox.c @@ -478,7 +478,7 @@ void VOX_LoadSound( channel_t *pchan, const char *pszin ) if( Q_strlen( psz ) > sizeof( buffer ) - 1 ) { - MsgDev( D_ERROR, "VOX_LoadSound: sentence is too long %s\n", psz ); + Con_Printf( S_ERROR "VOX_LoadSound: sentence is too long %s\n", psz ); return; } @@ -545,7 +545,7 @@ void VOX_ParseLineCommands( char *pSentenceData, int sentenceIndex ) length = pNext - pSentenceData; if( tempBufferPos + length > sizeof( tempBuffer )) { - MsgDev( D_ERROR, "sentence too long!\n" ); + Con_Printf( S_ERROR "sentence too long!\n" ); return; } diff --git a/engine/client/sound.h b/engine/client/sound.h index 2d790a3b..6da7ec9d 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -292,6 +292,7 @@ char *S_SkipSoundChar( const char *pch ); sfx_t *S_FindName( const char *name, int *pfInCache ); sound_t S_RegisterSound( const char *name ); void S_FreeSound( sfx_t *sfx ); +void S_InitSounds( void ); // s_dsp.c void SX_Init( void ); diff --git a/engine/client/vgui/vgui_draw.c b/engine/client/vgui/vgui_draw.c index ef087985..0fbc8027 100644 --- a/engine/client/vgui/vgui_draw.c +++ b/engine/client/vgui/vgui_draw.c @@ -50,7 +50,7 @@ void VGUI_DrawShutdown( void ) for( i = 1; i < g_textureId; i++ ) { - GL_FreeImage( va( "*vgui%i", i )); + GL_FreeTexture( g_textures[i] ); } } @@ -82,7 +82,7 @@ void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) if( id <= 0 || id >= VGUI_MAX_TEXTURES ) { - MsgDev( D_ERROR, "VGUI_UploadTexture: bad texture %i. Ignored\n", id ); + Con_DPrintf( S_ERROR "VGUI_UploadTexture: bad texture %i. Ignored\n", id ); return; } @@ -96,7 +96,7 @@ void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; r_image.buffer = (byte *)buffer; - g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE, false ); + g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE ); } /* diff --git a/engine/client/vgui/vgui_main.h b/engine/client/vgui/vgui_main.h index 9d8145ca..0fe2857c 100644 --- a/engine/client/vgui/vgui_main.h +++ b/engine/client/vgui/vgui_main.h @@ -90,6 +90,7 @@ protected: int _drawTextColor[4]; int _translateX, _translateY; int _currentTexture; + Panel *currentPanel; }; // initialize VGUI::App as external (part of engine) diff --git a/engine/client/vgui/vgui_surf.cpp b/engine/client/vgui/vgui_surf.cpp index 26f00430..30e106a6 100644 --- a/engine/client/vgui/vgui_surf.cpp +++ b/engine/client/vgui/vgui_surf.cpp @@ -75,6 +75,7 @@ void CEngineSurface :: SetupPaintState( const PaintStack *paintState ) _translateX = paintState->iTranslateX; _translateY = paintState->iTranslateY; SetScissorRect( paintState->iScissorLeft, paintState->iScissorTop, paintState->iScissorRight, paintState->iScissorBottom ); + currentPanel = paintState->m_pPanel; } void CEngineSurface :: InitVertex( vpoint_t &vertex, int x, int y, float u, float v ) @@ -196,11 +197,7 @@ void CEngineSurface :: drawSetTextFont( Font *font ) if( y + tall + 1 > FONT_SIZE ) { if( !staticFontInfo->bindIndex[currentPage] ) - { - int bindIndex = createNewTextureID(); - staticFontInfo->bindIndex[currentPage] = bindIndex; - } - + staticFontInfo->bindIndex[currentPage] = createNewTextureID(); drawSetTextureRGBA( staticFontInfo->bindIndex[currentPage], staticRGBA, FONT_SIZE, FONT_SIZE ); currentPage++; @@ -223,11 +220,7 @@ void CEngineSurface :: drawSetTextFont( Font *font ) if( currentPage != FONT_PAGES ) { if( !staticFontInfo->bindIndex[currentPage] ) - { - int bindIndex = createNewTextureID(); - staticFontInfo->bindIndex[currentPage] = bindIndex; - } - + staticFontInfo->bindIndex[currentPage] = createNewTextureID(); drawSetTextureRGBA( staticFontInfo->bindIndex[currentPage], staticRGBA, FONT_SIZE, FONT_SIZE ); } staticFontInfo->pageCount = currentPage + 1; @@ -327,13 +320,14 @@ void CEngineSurface :: drawPrintText( const char *text, int textLen ) static bool hasColor = 0; static int numColor = 7; - if( !text || !staticFont || !staticFontInfo ) + if( !COM_CheckString( text ) || !staticFont || !staticFontInfo ) return; int x = _drawTextPos[0] + _translateX; int y = _drawTextPos[1] + _translateY; int tall = staticFont->getTall(); int curTextColor[4]; + int iTotalWidth = 0; // HACKHACK: allow color strings in VGUI if( numColor != 7 && vgui_colorstrings->value ) @@ -377,12 +371,13 @@ void CEngineSurface :: drawPrintText( const char *text, int textLen ) float t1 = staticFontInfo->texCoord[curCh][3]; int wide = abcB; + iTotalWidth += abcA; drawSetTexture( staticFontInfo->bindIndex[staticFontInfo->pageForChar[curCh]] ); - drawPrintChar( x, y, wide, tall, s0, t0, s1, t1, curTextColor ); - x += abcA + abcB + abcC; + drawPrintChar( x + iTotalWidth, y, wide, tall, s0, t0, s1, t1, curTextColor ); + iTotalWidth += wide + abcC; } - _drawTextPos[0] += x; + _drawTextPos[0] += iTotalWidth; } void CEngineSurface :: drawSetTextureRGBA( int id, const char* rgba, int wide, int tall ) @@ -406,6 +401,7 @@ void CEngineSurface :: drawTexturedRect( int x0, int y0, int x1, int y1 ) vpoint_t rect[2]; vpoint_t clippedRect[2]; + // it's not a vertex, just fill rectangle InitVertex( rect[0], x0, y0, 0, 0 ); InitVertex( rect[1], x1, y1, 1, 1 ); diff --git a/engine/common/avikit.c b/engine/common/avikit.c index deca2199..e2c80705 100644 --- a/engine/common/avikit.c +++ b/engine/common/avikit.c @@ -141,7 +141,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) // WMA codecs, both versions - they simply don't work. if( Avi->audio_header->wFormatTag == 0x160 || Avi->audio_header->wFormatTag == 0x161 ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "ACM does not support this audio codec.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "ACM does not support this audio codec.\n" ); return false; } @@ -150,7 +151,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) if( Avi->audio_header_size < sizeof( WAVEFORMATEX )) { - if( !Avi->quiet ) MsgDev( D_ERROR, "ACM failed to open conversion stream.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" ); return false; } @@ -180,7 +182,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "ACM failed to open conversion stream.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" ); return false; } } @@ -200,7 +203,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) // get the size of the output buffer for streaming the compressed audio if( pacmStreamSize( Avi->cpa_conversion_stream, Avi->cpa_blockalign, &dest_length, ACM_STREAMSIZEF_SOURCE ) != MMSYSERR_NOERROR ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "Couldn't get ACM conversion stream size.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "Couldn't get ACM conversion stream size.\n" ); pacmStreamClose( Avi->cpa_conversion_stream, 0 ); return false; } @@ -223,7 +227,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) if( pacmStreamPrepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 ) != MMSYSERR_NOERROR ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "couldn't prep headers.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "couldn't prepare stream headers.\n" ); pacmStreamClose( Avi->cpa_conversion_stream, 0 ); return false; } @@ -481,20 +486,25 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi switch( hr ) { case AVIERR_BADFORMAT: - if( !Avi->quiet ) MsgDev( D_ERROR, "corrupt file or unknown format.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "corrupt file or unknown format.\n" ); break; case AVIERR_MEMORY: - if( !Avi->quiet ) MsgDev( D_ERROR, "insufficient memory to open file.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "insufficient memory to open file.\n" ); break; case AVIERR_FILEREAD: - if( !Avi->quiet ) MsgDev( D_ERROR, "disk error reading file.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "disk error reading file.\n" ); break; case AVIERR_FILEOPEN: - if( !Avi->quiet ) MsgDev( D_ERROR, "disk error opening file.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "disk error opening file.\n" ); break; case REGDB_E_CLASSNOTREG: default: - if( !Avi->quiet ) MsgDev( D_ERROR, "no handler found (or file not found).\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "no handler found (or file not found).\n" ); break; } return; @@ -564,7 +574,8 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi { if( Avi->pfile ) // if file is open, close it pAVIFileRelease( Avi->pfile ); - if( !Avi->quiet ) MsgDev( D_ERROR, "couldn't find a valid video stream.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "couldn't find a valid video stream.\n" ); return; } @@ -573,7 +584,8 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi if( Avi->video_getframe == NULL ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "error attempting to read video frames.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "error attempting to read video frames.\n" ); return; // couldn't open frame getter. } @@ -618,10 +630,7 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) // fast reject if( !avi_initialized ) - { - MsgDev( D_ERROR, "AVI_LoadVideo: movie support is disabled\n" ); return NULL; - } // open cinematic Q_snprintf( path, sizeof( path ), "media/%s", filename ); @@ -630,7 +639,7 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) if( FS_FileExists( path, false ) && !fullpath ) { - MsgDev( D_ERROR, "AVI_LoadVideo: Couldn't load %s from packfile. Please extract it\n", path ); + Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path ); return NULL; } @@ -667,35 +676,29 @@ qboolean AVI_Initailize( void ) { if( Sys_CheckParm( "-noavi" )) { - MsgDev( D_INFO, "AVI: Disabled\n" ); + Con_Printf( "AVI: Disabled\n" ); return false; } if( !Sys_LoadLibrary( &avifile_dll )) - { - MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); return false; - } if( !Sys_LoadLibrary( &msvfw_dll )) { - MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); Sys_FreeLibrary( &avifile_dll ); return false; } if( !Sys_LoadLibrary( &msacm_dll )) { - MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); Sys_FreeLibrary( &avifile_dll ); Sys_FreeLibrary( &msvfw_dll ); return false; } - pAVIFileInit(); avi_initialized = true; - MsgDev( D_NOTE, "AVI_Initailize: done\n" ); - + pAVIFileInit(); + return true; } diff --git a/engine/common/build.c b/engine/common/build.c index a978fd07..dac721ac 100644 --- a/engine/common/build.c +++ b/engine/common/build.c @@ -23,7 +23,7 @@ static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int Q_buildnum( void ) { // do not touch this! Only author of Xash3D can increase buildnumbers! -#if 0 +#if 1 int m = 0, d = 0, y = 0; static int b = 0; @@ -48,6 +48,6 @@ int Q_buildnum( void ) return b; #else - return 4150; + return 4140; #endif -} +} \ No newline at end of file diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 8e9faff8..e508025b 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -106,7 +106,7 @@ void Cbuf_AddText( const char *text ) if(( cmd_text.cursize + l ) >= cmd_text.maxsize ) { - MsgDev( D_WARN, "Cbuf_AddText: overflow\n" ); + Con_Reportf( S_WARN "Cbuf_AddText: overflow\n" ); } else { @@ -128,7 +128,7 @@ void Cbuf_InsertText( const char *text ) if(( cmd_text.cursize + l ) >= cmd_text.maxsize ) { - MsgDev( D_WARN, "Cbuf_InsertText: overflow\n" ); + Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" ); } else { @@ -184,7 +184,7 @@ void Cbuf_Execute( void ) if( i >= ( MAX_CMD_LINE - 1 )) { - MsgDev( D_ERROR, "Cbuf_Execute: command string owerflow\n" ); + Con_DPrintf( S_ERROR "Cbuf_Execute: command string owerflow\n" ); line[0] = 0; } else @@ -604,23 +604,20 @@ void Cmd_AddServerCommand( const char *cmd_name, xcommand_t function ) { cmd_t *cmd, *cur, *prev; - if( !cmd_name || !*cmd_name ) - { - MsgDev( D_ERROR, "Cmd_AddServerCommand: NULL name\n" ); + if( !COM_CheckString( cmd_name )) return; - } // fail if the command is a variable name if( Cvar_FindVar( cmd_name )) { - MsgDev( D_ERROR, "Cmd_AddServerCommand: %s already defined as a var\n", cmd_name ); + Con_DPrintf( S_ERROR "Cmd_AddServerCommand: %s already defined as a var\n", cmd_name ); return; } // fail if the command already exists if( Cmd_Exists( cmd_name )) { - MsgDev( D_ERROR, "Cmd_AddServerCommand: %s already defined\n", cmd_name ); + Con_DPrintf( S_ERROR "Cmd_AddServerCommand: %s already defined\n", cmd_name ); return; } @@ -648,23 +645,20 @@ int Cmd_AddClientCommand( const char *cmd_name, xcommand_t function ) { cmd_t *cmd, *cur, *prev; - if( !cmd_name || !*cmd_name ) - { - MsgDev( D_ERROR, "Cmd_AddClientCommand: NULL name\n" ); + if( !COM_CheckString( cmd_name )) return 0; - } // fail if the command is a variable name if( Cvar_FindVar( cmd_name )) { - MsgDev( D_ERROR, "Cmd_AddClientCommand: %s already defined as a var\n", cmd_name ); + Con_DPrintf( S_ERROR "Cmd_AddClientCommand: %s already defined as a var\n", cmd_name ); return 0; } // fail if the command already exists if( Cmd_Exists( cmd_name )) { - MsgDev( D_ERROR, "Cmd_AddClientCommand: %s already defined\n", cmd_name ); + Con_DPrintf( S_ERROR "Cmd_AddClientCommand: %s already defined\n", cmd_name ); return 0; } @@ -694,23 +688,20 @@ int Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function ) { cmd_t *cmd, *cur, *prev; - if( !cmd_name || !*cmd_name ) - { - MsgDev( D_ERROR, "Cmd_AddGameUICommand: NULL name\n" ); + if( !COM_CheckString( cmd_name )) return 0; - } // fail if the command is a variable name if( Cvar_FindVar( cmd_name )) { - MsgDev( D_ERROR, "Cmd_AddGameUICommand: %s already defined as a var\n", cmd_name ); + Con_DPrintf( S_ERROR "Cmd_AddGameUICommand: %s already defined as a var\n", cmd_name ); return 0; } // fail if the command already exists if( Cmd_Exists( cmd_name )) { - MsgDev( D_ERROR, "Cmd_AddGameUICommand: %s already defined\n", cmd_name ); + Con_DPrintf( S_ERROR "Cmd_AddGameUICommand: %s already defined\n", cmd_name ); return 0; } diff --git a/engine/common/common.c b/engine/common/common.c index df4b928d..402ce1d5 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -40,8 +40,8 @@ void DBG_AssertFunction( qboolean fExpr, const char* szExpr, const char* szFile, if( fExpr ) return; if( szMessage != NULL ) - MsgDev( at_error, "ASSERT FAILED:\n %s \n(%s@%d)\n%s\n", szExpr, szFile, szLine, szMessage ); - else MsgDev( at_error, "ASSERT FAILED:\n %s \n(%s@%d)\n", szExpr, szFile, szLine ); + Con_DPrintf( S_ERROR "ASSERT FAILED:\n %s \n(%s@%d)\n%s\n", szExpr, szFile, szLine, szMessage ); + else Con_DPrintf( S_ERROR "ASSERT FAILED:\n %s \n(%s@%d)\n", szExpr, szFile, szLine ); } #endif // DEBUG @@ -769,7 +769,7 @@ COM_CheckString */ int COM_CheckString( const char *string ) { - if( !string || (byte)*string <= ' ' ) + if( !string || !*string ) return 0; return 1; } diff --git a/engine/common/common.h b/engine/common/common.h index 49082dc4..11cc46f4 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -123,7 +123,7 @@ typedef enum #include "crtlib.h" #include "cvar.h" -#define XASH_VERSION 0.99f // engine current version +#define XASH_VERSION "0.99" // engine current version // PERFORMANCE INFO #define MIN_FPS 20.0 // host minimum fps value for maxfps. @@ -379,6 +379,7 @@ typedef struct host_parm_s string finalmsg; // server shutdown final message string downloadfile; // filename to be downloading int downloadcount; // how many files remain to downloading + char deferred_cmd[128]; // deferred commands host_redirect_t rd; // remote console // command line parms @@ -503,7 +504,7 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 == ======================================================================== */ #define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24) -#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5) +#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2) typedef enum { @@ -517,6 +518,7 @@ typedef enum PF_DXT1, // s3tc DXT1 format PF_DXT3, // s3tc DXT3 format PF_DXT5, // s3tc DXT5 format + PF_ATI2, // latc ATI2N format PF_TOTALCOUNT, // must be last } pixformat_t; diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 710667b1..be3f4500 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -675,10 +675,7 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir ) file_t *f; if( FS_FileSize( "maps.lst", onlyingamedir ) > 0 && !fRefresh ) - { - MsgDev( D_NOTE, "maps.lst is exist: %s\n", onlyingamedir ? "basedir" : "gamedir" ); return true; // exist - } t = FS_Search( "maps/*.bsp", false, onlyingamedir ); @@ -917,10 +914,11 @@ void Host_WriteConfig( void ) if( !clgame.hInstance ) return; - MsgDev( D_NOTE, "Host_WriteConfig()\n" ); + f = FS_Open( "config.cfg", "w", false ); if( f ) { + Con_Reportf( "Host_WriteConfig()\n" ); FS_Printf( f, "//=======================================================================\n"); FS_Printf( f, "//\t\t\tCopyright XashXT Group %s (C)\n", Q_timestamp( TIME_YEAR_ONLY )); FS_Printf( f, "//\t\t\tconfig.cfg - archive of cvars\n" ); @@ -945,7 +943,7 @@ void Host_WriteConfig( void ) FS_Close( f ); } - else MsgDev( D_ERROR, "Couldn't write config.cfg.\n" ); + else Con_DPrintf( S_ERROR "Couldn't write config.cfg.\n" ); } /* @@ -974,7 +972,7 @@ void Host_WriteServerConfig( const char *name ) CSCR_WriteGameCVars( f, "settings.scr" ); FS_Close( f ); } - else MsgDev( D_ERROR, "Couldn't write %s.\n", name ); + else Con_DPrintf( S_ERROR "Couldn't write %s.\n", name ); SV_FreeGameProgs(); // release progs with all variables } @@ -990,10 +988,11 @@ void Host_WriteOpenGLConfig( void ) { file_t *f; - MsgDev( D_NOTE, "Host_WriteGLConfig()\n" ); + f = FS_Open( "opengl.cfg", "w", false ); if( f ) { + Con_Reportf( "Host_WriteGLConfig()\n" ); FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//\t\t\tCopyright XashXT Group %s (C)\n", Q_timestamp( TIME_YEAR_ONLY )); FS_Printf( f, "//\t\t opengl.cfg - archive of opengl extension cvars\n"); @@ -1002,7 +1001,7 @@ void Host_WriteOpenGLConfig( void ) Cmd_WriteOpenGLVariables( f ); FS_Close( f ); } - else MsgDev( D_ERROR, "can't update opengl.cfg.\n" ); + else Con_DPrintf( S_ERROR "can't update opengl.cfg.\n" ); } /* @@ -1016,10 +1015,10 @@ void Host_WriteVideoConfig( void ) { file_t *f; - MsgDev( D_NOTE, "Host_WriteVideoConfig()\n" ); f = FS_Open( "video.cfg", "w", false ); if( f ) { + Con_Reportf( "Host_WriteVideoConfig()\n" ); FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//\t\t\tCopyright XashXT Group %s (C)\n", Q_timestamp( TIME_YEAR_ONLY )); FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n"); @@ -1027,7 +1026,7 @@ void Host_WriteVideoConfig( void ) Cvar_WriteVariables( f, FCVAR_RENDERINFO ); FS_Close( f ); } - else MsgDev( D_ERROR, "can't update video.cfg.\n" ); + else Con_DPrintf( S_ERROR "can't update video.cfg.\n" ); } void Key_EnumCmds_f( void ) diff --git a/engine/common/console.c b/engine/common/console.c index b0b0dee3..17c40965 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -468,7 +468,7 @@ void Con_CheckResize( void ) int i, width; if( con.curFont && con.curFont->hFontTexture ) - charWidth = con.curFont->charWidths['M'] - 1; + charWidth = con.curFont->charWidths['O'] - 1; width = ( glState.width / charWidth ) - 2; if( !glw_state.initialized ) width = (640 / 5); @@ -973,7 +973,7 @@ void Con_Init( void ) Cmd_AddCommand( "contimes", Con_SetTimes_f, "change number of console overlay lines (4-64)" ); con.initialized = true; - MsgDev( D_INFO, "Console initialized.\n" ); + Con_Printf( "Console initialized.\n" ); } /* @@ -1746,6 +1746,7 @@ void Key_Console( int key ) Con_ClearField( &con.input ); con.input.widthInChars = con.linewidth; + Con_Bottom(); if( cls.state == ca_disconnected ) { @@ -1759,6 +1760,7 @@ void Key_Console( int key ) if( key == K_TAB ) { Con_CompleteCommand( &con.input ); + Con_Bottom(); return; } @@ -2096,7 +2098,7 @@ void Con_DrawSolidConsole( int lines ) memcpy( color, g_color_table[7], sizeof( color )); - Q_snprintf( curbuild, MAX_STRING, "Xash3D %i/%g (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + Q_snprintf( curbuild, MAX_STRING, "Xash3D %i/%s (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); start = glState.width - stringLen; stringLen = Con_StringLength( curbuild ); @@ -2246,8 +2248,8 @@ void Con_DrawVersion( void ) } if( host.force_draw_version || draw_version ) - Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); - else Q_snprintf( curbuild, MAX_STRING, "v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%s (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + else Q_snprintf( curbuild, MAX_STRING, "v%i/%s (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); start = glState.width - stringLen * 1.05f; stringLen = Con_StringLength( curbuild ); @@ -2368,7 +2370,7 @@ void Con_VidInit( void ) { qboolean draw_to_console = false; int length = 0; - gltexture_t *chars; + gl_texture_t *chars; // NOTE: only these games want to draw build number into console background if( !Q_stricmp( FS_Gamedir(), "id1" )) diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 6aabfec8..42e28605 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -320,7 +320,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char * // check for command coexisting if( Cmd_Exists( name )) { - MsgDev( D_ERROR, "can't register variable '%s', is already defined as command\n", name ); + Con_DPrintf( S_ERROR "can't register variable '%s', is already defined as command\n", name ); return NULL; } @@ -356,7 +356,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char * if( FBitSet( var->flags, FCVAR_ALLOCATED ) && Q_strcmp( var_desc, var->desc )) { if( !FBitSet( flags, FCVAR_GLCONFIG )) - MsgDev( D_REPORT, "%s change description from %s to %s\n", var->name, var->desc, var_desc ); + Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc ); // update description if needs freestring( var->desc ); var->desc = copystring( var_desc ); @@ -410,7 +410,7 @@ void Cvar_RegisterVariable( convar_t *var ) { if( !FBitSet( dup->flags, FCVAR_TEMPORARY )) { - MsgDev( D_ERROR, "can't register variable '%s', is already defined\n", var->name ); + Con_DPrintf( S_ERROR "can't register variable '%s', is already defined\n", var->name ); return; } @@ -421,7 +421,7 @@ void Cvar_RegisterVariable( convar_t *var ) // check for overlap with a command if( Cmd_Exists( var->name )) { - MsgDev( D_ERROR, "can't register variable '%s', is already defined as command\n", var->name ); + Con_DPrintf( S_ERROR "can't register variable '%s', is already defined as command\n", var->name ); return; } @@ -469,16 +469,12 @@ void Cvar_DirectSet( convar_t *var, const char *value ) if( CVAR_CHECK_SENTINEL( var ) || ( var->next == NULL && !FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED ))) { // need to registering cvar fisrt - MsgDev( D_WARN, "Cvar_DirectSet: called for unregistered cvar '%s'\n", var->name ); Cvar_RegisterVariable( var ); // ok, register it } // lookup for registration again if( var != Cvar_FindVar( var->name )) - { - MsgDev( D_ERROR, "Cvar_DirectSet: couldn't find cvar '%s' in linked list\n", var->name ); - return; - } + return; // how this possible? if( FBitSet( var->flags, FCVAR_READ_ONLY|FCVAR_GLCONFIG )) { @@ -565,8 +561,7 @@ void Cvar_Set( const char *var_name, const char *value ) if( !var ) { // there is an error in C code if this happens - if( host.type != HOST_DEDICATED ) - MsgDev( D_ERROR, "Cvar_Set: variable '%s' not found\n", var_name ); + Con_Printf( "Cvar_Set: variable '%s' not found\n", var_name ); return; } diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index 2cc940f8..1f0b2e25 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -109,7 +109,6 @@ char fs_basedir[MAX_SYSPATH]; // base game directory char fs_gamedir[MAX_SYSPATH]; // game current directory char fs_writedir[MAX_SYSPATH]; // path that game allows to overwrite, delete and rename files (and create new of course) qboolean fs_ext_path = false; // attempt to read\write from ./ or ../ pathes -static const wadtype_t wad_hints[10]; static void FS_InitMemory( void ); static searchpath_t *FS_FindFile( const char *name, int *index, qboolean gamedironly ); @@ -1005,6 +1004,11 @@ static qboolean FS_ParseLiblistGam( const char *filename, const char *gamedir, g pfile = COM_ParseFile( pfile, token ); GameInfo->size = Q_atoi( token ); } + else if( !Q_stricmp( token, "edicts" )) + { + pfile = COM_ParseFile( pfile, token ); + GameInfo->max_edicts = Q_atoi( token ); + } else if( !Q_stricmp( token, "mpentity" )) { pfile = COM_ParseFile( pfile, GameInfo->mp_entity ); @@ -2641,7 +2645,7 @@ search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly ) continue; // build the lumpname with image suffix (if present) - Q_snprintf( temp, sizeof( temp ), "%s%s", wad->lumps[i].name, wad_hints[wad->lumps[i].img_type].ext ); + Q_strncpy( temp, wad->lumps[i].name, sizeof( temp )); while( temp[0] ) { @@ -2764,21 +2768,6 @@ static const wadtype_t wad_types[7] = { NULL, TYP_NONE } }; -// suffix converts to img_type and back -static const wadtype_t wad_hints[10] = -{ -{ "", IMG_DIFFUSE }, // no suffix -{ "_mask", IMG_ALPHAMASK }, // alpha-channel stored to another lump -{ "_norm", IMG_NORMALMAP }, // indexed normalmap -{ "_spec", IMG_GLOSSMAP }, // grayscale\color specular -{ "_gpow", IMG_GLOSSPOWER }, // grayscale gloss power -{ "_hmap", IMG_HEIGHTMAP }, // heightmap (can be converted to normalmap) -{ "_luma", IMG_LUMA }, // self-illuminate parts on the diffuse -{ "_adec", IMG_DECAL_ALPHA }, // classic HL-decal (with alpha-channel) -{ "_cdec", IMG_DECAL_COLOR }, // paranoia decal (base 127 127 127) -{ NULL, 0 } // terminator -}; - /* =========== W_TypeFromExt @@ -2826,40 +2815,6 @@ static const char *W_ExtFromType( char lumptype ) return ""; } -/* -=========== -W_HintFromSuf - -Convert name suffix into image type -=========== -*/ -char W_HintFromSuf( const char *lumpname ) -{ - char barename[64]; - char suffix[8]; - size_t namelen; - const wadtype_t *hint; - - // trying to extract hint from the name - COM_FileBase( lumpname, barename ); - namelen = Q_strlen( barename ); - - if( namelen <= HINT_NAMELEN ) - return IMG_DIFFUSE; - - Q_strncpy( suffix, barename + namelen - HINT_NAMELEN, sizeof( suffix )); - - // we not known about filetype, so match only by filename - for( hint = wad_hints; hint->ext; hint++ ) - { - if( !Q_stricmp( suffix, hint->ext )) - return hint->type; - } - - // no any special type was found - return IMG_DIFFUSE; -} - /* =========== W_FindLump @@ -2869,37 +2824,11 @@ Serach for already existed lump */ static dlumpinfo_t *W_FindLump( wfile_t *wad, const char *name, const char matchtype ) { - char img_type = IMG_DIFFUSE; - char barename[64], suffix[8]; - int left, right; - size_t namelen; - const wadtype_t *hint; + int left, right; if( !wad || !wad->lumps || matchtype == TYP_NONE ) return NULL; - // trying to extract hint from the name - COM_FileBase( name, barename ); - namelen = Q_strlen( barename ); - - if( namelen > HINT_NAMELEN ) - { - Q_strncpy( suffix, barename + namelen - HINT_NAMELEN, sizeof( suffix )); - - // we not known about filetype, so match only by filename - for( hint = wad_hints; hint->ext; hint++ ) - { - if( !Q_stricmp( suffix, hint->ext )) - { - img_type = hint->type; - break; - } - } - - if( img_type != IMG_DIFFUSE ) - barename[namelen - HINT_NAMELEN] = '\0'; // kill the suffix - } - // look for the file (binary search) left = 0; right = wad->numlumps - 1; @@ -2907,15 +2836,11 @@ static dlumpinfo_t *W_FindLump( wfile_t *wad, const char *name, const char match while( left <= right ) { int middle = (left + right) / 2; - int diff = Q_stricmp( wad->lumps[middle].name, barename ); + int diff = Q_stricmp( wad->lumps[middle].name, name ); if( !diff ) { - if( wad->lumps[middle].img_type > img_type ) - diff = 1; - else if( wad->lumps[middle].img_type < img_type ) - diff = -1; - else if(( matchtype == TYP_ANY ) || ( matchtype == wad->lumps[middle].type )) + if(( matchtype == TYP_ANY ) || ( matchtype == wad->lumps[middle].type )) return &wad->lumps[middle]; // found else if( wad->lumps[middle].type < matchtype ) diff = 1; @@ -2956,11 +2881,7 @@ static dlumpinfo_t *W_AddFileToWad( const char *name, wfile_t *wad, dlumpinfo_t if( !diff ) { - if( wad->lumps[middle].img_type > newlump->img_type ) - diff = 1; - else if( wad->lumps[middle].img_type < newlump->img_type ) - diff = -1; - else if( wad->lumps[middle].type < newlump->type ) + if( wad->lumps[middle].type < newlump->type ) diff = 1; else if( wad->lumps[middle].type > newlump->type ) diff = -1; @@ -3143,10 +3064,6 @@ wfile_t *W_Open( const char *filename, int *error ) if( srclumps[i].type == 68 && !Q_stricmp( srclumps[i].name, "conchars" )) srclumps[i].type = TYP_GFXPIC; - // fixups bad image types (some quake wads) - if( srclumps[i].img_type < 0 || srclumps[i].img_type > IMG_DECAL_COLOR ) - srclumps[i].img_type = IMG_DIFFUSE; - W_AddFileToWad( name, wad, &srclumps[i] ); } diff --git a/engine/common/filesystem.h b/engine/common/filesystem.h index b08f62b1..f407f6f2 100644 --- a/engine/common/filesystem.h +++ b/engine/common/filesystem.h @@ -62,10 +62,6 @@ infotable dlumpinfo_t[dwadinfo_t->numlumps] #define HINT_NAMELEN 5 // e.g. _mask, _norm #define MAX_FILES_IN_WAD 65535 // real limit as above <2Gb size not a lumpcount -// hidden virtual lump types -#define TYP_ANY -1 // any type can be accepted -#define TYP_NONE 0 // unknown lump type - #include "const.h" typedef struct @@ -82,8 +78,8 @@ typedef struct int size; // uncompressed char type; // TYP_* char attribs; // file attribs - char img_type; // IMG_* - char pad; + char pad0; + char pad1; char name[WAD3_NAMELEN]; // must be null terminated } dlumpinfo_t; diff --git a/engine/common/host.c b/engine/common/host.c index 82048720..cb25e0d9 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -65,19 +65,19 @@ Host_PrintEngineFeatures void Host_PrintEngineFeatures( void ) { if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD )) - MsgDev( D_REPORT, "^3EXT:^7 big world support enabled\n" ); + Con_Reportf( "^3EXT:^7 big world support enabled\n" ); if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA )) - MsgDev( D_REPORT, "^3EXT:^7 deluxemap support enabled\n" ); + Con_Reportf( "^3EXT:^7 deluxemap support enabled\n" ); if( FBitSet( host.features, ENGINE_PHYSICS_PUSHER_EXT )) - MsgDev( D_REPORT, "^3EXT:^7 Improved MOVETYPE_PUSH is used\n" ); + Con_Reportf( "^3EXT:^7 Improved MOVETYPE_PUSH is used\n" ); if( FBitSet( host.features, ENGINE_LARGE_LIGHTMAPS )) - MsgDev( D_REPORT, "^3EXT:^7 Large lightmaps enabled\n" ); + Con_Reportf( "^3EXT:^7 Large lightmaps enabled\n" ); if( FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG )) - MsgDev( D_REPORT, "^3EXT:^7 Compensate quake bug enabled\n" ); + Con_Reportf( "^3EXT:^7 Compensate quake bug enabled\n" ); } /* @@ -94,7 +94,7 @@ void Host_EndGame( qboolean abort, const char *message, ... ) Q_vsnprintf( string, sizeof( string ), message, argptr ); va_end( argptr ); - MsgDev( D_INFO, "Host_EndGame: %s\n", string ); + Con_Printf( "Host_EndGame: %s\n", string ); SV_Shutdown( "\n" ); CL_Disconnect(); @@ -228,7 +228,7 @@ void Host_Exec_f( void ) f = FS_LoadFile( cfgpath, &len, false ); if( !f ) { - MsgDev( D_NOTE, "couldn't exec %s\n", Cmd_Argv( 1 )); + Con_Reportf( "couldn't exec %s\n", Cmd_Argv( 1 )); return; } @@ -242,7 +242,7 @@ void Host_Exec_f( void ) Mem_Free( f ); if( !host.apply_game_config ) - MsgDev( D_INFO, "execing %s\n", Cmd_Argv( 1 )); + Con_Printf( "execing %s\n", Cmd_Argv( 1 )); Cbuf_InsertText( txt ); Mem_Free( txt ); } @@ -325,7 +325,7 @@ qboolean Host_RegisterDecal( const char *name, int *count ) if( i == MAX_DECALS ) { - MsgDev( D_ERROR, "MAX_DECALS limit exceeded (%d)\n", MAX_DECALS ); + Con_DPrintf( S_ERROR "MAX_DECALS limit exceeded (%d)\n", MAX_DECALS ); return false; } @@ -739,7 +739,7 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame ) Con_CreateConsole(); // system console used by dedicated server or show fatal errors // NOTE: this message couldn't be passed into game console but it doesn't matter - MsgDev( D_NOTE, "Sys_LoadLibrary: Loading xash.dll - ok\n" ); + Con_Reportf( "Sys_LoadLibrary: Loading xash.dll - ok\n" ); // get default screen res VID_InitDefaultResolution(); @@ -823,8 +823,8 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func host_clientloaded = Cvar_Get( "host_clientloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" ); host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" ); con_gamemaps = Cvar_Get( "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" ); - build = Cvar_Get( "build", va( "%i", Q_buildnum()), FCVAR_READ_ONLY, "returns a current build number" ); - ver = Cvar_Get( "ver", va( "%i/%g (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum()), FCVAR_READ_ONLY, "shows an engine version" ); + build = Cvar_Get( "buildnum", va( "%i", Q_buildnum()), FCVAR_READ_ONLY, "returns a current build number" ); + ver = Cvar_Get( "ver", va( "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum()), FCVAR_READ_ONLY, "shows an engine version" ); Mod_Init(); NET_Init(); diff --git a/engine/common/host_state.c b/engine/common/host_state.c index d76551a6..2b3dbc67 100644 --- a/engine/common/host_state.c +++ b/engine/common/host_state.c @@ -25,6 +25,14 @@ static void Host_SetState( host_state_t newState, qboolean clearNext ) if( clearNext ) GameState->nextstate = newState; GameState->curstate = newState; + + if( clearNext && newState == STATE_RUNFRAME ) + { + // states finished here + GameState->backgroundMap = false; + GameState->loadGame = false; + GameState->newGame = false; + } } static void Host_SetNextState( host_state_t nextState ) @@ -38,6 +46,9 @@ void COM_NewGame( char const *pMapName ) if( GameState->nextstate != STATE_RUNFRAME ) return; + if( UI_CreditsActive( )) + return; + Q_strncpy( GameState->levelName, pMapName, sizeof( GameState->levelName )); Host_SetNextState( STATE_LOAD_LEVEL ); @@ -52,6 +63,9 @@ void COM_LoadLevel( char const *pMapName, qboolean background ) if( GameState->nextstate != STATE_RUNFRAME ) return; + if( UI_CreditsActive( )) + return; + Q_strncpy( GameState->levelName, pMapName, sizeof( GameState->levelName )); Host_SetNextState( STATE_LOAD_LEVEL ); @@ -66,6 +80,9 @@ void COM_LoadGame( char const *pMapName ) if( GameState->nextstate != STATE_RUNFRAME ) return; + if( UI_CreditsActive( )) + return; + Q_strncpy( GameState->levelName, pMapName, sizeof( GameState->levelName )); Host_SetNextState( STATE_LOAD_GAME ); GameState->backgroundMap = false; @@ -78,6 +95,9 @@ void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean if( GameState->nextstate != STATE_RUNFRAME ) return; + if( UI_CreditsActive( )) + return; + Q_strncpy( GameState->levelName, pNewLevel, sizeof( GameState->levelName )); GameState->backgroundMap = background; diff --git a/engine/common/imagelib/img_dds.c b/engine/common/imagelib/img_dds.c index 3b6c3b3a..1e24176d 100644 --- a/engine/common/imagelib/img_dds.c +++ b/engine/common/imagelib/img_dds.c @@ -117,6 +117,9 @@ void Image_DXTGetPixelFormat( dds_t *hdr ) case TYPE_DXT5: image.type = PF_DXT5; break; + case TYPE_ATI2: + image.type = PF_ATI2; + break; default: image.type = PF_UNKNOWN; // assume error break; @@ -157,7 +160,8 @@ size_t Image_DXTGetLinearSize( int type, int width, int height, int depth ) { case PF_DXT1: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 8 ); case PF_DXT3: - case PF_DXT5: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 ); + case PF_DXT5: + case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 ); case PF_BGR_24: case PF_RGB_24: return (width * height * depth * 3); case PF_BGRA_32: @@ -214,7 +218,8 @@ uint Image_DXTCalcSize( const char *name, dds_t *hdr, size_t filesize ) if( filesize != buffsize ) // main check { MsgDev( D_WARN, "Image_LoadDDS: (%s) probably corrupted(%i should be %i)\n", name, buffsize, filesize ); - return false; + if( buffsize > filesize ) + return false; } return buffsize; @@ -274,7 +279,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, size_t filesize ) Image_DXTGetPixelFormat( &header ); // and image type too :) Image_DXTAdjustVolume( &header ); - if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ( image.type == PF_DXT1 || image.type == PF_DXT3 || image.type == PF_DXT5 )) + if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageDXT( image.type )) return false; // silently rejected if( image.type == PF_UNKNOWN ) @@ -324,7 +329,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, size_t filesize ) // dds files will be uncompressed on a render. requires minimal of info for set this image.rgba = Mem_Malloc( host.imagepool, image.size ); memcpy( image.rgba, fin, image.size ); - image.flags |= IMAGE_DDS_FORMAT; + SetBits( image.flags, IMAGE_DDS_FORMAT ); return true; } \ No newline at end of file diff --git a/engine/common/imagelib/img_main.c b/engine/common/imagelib/img_main.c index 9fdf95d5..57cf79d4 100644 --- a/engine/common/imagelib/img_main.c +++ b/engine/common/imagelib/img_main.c @@ -47,16 +47,6 @@ static const suffix_t skybox_qv2[6] = static const suffix_t cubemap_v1[6] = { -{ "posx", 0, CB_HINT_POSX }, -{ "negx", 0, CB_HINT_NEGX }, -{ "posy", 0, CB_HINT_POSY }, -{ "negy", 0, CB_HINT_NEGY }, -{ "posz", 0, CB_HINT_POSZ }, -{ "negz", 0, CB_HINT_NEGZ }, -}; - -static const suffix_t cubemap_v2[6] = -{ { "px", 0, CB_HINT_POSX }, { "nx", 0, CB_HINT_NEGX }, { "py", 0, CB_HINT_POSY }, @@ -75,8 +65,7 @@ static const cubepack_t load_cubemap[] = { { "3Ds Sky1", skybox_qv1 }, { "3Ds Sky2", skybox_qv2 }, -{ "3Ds Cube", cubemap_v2 }, -{ "Tenebrae", cubemap_v1 }, +{ "3Ds Cube", cubemap_v1 }, { NULL, NULL }, }; @@ -93,6 +82,7 @@ const bpc_desc_t PFDesc[] = {PF_DXT1, "DXT 1", 0x83F1, 4 }, {PF_DXT3, "DXT 3", 0x83F2, 4 }, {PF_DXT5, "DXT 5", 0x83F3, 4 }, +{PF_ATI2, "ATI 2", 0x8837, 4 }, }; void Image_Reset( void ) @@ -128,7 +118,6 @@ rgbdata_t *ImagePack( void ) if( image.cubemap && image.num_sides != 6 ) { // this never be happens, just in case - MsgDev( D_NOTE, "ImagePack: inconsistent cubemap pack %d\n", image.num_sides ); FS_FreeImage( pack ); return NULL; } @@ -229,8 +218,8 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) const cubepack_t *cmap; byte *f; - Image_Reset(); // clear old image Q_strncpy( loadname, filename, sizeof( loadname )); + Image_Reset(); // clear old image if( Q_stricmp( ext, "" )) { @@ -259,6 +248,7 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) Q_sprintf( path, format->formatstring, loadname, "", format->ext ); image.hint = format->hint; f = FS_LoadFile( path, &filesize, false ); + if( f && filesize > 0 ) { if( format->loadfunc( path, f, filesize )) @@ -266,7 +256,7 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) Mem_Free( f ); // release buffer return ImagePack(); // loaded } - else Mem_Free(f); // release buffer + else Mem_Free( f ); // release buffer } } } @@ -308,8 +298,6 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) // first side not found, probably it's not cubemap // it contain info about image_type and dimensions, don't generate black cubemaps if( !image.cubemap ) break; - MsgDev( D_ERROR, "FS_LoadImage: couldn't load (%s%s), create black image\n", loadname, cmap->type[i].suf ); - // Mem_Alloc already filled memblock with 0x00, no need to do it again image.cubemap = Mem_Realloc( host.imagepool, image.cubemap, image.ptr + image.size ); image.ptr += image.size; // move to next @@ -345,10 +333,8 @@ load_internal: } } - if( !image.loadformats || image.loadformats->ext == NULL ) - MsgDev( D_NOTE, "FS_LoadImage: imagelib offline\n" ); - else if( filename[0] != '#' ) - MsgDev( D_WARN, "FS_LoadImage: couldn't load \"%s\"\n", loadname ); + if( filename[0] != '#' ) + Con_Reportf( S_WARN "FS_LoadImage: couldn't load \"%s\"\n", loadname ); // clear any force flags image.force_flags = 0; @@ -390,7 +376,7 @@ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix ) if( pix->flags & IMAGE_SKYBOX ) box = skybox_qv1; else if( pix->flags & IMAGE_CUBEMAP ) - box = cubemap_v2; + box = cubemap_v1; else { // clear any force flags @@ -456,13 +442,10 @@ free RGBA buffer */ void FS_FreeImage( rgbdata_t *pack ) { - if( pack ) - { - if( pack->buffer ) Mem_Free( pack->buffer ); - if( pack->palette ) Mem_Free( pack->palette ); - Mem_Free( pack ); - } - else MsgDev( D_WARN, "FS_FreeImage: trying to free NULL image\n" ); + if( !pack ) return; + if( pack->buffer ) Mem_Free( pack->buffer ); + if( pack->palette ) Mem_Free( pack->palette ); + Mem_Free( pack ); } /* diff --git a/engine/common/imagelib/img_quant.c b/engine/common/imagelib/img_quant.c index c44569b4..92af3809 100644 --- a/engine/common/imagelib/img_quant.c +++ b/engine/common/imagelib/img_quant.c @@ -245,15 +245,14 @@ int inxsearch( int r, int g, int b ) // Search for biased BGR values int contest( int r, int g, int b ) { - // finds closest neuron (min dist) and updates freq - // finds best neuron (min dist-bias) and returns position - // for frequently chosen neurons, freq[i] is high and bias[i] is negative - // bias[i] = gamma * ((1 / netsize) - freq[i]) - register int *p, *f, *n; register int i, dist, a, biasdist, betafreq; int bestpos, bestbiaspos, bestd, bestbiasd; + // finds closest neuron (min dist) and updates freq + // finds best neuron (min dist-bias) and returns position + // for frequently chosen neurons, freq[i] is high and bias[i] is negative + // bias[i] = gamma * ((1 / netsize) - freq[i]) bestd = ~(1<<31); bestbiasd = bestd; bestpos = -1; diff --git a/engine/common/imagelib/img_utils.c b/engine/common/imagelib/img_utils.c index 640e584a..e8e48141 100644 --- a/engine/common/imagelib/img_utils.c +++ b/engine/common/imagelib/img_utils.c @@ -250,7 +250,7 @@ qboolean Image_ValidSize( const char *name ) { if( image.width > IMAGE_MAXWIDTH || image.height > IMAGE_MAXHEIGHT || image.width <= 0 || image.height <= 0 ) { - MsgDev( D_ERROR, "Image: %s has invalid sizes %i x %i\n", name, image.width, image.height ); + Con_DPrintf( S_ERROR "Image: (%s) dims out of range [%dx%d]\n", name, image.width, image.height ); return false; } return true; @@ -260,7 +260,7 @@ qboolean Image_LumpValidSize( const char *name ) { if( image.width > LUMP_MAXWIDTH || image.height > LUMP_MAXHEIGHT || image.width <= 0 || image.height <= 0 ) { - MsgDev(D_WARN, "Image_LumpValidSize: (%s) dims out of range[%dx%d]\n", name, image.width,image.height ); + Con_DPrintf( S_ERROR "Image: (%s) dims out of range [%dx%d]\n", name, image.width,image.height ); return false; } return true; @@ -309,7 +309,6 @@ void Image_SetPalette( const byte *pal, uint *d_table ) rgba[3] = i; d_table[i] = *(uint *)rgba; } -// d_table[0] = 0x00808080; break; case LUMP_MASKED: for( i = 0; i < 255; i++ ) @@ -390,11 +389,11 @@ void Image_GetPaletteLMP( const byte *pal, int rendermode ) Image_GetPaletteQ1(); break; case LUMP_HALFLIFE: - Image_GetPaletteHL(); // default half-life palette + Image_GetPaletteHL(); break; default: - MsgDev( D_ERROR, "Image_GetPaletteLMP: invalid palette specified\n" ); - Image_GetPaletteHL(); // defaulting to half-life palette + // defaulting to half-life palette + Image_GetPaletteHL(); break; } } @@ -574,17 +573,8 @@ qboolean Image_Copy8bitRGBA( const byte *in, byte *out, int pixels ) byte *col; int i; - if( !image.d_currentpal ) - { - MsgDev( D_ERROR, "Image_Copy8bitRGBA: no palette set\n" ); + if( !in || !image.d_currentpal ) return false; - } - - if( !in ) - { - MsgDev( D_ERROR, "Image_Copy8bitRGBA: no input image\n" ); - return false; - } // this is a base image with luma - clear luma pixels if( image.flags & IMAGE_HAS_LUMA ) @@ -741,7 +731,7 @@ void Image_Resample32Lerp( const void *indata, int inwidth, int inheight, void * if( yi != oldy ) { inrow = (byte *)indata + inwidth4 * yi; - if (yi == oldy+1) memcpy( resamplerow1, resamplerow2, outwidth4 ); + if( yi == oldy + 1 ) memcpy( resamplerow1, resamplerow2, outwidth4 ); else Image_Resample32LerpLine( inrow, resamplerow1, inwidth, outwidth ); Image_Resample32LerpLine( inrow + inwidth4, resamplerow2, inwidth, outwidth ); oldy = yi; @@ -806,7 +796,7 @@ void Image_Resample32Lerp( const void *indata, int inwidth, int inheight, void * { if( yi != oldy ) { - inrow = (byte *)indata + inwidth4*yi; + inrow = (byte *)indata + inwidth4 * yi; if( yi == oldy + 1 ) memcpy( resamplerow1, resamplerow2, outwidth4 ); else Image_Resample32LerpLine( inrow, resamplerow1, inwidth, outwidth); oldy = yi; @@ -1085,7 +1075,6 @@ byte *Image_ResampleInternal( const void *indata, int inwidth, int inheight, int else Image_Resample32Nolerp( indata, inwidth, inheight, image.tempbuffer, outwidth, outheight ); break; default: - MsgDev( D_WARN, "Image_Resample: unsupported format %s\n", PFDesc[type].name ); *resampled = false; return (byte *)indata; } @@ -1105,9 +1094,9 @@ byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int t word width = *srcwidth; word height = *srcheight; int samples = PFDesc[type].bpp; - qboolean flip_x = ( flags & IMAGE_FLIP_X ) ? true : false; - qboolean flip_y = ( flags & IMAGE_FLIP_Y ) ? true : false; - qboolean flip_i = ( flags & IMAGE_ROT_90 ) ? true : false; + qboolean flip_x = FBitSet( flags, IMAGE_FLIP_X ) ? true : false; + qboolean flip_y = FBitSet( flags, IMAGE_FLIP_Y ) ? true : false; + qboolean flip_i = FBitSet( flags, IMAGE_ROT_90 ) ? true : false; int row_inc = ( flip_y ? -samples : samples ) * width; int col_inc = ( flip_x ? -samples : samples ); int row_ofs = ( flip_y ? ( height - 1 ) * width * samples : 0 ); @@ -1130,7 +1119,6 @@ byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int t image.tempbuffer = Mem_Realloc( host.imagepool, image.tempbuffer, width * height * samples ); break; default: - MsgDev( D_WARN, "Image_Flip: unsupported format %s\n", PFDesc[type].name ); return (byte *)in; } @@ -1334,10 +1322,7 @@ rgbdata_t *Image_LightGamma( rgbdata_t *pic ) qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomColor ) { if( !pic->palette ) - { - MsgDev( D_ERROR, "Image_Remap: palette is missed\n" ); return false; - } switch( pic->type ) { @@ -1347,7 +1332,6 @@ qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomColor ) Image_ConvertPalTo24bit( pic ); break; default: - MsgDev( D_ERROR, "Image_Remap: unsupported format %s\n", PFDesc[pic->type].name ); return false; } @@ -1495,7 +1479,6 @@ qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, imgf // check for buffers if( !pic || !pic->buffer ) { - MsgDev( D_WARN, "Image_Process: NULL image\n" ); image.force_flags = 0; return false; } @@ -1540,7 +1523,7 @@ qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, imgf if( resampled ) // resampled or filled { - MsgDev( D_NOTE, "Image_Resample: from[%d x %d] to [%d x %d]\n", pic->width, pic->height, w, h ); + Con_Reportf( "Image_Resample: from[%d x %d] to [%d x %d]\n", pic->width, pic->height, w, h ); pic->width = w, pic->height = h; pic->size = w * h * PFDesc[pic->type].bpp; Mem_Free( pic->buffer ); // free original image buffer diff --git a/engine/common/imagelib/img_wad.c b/engine/common/imagelib/img_wad.c index e64c304b..83fae094 100644 --- a/engine/common/imagelib/img_wad.c +++ b/engine/common/imagelib/img_wad.c @@ -384,13 +384,13 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize ) // NOTE: decals with 'blue base' can be interpret as colored decals if( !Image_CheckFlag( IL_LOAD_DECAL ) || ( pal[765] == 0 && pal[766] == 0 && pal[767] == 255 )) { + SetBits( image.flags, IMAGE_ONEBIT_ALPHA ); rendermode = LUMP_MASKED; - image.flags |= IMAGE_ONEBIT_ALPHA; } else { // classic gradient decals - image.flags |= IMAGE_COLORINDEX; + SetBits( image.flags, IMAGE_COLORINDEX ); rendermode = LUMP_GRADIENT; } @@ -405,8 +405,8 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize ) // this is a good reason for using fullbright pixels pal_type = Image_ComparePalette( pal ); - // check for luma pixels (but ignore liquid textures, this a Xash3D limitation) - if( mip.name[0] != '!' && pal_type == PAL_QUAKE1 ) + // check for luma pixels (but ignore liquid textures because they have no lightmap) + if( mip.name[0] != '*' && mip.name[0] != '!' && pal_type == PAL_QUAKE1 ) { for( i = 0; i < image.width * image.height; i++ ) { @@ -440,11 +440,7 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize ) { if( fin[i] > 224 && fin[i] != 255 ) { - // don't apply luma to water surfaces because - // we use glpoly->next for store luma chain each frame - // and can't modify glpoly_t because many-many HL mods - // expected unmodified glpoly_t and can crashes on changed struct - // water surfaces uses glpoly->next as pointer to subdivided surfaces (as q1) + // don't apply luma to water surfaces because they have no lightmap if( mip.name[0] != '*' && mip.name[0] != '!' ) image.flags |= IMAGE_HAS_LUMA; break; @@ -503,8 +499,9 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize ) // calc the decal reflectivity image.fogParams[3] = VectorAvg( image.fogParams ); } - else if( pal != NULL )// calc texture reflectivity + else if( pal != NULL ) { + // calc texture reflectivity for( i = 0; i < 256; i++ ) { reflectivity[0] += pal[i*3+0]; diff --git a/engine/common/infostring.c b/engine/common/infostring.c index fd299ac1..7f7594e3 100644 --- a/engine/common/infostring.c +++ b/engine/common/infostring.c @@ -416,7 +416,7 @@ qboolean Info_SetValueForStarKey( char *s, const char *key, const char *value, i if( Q_strstr( key, "\\" ) || Q_strstr( value, "\\" )) { - MsgDev( D_ERROR, "SetValueForKey: can't use keys or values with a \\\n" ); + Con_Printf( S_ERROR "SetValueForKey: can't use keys or values with a \\\n" ); return false; } @@ -425,15 +425,12 @@ qboolean Info_SetValueForStarKey( char *s, const char *key, const char *value, i if( Q_strstr( key, "\"" ) || Q_strstr( value, "\"" )) { - MsgDev( D_ERROR, "SetValueForKey: can't use keys or values with a \"\n" ); + Con_Printf( S_ERROR "SetValueForKey: can't use keys or values with a \"\n" ); return false; } if( Q_strlen( key ) > ( MAX_KV_SIZE - 1 ) || Q_strlen( value ) > ( MAX_KV_SIZE - 1 )) - { - MsgDev( D_ERROR, "SetValueForKey: keys and values must be < %i characters.\n", MAX_KV_SIZE ); return false; - } Info_RemoveKey( s, key ); @@ -458,14 +455,12 @@ qboolean Info_SetValueForStarKey( char *s, const char *key, const char *value, i if( largekey[0] == 0 ) { // no room to add setting - MsgDev( D_ERROR, "SetValueForKey: info string length exceeded\n" ); return true; // info changed, new value can't saved } } else { // no room to add setting - MsgDev( D_ERROR, "SetValueForKey: info string length exceeded\n" ); return true; // info changed, new value can't saved } } @@ -492,7 +487,7 @@ qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int m { if( key[0] == '*' ) { - MsgDev( D_ERROR, "Can't set *keys\n" ); + Con_Printf( S_ERROR "Can't set *keys\n" ); return false; } diff --git a/engine/common/keys.c b/engine/common/keys.c index 65d2e527..8ddcc66e 100644 --- a/engine/common/keys.c +++ b/engine/common/keys.c @@ -20,6 +20,7 @@ GNU General Public License for more details. typedef struct key_s { qboolean down; + qboolean gamedown; int repeats; // if > 1, it is autorepeating const char *binding; } key_t; @@ -265,16 +266,27 @@ const char *Key_GetBinding( int keynum ) Key_GetKey =================== */ -int Key_GetKey( const char *binding ) +int Key_GetKey( const char *pBinding ) { int i; - if( !binding ) return -1; + if( !pBinding ) return -1; for( i = 0; i < 256; i++ ) { - if( keys[i].binding && !Q_stricmp( binding, keys[i].binding )) - return i; + if( !keys[i].binding ) + continue; + + if( *keys[i].binding == '+' ) + { + if( !Q_strnicmp( keys[i].binding + 1, pBinding, Q_strlen( pBinding ))) + return i; + } + else + { + if( !Q_strnicmp( keys[i].binding, pBinding, Q_strlen( pBinding ))) + return i; + } } return -1; @@ -459,18 +471,17 @@ void Key_Init( void ) /* =================== -Key_AddKeyUpCommands +Key_AddKeyCommands =================== */ -void Key_AddKeyUpCommands( int key, const char *kb ) +void Key_AddKeyCommands( int key, const char *kb, qboolean down ) { - int i; - char button[1024], *buttonPtr; + char button[1024]; + char *buttonPtr; char cmd[1024]; - qboolean keyevent; + int i; if( !kb ) return; - keyevent = false; buttonPtr = button; for( i = 0; ; i++ ) @@ -481,18 +492,15 @@ void Key_AddKeyUpCommands( int key, const char *kb ) if( button[0] == '+' ) { // button commands add keynum as a parm - Q_sprintf( cmd, "-%s %i\n", button+1, key ); + if( down ) Q_sprintf( cmd, "%s %i\n", button, key ); + else Q_sprintf( cmd, "-%s %i\n", button + 1, key ); Cbuf_AddText( cmd ); - keyevent = true; } - else + else if( down ) { - if( keyevent ) - { - // down-only command - Cbuf_AddText( button ); - Cbuf_AddText( "\n" ); - } + // down-only command + Cbuf_AddText( button ); + Cbuf_AddText( "\n" ); } buttonPtr = button; @@ -505,6 +513,29 @@ void Key_AddKeyUpCommands( int key, const char *kb ) } } +/* +=================== +Key_IsAllowedAutoRepeat + +List of keys that allows auto-repeat +=================== +*/ +qboolean Key_IsAllowedAutoRepeat( int key ) +{ + switch( key ) + { + case K_BACKSPACE: + case K_PAUSE: + case K_PGUP: + case K_KP_PGUP: + case K_PGDN: + case K_KP_PGDN: + return true; + default: + return false; + } +} + /* =================== Key_Event @@ -515,30 +546,58 @@ Called by the system for both key up and key down events void Key_Event( int key, qboolean down ) { const char *kb; - char cmd[1024]; // key was pressed before engine was run if( !keys[key].down && !down ) return; - // update auto-repeat status and BUTTON_ANY status + kb = keys[key].binding; keys[key].down = down; +#ifdef HACKS_RELATED_HLMODS + if(( cls.key_dest == key_game ) && ( cls.state == ca_cinematic ) && ( key != K_ESCAPE || !down )) + { + // only escape passed when cinematic is playing + // HLFX 0.6 bug: crash in vgui3.dll while press +attack during movie playback + return; + } +#endif + // distribute the key down event to the apropriate handler + if( cls.key_dest == key_game && ( down || keys[key].gamedown )) + { + if( !clgame.dllFuncs.pfnKey_Event( down, key, keys[key].binding )) + { + if( keys[key].repeats == 0 && down ) + { + keys[key].gamedown = true; + } + + if( !down ) + { + keys[key].gamedown = false; + keys[key].repeats = 0; + } + return; // handled in client.dll + } + } + + // update auto-repeat status if( down ) { keys[key].repeats++; - if( key != K_BACKSPACE && key != K_PAUSE && keys[key].repeats > 1 ) + if( !Key_IsAllowedAutoRepeat( key ) && keys[key].repeats > 1 ) { - if( cls.key_dest == key_game ) - { - // ignore most autorepeats - return; - } + // ignore most autorepeats + return; } + + if( key >= 200 && !kb ) + Con_Printf( "%s is unbound.\n", Key_KeynumToString( key )); } else { + keys[key].gamedown = false; keys[key].repeats = 0; } @@ -563,13 +622,13 @@ void Key_Event( int key, qboolean down ) switch( cls.key_dest ) { case key_game: - if( gl_showtextures->value ) + if( CVAR_TO_BOOL( gl_showtextures )) { // close texture atlas Cvar_SetValue( "r_showtextures", 0.0f ); return; } - if( host.mouse_visible && cls.state != ca_cinematic ) + else if( host.mouse_visible && cls.state != ca_cinematic ) { clgame.dllFuncs.pfnKey_Event( down, key, keys[key].binding ); return; // handled in client.dll @@ -586,9 +645,7 @@ void Key_Event( int key, qboolean down ) case key_menu: UI_KeyEvent( key, true ); return; - default: - MsgDev( D_ERROR, "Key_Event: bad cls.key_dest\n" ); - return; + default: return; } } @@ -605,72 +662,14 @@ void Key_Event( int key, qboolean down ) // an action started before a mode switch. if( !down ) { - kb = keys[key].binding; - - if( cls.key_dest == key_game && ( key != K_ESCAPE )) - clgame.dllFuncs.pfnKey_Event( down, key, kb ); - - Key_AddKeyUpCommands( key, kb ); + Key_AddKeyCommands( key, kb, down ); return; } // distribute the key down event to the apropriate handler if( cls.key_dest == key_game ) { - if( cls.state == ca_cinematic && ( key != K_ESCAPE || !down )) - { - // only escape passed when cinematic is playing - // HLFX 0.6 bug: crash in vgui3.dll while press +attack during movie playback - return; - } - - // send the bound action - kb = keys[key].binding; - - if( !clgame.dllFuncs.pfnKey_Event( down, key, keys[key].binding )) - { - // handled in client.dll - } - else if( kb != NULL ) - { - if( kb[0] == '+' ) - { - int i; - char button[1024], *buttonPtr; - - for( i = 0, buttonPtr = button; ; i++ ) - { - if( kb[i] == ';' || !kb[i] ) - { - *buttonPtr = '\0'; - if( button[0] == '+' ) - { - Q_sprintf( cmd, "%s %i\n", button, key ); - Cbuf_AddText( cmd ); - } - else - { - // down-only command - Cbuf_AddText( button ); - Cbuf_AddText( "\n" ); - } - - buttonPtr = button; - while (( kb[i] <= ' ' || kb[i] == ';' ) && kb[i] != 0 ) - i++; - } - - *buttonPtr++ = kb[i]; - if( !kb[i] ) break; - } - } - else - { - // down-only command - Cbuf_AddText( kb ); - Cbuf_AddText( "\n" ); - } - } + Key_AddKeyCommands( key, kb, down ); } else if( cls.key_dest == key_console ) { @@ -730,6 +729,7 @@ void Key_ClearStates( void ) keys[i].down = 0; keys[i].repeats = 0; + keys[i].gamedown = 0; } if( clgame.hInstance ) diff --git a/engine/common/library.c b/engine/common/library.c index 67d67fad..26115d7c 100644 --- a/engine/common/library.c +++ b/engine/common/library.c @@ -187,7 +187,7 @@ static void PerformBaseRelocation( MEMORYMODULE *module, DWORD delta ) *patchAddrHL += delta; break; default: - MsgDev( D_ERROR, "PerformBaseRelocation: unknown relocation: %d\n", type ); + Con_Reportf( S_ERROR "PerformBaseRelocation: unknown relocation: %d\n", type ); break; } } @@ -272,7 +272,7 @@ static int BuildImportTable( MEMORYMODULE *module ) if( handle == NULL ) { - MsgDev( D_ERROR, "couldn't load library %s\n", libname ); + Con_Printf( S_ERROR "couldn't load library %s\n", libname ); result = 0; break; } @@ -294,20 +294,23 @@ static int BuildImportTable( MEMORYMODULE *module ) for( ; *thunkRef; thunkRef++, funcRef++ ) { + LPCSTR funcName; + if( IMAGE_SNAP_BY_ORDINAL( *thunkRef )) { - LPCSTR funcName = (LPCSTR)IMAGE_ORDINAL( *thunkRef ); + funcName = (LPCSTR)IMAGE_ORDINAL( *thunkRef ); *funcRef = (DWORD)COM_GetProcAddress( handle, funcName ); } else { PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)CALCULATE_ADDRESS( codeBase, *thunkRef ); - LPCSTR funcName = (LPCSTR)&thunkData->Name; + funcName = (LPCSTR)&thunkData->Name; *funcRef = (DWORD)COM_GetProcAddress( handle, funcName ); } if( *funcRef == 0 ) { + Con_Printf( S_ERROR "%s unable to find address: %s\n", libname, funcName ); result = 0; break; } @@ -470,7 +473,7 @@ library_error: // cleanup if( data ) Mem_Free( data ); MemoryFreeLibrary( result ); - MsgDev( D_ERROR, "LoadLibrary: %s\n", errorstring ); + Con_Printf( S_ERROR "LoadLibrary: %s\n", errorstring ); return NULL; } @@ -816,7 +819,7 @@ void *COM_GetProcAddress( void *hInstance, const char *name ) if( hInst->custom_loader ) return (void *)MemoryGetProcAddress( hInst->hInstance, name ); - return (void *)GetProcAddress( hInst->hInstance, GetMSVCName( name )); + return (void *)GetProcAddress( hInst->hInstance, name ); } void COM_FreeLibrary( void *hInstance ) @@ -829,10 +832,10 @@ void COM_FreeLibrary( void *hInstance ) if( host.status == HOST_CRASHED ) { // we need to hold down all modules, while MSVC can find error - MsgDev( D_NOTE, "Sys_FreeLibrary: hold %s for debugging\n", hInst->dllName ); + Con_Reportf( "Sys_FreeLibrary: hold %s for debugging\n", hInst->dllName ); return; } - else MsgDev( D_NOTE, "Sys_FreeLibrary: Unloading %s\n", hInst->dllName ); + else Con_Reportf( "Sys_FreeLibrary: Unloading %s\n", hInst->dllName ); if( hInst->custom_loader ) MemoryFreeLibrary( hInst->hInstance ); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 84e02d95..64dcaace 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -135,6 +135,7 @@ void RoundUpHullSize( vec3_t size ) value = size[i]; if( value < 0.0f ) negative = true; value = Q_ceil( fabs( value )); + result = Q_ceil( size[i] ); // lookup hull table to find nearest supposed value for( j = 0; j < NUM_HULL_ROUNDS; j++ ) @@ -321,6 +322,25 @@ void SinCos( float radians, float *sine, float *cosine ) } } +/* +============== +VectorCompareEpsilon + +============== +*/ +qboolean VectorCompareEpsilon( const vec3_t vec1, const vec3_t vec2, vec_t epsilon ) +{ + vec_t ax, ay, az; + + ax = fabs( vec1[0] - vec2[0] ); + ay = fabs( vec1[1] - vec2[1] ); + az = fabs( vec1[2] - vec2[2] ); + + if(( ax <= epsilon ) && ( ay <= epsilon ) && ( az <= epsilon )) + return true; + return false; +} + float VectorNormalizeLength2( const vec3_t v, vec3_t out ) { float length, ilength; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 598eadb5..2b898780 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -69,7 +69,7 @@ GNU General Public License for more details. #define Q_recip( a ) ((float)(1.0f / (float)(a))) #define Q_floor( a ) ((float)(long)(a)) #define Q_ceil( a ) ((float)(long)((a) + 1)) - +#define Q_round( x, y ) (floor( x / y + 0.5 ) * y ) #define Q_rint(x) ((x) < 0 ? ((int)((x)-0.5f)) : ((int)((x)+0.5f))) #define IS_NAN(x) (((*(int *)&x) & (255<<23)) == (255<<23)) @@ -131,6 +131,7 @@ int PlaneTypeForNormal( const vec3_t normal ); int NearestPOW( int value, qboolean roundDown ); void SinCos( float radians, float *sine, float *cosine ); float VectorNormalizeLength2( const vec3_t v, vec3_t out ); +qboolean VectorCompareEpsilon( const vec3_t vec1, const vec3_t vec2, vec_t epsilon ); void VectorVectors( const vec3_t forward, vec3_t right, vec3_t up ); void VectorAngles( const float *forward, float *angles ); void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up ); @@ -166,10 +167,12 @@ void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matri void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin ); void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale ); void Matrix3x4_TransformPositivePlane( const matrix3x4 in, const vec3_t normal, float d, vec3_t out, float *dist ); +void Matrix3x4_TransformAABB( const matrix3x4 world, const vec3_t mins, const vec3_t maxs, vec3_t absmin, vec3_t absmax ); void Matrix3x4_SetOrigin( matrix3x4 out, float x, float y, float z ); void Matrix3x4_Invert_Simple( matrix3x4 out, const matrix3x4 in1 ); void Matrix3x4_OriginFromMatrix( const matrix3x4 in, float *out ); void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out ); +void Matrix3x4_Transpose( matrix3x4 out, const matrix3x4 in1 ); #define Matrix4x4_LoadIdentity( mat ) Matrix4x4_Copy( mat, matrix4x4_identity ) #define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 )) diff --git a/engine/common/matrixlib.c b/engine/common/matrixlib.c index fdeea667..d656d53a 100644 --- a/engine/common/matrixlib.c +++ b/engine/common/matrixlib.c @@ -251,6 +251,47 @@ void Matrix3x4_Invert_Simple( matrix3x4 out, const matrix3x4 in1 ) out[2][3] = -(in1[0][3] * out[2][0] + in1[1][3] * out[2][1] + in1[2][3] * out[2][2]); } +void Matrix3x4_Transpose( matrix3x4 out, const matrix3x4 in1 ) +{ + // transpose only rotational component + out[0][0] = in1[0][0]; + out[0][1] = in1[1][0]; + out[0][2] = in1[2][0]; + out[1][0] = in1[0][1]; + out[1][1] = in1[1][1]; + out[1][2] = in1[2][1]; + out[2][0] = in1[0][2]; + out[2][1] = in1[1][2]; + out[2][2] = in1[2][2]; + + // copy origin + out[0][3] = in1[0][3]; + out[1][3] = in1[1][3]; + out[2][3] = in1[2][3]; +} + +/* +================== +Matrix3x4_TransformAABB +================== +*/ +void Matrix3x4_TransformAABB( const matrix3x4 world, const vec3_t mins, const vec3_t maxs, vec3_t absmin, vec3_t absmax ) +{ + vec3_t localCenter, localExtents; + vec3_t worldCenter, worldExtents; + + VectorAverage( mins, maxs, localCenter ); + VectorSubtract( maxs, localCenter, localExtents ); + + Matrix3x4_VectorTransform( world, localCenter, worldCenter ); + worldExtents[0] = DotProductAbs( localExtents, world[0] ); // auto-transposed! + worldExtents[1] = DotProductAbs( localExtents, world[1] ); + worldExtents[2] = DotProductAbs( localExtents, world[2] ); + + VectorSubtract( worldCenter, worldExtents, absmin ); + VectorAdd( worldCenter, worldExtents, absmax ); +} + const matrix4x4 matrix4x4_identity = { { 1, 0, 0, 0 }, // PITCH diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index 016bfb1e..c357f0bf 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -135,7 +135,6 @@ typedef struct int lightmap_samples; // samples per lightmap (1 or 3) int version; // model version qboolean isworld; - qboolean vis_errors; // don't spam about vis decompression errors } dbspmodel_t; typedef struct @@ -179,6 +178,7 @@ world_static_t world; static dbspmodel_t srcmodel; static loadstat_t loadstat; static model_t *worldmodel; +static byte g_visdata[(MAX_MAP_LEAFS+7)/8]; // intermediate buffer static mlumpstat_t worldstats[HEADER_LUMPS+EXTRA_LUMPS]; static mlumpinfo_t srclumps[HEADER_LUMPS] = { @@ -291,7 +291,7 @@ static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, { if( !FBitSet( flags, LUMP_SILENT )) { - MsgDev( D_WARN, "map ^2%s^7 has no %s\n", loadstat.name, msg1 ); + Con_DPrintf( S_WARN "map ^2%s^7 has no %s\n", loadstat.name, msg1 ); loadstat.numwarnings++; } } @@ -299,7 +299,7 @@ static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, { // it has the mincount and the lump is completely missed! if( !FBitSet( flags, LUMP_SILENT )) - MsgDev( D_ERROR, "map ^2%s^7 has no %s\n", loadstat.name, msg1 ); + Con_DPrintf( S_ERROR "map ^2%s^7 has no %s\n", loadstat.name, msg1 ); loadstat.numerrors++; } } @@ -309,7 +309,7 @@ static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, if( l->filelen % real_entrysize ) { if( !FBitSet( flags, LUMP_SILENT )) - MsgDev( D_ERROR, "Mod_Load%s: funny lump size\n", msg2 ); + Con_DPrintf( S_ERROR "Mod_Load%s: funny lump size\n", msg2 ); loadstat.numerrors++; return; } @@ -320,7 +320,7 @@ static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, { // it has the mincount and it's smaller than this limit if( !FBitSet( flags, LUMP_SILENT )) - MsgDev( D_ERROR, "map ^2%s^7 has no %s\n", loadstat.name, msg1 ); + Con_DPrintf( S_ERROR "map ^2%s^7 has no %s\n", loadstat.name, msg1 ); loadstat.numerrors++; return; } @@ -331,14 +331,14 @@ static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, if( FBitSet( info->flags, CHECK_OVERFLOW )) { if( !FBitSet( flags, LUMP_SILENT )) - MsgDev( D_ERROR, "map ^2%s^7 has too many %s\n", loadstat.name, msg1 ); + Con_DPrintf( S_ERROR "map ^2%s^7 has too many %s\n", loadstat.name, msg1 ); loadstat.numerrors++; return; } else if( !FBitSet( flags, LUMP_SILENT )) { // just throw warning - MsgDev( D_WARN, "map ^2%s^7 has too many %s\n", loadstat.name, msg1 ); + Con_DPrintf( S_WARN "map ^2%s^7 has too many %s\n", loadstat.name, msg1 ); loadstat.numwarnings++; } } @@ -449,62 +449,46 @@ void Mod_PrintWorldStats_f( void ) */ /* =================== -Mod_DecompressVis +Mod_DecompressPVS =================== */ -static void Mod_DecompressVis( dbspmodel_t *bmod, const byte *in, const byte *inend, byte *out, byte *outend ) +byte *Mod_DecompressPVS( const byte *in, int visbytes ) { - byte *outstart = out; + byte *out; int c; - while( out < outend ) - { - if( in == inend ) - { - if( !bmod->vis_errors ) - { - MsgDev( D_WARN, "Mod_DecompressVis: input underrun (decompressed %i of %i output bytes)\n", - (int)(out - outstart), (int)(outend - outstart)); - bmod->vis_errors = true; - } - return; - } + out = g_visdata; - c = *in++; - - if( c ) + if( !in ) + { + // no vis info, so make all visible + while( visbytes ) { - *out++ = c; - } - else - { - if( in == inend ) - { - if( !bmod->vis_errors ) - { - MsgDev( D_NOTE, "Mod_DecompressVis: input underrun (during zero-run) (decompressed %i of %i output bytes)\n", - (int)(out - outstart), (int)(outend - outstart)); - bmod->vis_errors = true; - } - return; - } - - for( c = *in++; c > 0; c-- ) - { - if( out == outend ) - { - if( !bmod->vis_errors ) - { - MsgDev( D_NOTE, "Mod_DecompressVis: output overrun (decompressed %i of %i output bytes)\n", - (int)(out - outstart), (int)(outend - outstart)); - bmod->vis_errors = true; - } - return; - } - *out++ = 0; - } + *out++ = 0xff; + visbytes--; } + return g_visdata; } + + do + { + if( *in ) + { + *out++ = *in++; + continue; + } + + c = in[1]; + in += 2; + + while( c ) + { + *out++ = 0; + c--; + } + } while( out - g_visdata < visbytes ); + + return g_visdata; } /* @@ -556,7 +540,7 @@ byte *Mod_GetPVSForPoint( const vec3_t p ) } if( leaf && leaf->cluster >= 0 ) - return world.visdata + leaf->cluster * world.visbytes; + return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes ); return NULL; } @@ -589,7 +573,7 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v // if this leaf is in a cluster, accumulate the vis bits if(((mleaf_t *)node)->cluster >= 0 ) { - byte *vis = world.visdata + ((mleaf_t *)node)->cluster * world.visbytes; + byte *vis = Mod_DecompressPVS( ((mleaf_t *)node)->compressed_vis, world.visbytes ); for( i = 0; i < visbytes; i++ ) visbuffer[i] |= vis[i]; @@ -615,7 +599,7 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q bytes = Q_min( bytes, visbytes ); // enable full visibility for some reasons - if( fullvis || !world.visclusters || !leaf || leaf->cluster < 0 ) + if( fullvis || !worldmodel->visdata || !leaf || leaf->cluster < 0 ) { memset( visbuffer, 0xFF, bytes ); return bytes; @@ -863,7 +847,7 @@ static qboolean Mod_CheckWaterAlphaSupport( dbspmodel_t *bmod ) { if(( leaf->contents == CONTENTS_WATER || leaf->contents == CONTENTS_SLIME ) && leaf->cluster >= 0 ) { - pvs = world.visdata + leaf->cluster * world.visbytes; + pvs = Mod_DecompressPVS( leaf->compressed_vis, world.visbytes ); for( j = 0; j < loadmodel->numleafs; j++ ) { @@ -1049,8 +1033,8 @@ static void Mod_CalcSurfaceExtents( msurface_t *surf ) info->lightextents[i] = surf->extents[i]; } - if( !FBitSet( tex->flags, TEX_SPECIAL ) && surf->extents[i] > 4096 ) - MsgDev( D_ERROR, "Bad surface extents %i\n", surf->extents[i] ); + if( !FBitSet( tex->flags, TEX_SPECIAL ) && ( surf->extents[i] > 16384 ) && ( tr.block_size == BLOCK_SIZE_DEFAULT )) + Con_Reportf( S_ERROR "Bad surface extents %i\n", surf->extents[i] ); } } @@ -1259,7 +1243,7 @@ static qboolean Mod_LoadColoredLighting( dbspmodel_t *bmod ) return false; if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg - MsgDev( D_WARN, "%s probably is out of date\n", path ); + Con_Printf( S_WARN "%s probably is out of date\n", path ); in = FS_LoadFile( path, &litdatasize, false ); @@ -1314,7 +1298,7 @@ static void Mod_LoadDeluxemap( dbspmodel_t *bmod ) return; if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg - MsgDev( D_WARN, "%s probably is out of date\n", path ); + Con_Printf( S_WARN "%s probably is out of date\n", path ); in = FS_LoadFile( path, &deluxdatasize, false ); @@ -1331,7 +1315,7 @@ static void Mod_LoadDeluxemap( dbspmodel_t *bmod ) if( deluxdatasize != bmod->lightdatasize ) { - MsgDev( D_ERROR, "%s has mismatched size (%i should be %i)\n", path, deluxdatasize, bmod->lightdatasize ); + Con_Reportf( S_ERROR "%s has mismatched size (%i should be %i)\n", path, deluxdatasize, bmod->lightdatasize ); Mem_Free( in ); return; } @@ -1828,11 +1812,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) mt = (mip_t *)((byte *)in + in->dataofs[i] ); if( !mt->name[0] ) - { - MsgDev( D_WARN, "unnamed texture in %s\n", loadstat.name ); Q_snprintf( mt->name, sizeof( mt->name ), "miptex_%i", i ); - } - tx = Mem_Calloc( loadmodel->mempool, sizeof( *tx )); loadmodel->textures[i] = tx; @@ -1915,7 +1895,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( !tx->gl_texturenum ) { if( host.type != HOST_DEDICATED ) - MsgDev( D_ERROR, "couldn't load %s.mip\n", mt->name ); + Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name ); tx->gl_texturenum = tr.defaultTexture; } @@ -1994,7 +1974,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) altanims[altmax] = tx; altmax++; } - else MsgDev( D_ERROR, "Mod_LoadTextures: bad animating texture %s\n", tx->name ); + else Con_Printf( S_ERROR "Mod_LoadTextures: bad animating texture %s\n", tx->name ); for( j = i + 1; j < loadmodel->numtextures; j++ ) { @@ -2022,7 +2002,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( num + 1 > altmax ) altmax = num + 1; } - else MsgDev( D_ERROR, "Mod_LoadTextures: bad animating texture %s\n", tx->name ); + else Con_Printf( S_ERROR "Mod_LoadTextures: bad animating texture %s\n", tx->name ); } // link them all together @@ -2032,7 +2012,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( !tx2 ) { - MsgDev( D_ERROR, "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name ); + Con_Printf( S_ERROR "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name ); tx->anim_total = 0; break; } @@ -2050,7 +2030,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod ) if( !tx2 ) { - MsgDev( D_ERROR, "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name ); + Con_Printf( S_ERROR "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name ); tx->anim_total = 0; break; } @@ -2100,11 +2080,7 @@ static void Mod_LoadTexInfo( dbspmodel_t *bmod ) miptex = in->miptex; if( miptex < 0 || miptex > loadmodel->numtextures ) - { - MsgDev( D_WARN, "Mod_LoadTexInfo: bad miptex number %i in '%s'\n", miptex, loadmodel->name ); - miptex = 0; - } - + miptex = 0; // this is possible? out->texture = loadmodel->textures[miptex]; out->flags = in->flags; @@ -2150,11 +2126,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod ) dface32_t *in = &bmod->surfaces32[i]; if(( in->firstedge + in->numedges ) > loadmodel->numsurfedges ) - { - MsgDev( D_ERROR, "bad surface %i from %i\n", i, bmod->numsurfaces ); - continue; - } - + continue; // corrupted level? out->firstedge = in->firstedge; out->numedges = in->numedges; if( in->side ) SetBits( out->flags, SURF_PLANEBACK ); @@ -2171,7 +2143,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod ) if(( in->firstedge + in->numedges ) > loadmodel->numsurfedges ) { - MsgDev( D_ERROR, "bad surface %i from %i\n", i, bmod->numsurfaces ); + Con_Reportf( S_ERROR "bad surface %i from %i\n", i, bmod->numsurfaces ); continue; } @@ -2189,15 +2161,15 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod ) tex = out->texinfo->texture; if( !Q_strncmp( tex->name, "sky", 3 )) - SetBits( out->flags, SURF_DRAWTILED|SURF_DRAWSKY ); + SetBits( out->flags, SURF_DRAWSKY ); if(( tex->name[0] == '*' && Q_stricmp( tex->name, "*default" )) || tex->name[0] == '!' ) - SetBits( out->flags, SURF_DRAWTURB|SURF_DRAWTILED ); + SetBits( out->flags, SURF_DRAWTURB ); if( !CL_IsQuakeCompatible( )) { if( !Q_strncmp( tex->name, "water", 5 ) || !Q_strnicmp( tex->name, "laser", 5 )) - SetBits( out->flags, SURF_DRAWTURB|SURF_DRAWTILED ); + SetBits( out->flags, SURF_DRAWTURB ); } if( !Q_strncmp( tex->name, "scroll", 6 )) @@ -2259,10 +2231,10 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod ) if( samples == 1 || samples == 3 ) { bmod->lightmap_samples = (int)samples; - MsgDev( D_REPORT, "lighting: %s\n", (bmod->lightmap_samples == 1) ? "monochrome" : "colored" ); + Con_Reportf( "lighting: %s\n", (bmod->lightmap_samples == 1) ? "monochrome" : "colored" ); bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero } - else MsgDev( D_WARN, "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples ); + else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples ); } } @@ -2340,20 +2312,16 @@ static void Mod_LoadLeafs( dbspmodel_t *bmod ) { mleaf_t *out; int i, j, p; + int visclusters = 0; loadmodel->leafs = out = (mleaf_t *)Mem_Calloc( loadmodel->mempool, bmod->numleafs * sizeof( *out )); loadmodel->numleafs = bmod->numleafs; if( bmod->isworld ) { - // get visleafs from the submodel data - world.visclusters = loadmodel->submodels[0].visleafs; - world.visbytes = (world.visclusters + 7) >> 3; - world.visdata = (byte *)Mem_Malloc( loadmodel->mempool, world.visclusters * world.visbytes ); - world.fatbytes = (world.visclusters + 31) >> 3; - - // enable full visibility as default - memset( world.visdata, 0xFF, world.visclusters * world.visbytes ); + visclusters = loadmodel->submodels[0].visleafs; + world.visbytes = (visclusters + 7) >> 3; + world.fatbytes = (visclusters + 31) >> 3; } for( i = 0; i < bmod->numleafs; i++, out++ ) @@ -2401,22 +2369,15 @@ static void Mod_LoadLeafs( dbspmodel_t *bmod ) { out->cluster = ( i - 1 ); // solid leaf 0 has no visdata - if( out->cluster >= world.visclusters ) + if( out->cluster >= visclusters ) out->cluster = -1; // ignore visofs errors on leaf 0 (solid) if( p >= 0 && out->cluster >= 0 && loadmodel->visdata ) { if( p < bmod->visdatasize ) - { - byte *inrow = loadmodel->visdata + p; - byte *inrowend = loadmodel->visdata + bmod->visdatasize; - byte *outrow = world.visdata + out->cluster * world.visbytes; - byte *outrowend = world.visdata + (out->cluster + 1) * world.visbytes; - - Mod_DecompressVis( bmod, inrow, inrowend, outrow, outrowend ); - } - else MsgDev( D_WARN, "Mod_LoadLeafs: invalid visofs for leaf #%i\n", i ); + out->compressed_vis = loadmodel->visdata + p; + else Con_Reportf( S_WARN "Mod_LoadLeafs: invalid visofs for leaf #%i\n", i ); } } else out->cluster = -1; // no visclusters on bmodels @@ -2510,7 +2471,7 @@ static void Mod_LoadLightVecs( dbspmodel_t *bmod ) if( bmod->deluxdatasize != bmod->lightdatasize ) { if( bmod->deluxdatasize > 0 ) - MsgDev( D_ERROR, "Mod_LoadLightVecs: has mismatched size (%i should be %i)\n", bmod->deluxdatasize, bmod->lightdatasize ); + Con_Printf( S_ERROR "Mod_LoadLightVecs: has mismatched size (%i should be %i)\n", bmod->deluxdatasize, bmod->lightdatasize ); else Mod_LoadDeluxemap( bmod ); // old method return; } @@ -2529,7 +2490,7 @@ static void Mod_LoadShadowmap( dbspmodel_t *bmod ) if( bmod->shadowdatasize != ( bmod->lightdatasize / 3 )) { if( bmod->shadowdatasize > 0 ) - MsgDev( D_ERROR, "Mod_LoadShadowmap: has mismatched size (%i should be %i)\n", bmod->shadowdatasize, bmod->lightdatasize / 3 ); + Con_Printf( S_ERROR "Mod_LoadShadowmap: has mismatched size (%i should be %i)\n", bmod->shadowdatasize, bmod->lightdatasize / 3 ); return; } @@ -2650,7 +2611,7 @@ qboolean Mod_LoadBmodelLumps( const byte *mod_base, qboolean isworld ) case QBSP2_VERSION: break; default: - MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", loadmodel->name, header->version, HLBSP_VERSION ); + Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", loadmodel->name, header->version, HLBSP_VERSION ); loadstat.numerrors++; return false; } @@ -2712,7 +2673,7 @@ qboolean Mod_LoadBmodelLumps( const byte *mod_base, qboolean isworld ) if( COM_CheckString( wadvalue )) { wadvalue[Q_strlen( wadvalue ) - 2] = '\0'; // kill the last semicolon - Con_DPrintf( "Wad files required to run the map: \"%s\"\n", wadvalue ); + Con_Reportf( "Wad files required to run the map: \"%s\"\n", wadvalue ); } return true; @@ -2754,7 +2715,7 @@ qboolean Mod_TestBmodelLumps( const char *name, const byte *mod_base, qboolean s default: // don't early out: let me analyze errors if( !FBitSet( flags, LUMP_SILENT )) - MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", name, header->version, HLBSP_VERSION ); + Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", name, header->version, HLBSP_VERSION ); loadstat.numerrors++; break; } diff --git a/engine/common/mod_dbghulls.c b/engine/common/mod_dbghulls.c index ffa96a1e..41d78e82 100644 --- a/engine/common/mod_dbghulls.c +++ b/engine/common/mod_dbghulls.c @@ -775,4 +775,4 @@ void R_DrawModelHull( void ) } pglEnable( GL_TEXTURE_2D ); pglDisable( GL_POLYGON_OFFSET_FILL ); -} +} \ No newline at end of file diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index ef2150ef..73f1768f 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -140,10 +140,8 @@ typedef struct int num_hull_models; // visibility info - byte *visdata; // uncompressed visdata size_t visbytes; // cluster size size_t fatbytes; // fatpvs size - int visclusters; // num visclusters // world bounds vec3_t mins; // real accuracy world bounds diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index 7414a86c..23b5a1bd 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -429,7 +429,7 @@ static void SV_StudioSetupBones( model_t *pModel, float frame, int sequence, con { // only show warn if sequence that out of range was specified intentionally if( sequence > mod_studiohdr->numseq ) - MsgDev( D_WARN, "SV_StudioSetupBones: sequence %i/%i out of range for model %s\n", sequence, mod_studiohdr->numseq, mod_studiohdr->name ); + Con_Reportf( S_WARN "SV_StudioSetupBones: sequence %i/%i out of range for model %s\n", sequence, mod_studiohdr->numseq, pModel->name ); sequence = 0; } @@ -783,7 +783,7 @@ studiohdr_t *R_StudioLoadHeader( model_t *mod, const void *buffer ) if( i != STUDIO_VERSION ) { - MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", mod->name, i, STUDIO_VERSION ); + Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, STUDIO_VERSION ); return NULL; } @@ -818,7 +818,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ) if( !thdr ) { - MsgDev( D_WARN, "Mod_LoadStudioModel: %s missing textures file\n", mod->name ); + Con_Printf( S_WARN "Mod_LoadStudioModel: %s missing textures file\n", mod->name ); if( buffer2 ) Mem_Free( buffer2 ); } else @@ -933,7 +933,7 @@ void Mod_InitStudioAPI( void ) pBlendIface = (STUDIOAPI)COM_GetProcAddress( svgame.hInstance, "Server_GetBlendingInterface" ); if( pBlendIface && pBlendIface( SV_BLENDING_INTERFACE_VERSION, &pBlendAPI, &gStudioAPI, &studio_transform, &studio_bones )) { - MsgDev( D_REPORT, "SV_LoadProgs: ^2initailized Server Blending interface ^7ver. %i\n", SV_BLENDING_INTERFACE_VERSION ); + Con_Reportf( "SV_LoadProgs: ^2initailized Server Blending interface ^7ver. %i\n", SV_BLENDING_INTERFACE_VERSION ); return; } diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 1d0a5346..64a8da95 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -705,7 +705,7 @@ void Netchan_CheckForCompletion( netchan_t *chan, int stream, int intotalbuffers { if( chan->sock == NS_CLIENT ) { - MsgDev( D_ERROR, "Lost/dropped fragment would cause stall, retrying connection\n" ); + Con_DPrintf( S_ERROR "Lost/dropped fragment would cause stall, retrying connection\n" ); Cbuf_AddText( "reconnect\n" ); } } @@ -714,10 +714,7 @@ void Netchan_CheckForCompletion( netchan_t *chan, int stream, int intotalbuffers // received final message if( c == intotalbuffers ) - { -// MsgDev( D_NOTE, "\n%s: incoming is complete %i bytes waiting\n", ns_strings[chan->sock], size ); chan->incomingready[stream] = true; - } } /* diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index d1d3550d..58cf59bf 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -317,7 +317,7 @@ delta_info_t *Delta_FindStruct( const char *name ) return &dt_info[i]; } - MsgDev( D_WARN, "Struct %s not found in delta_info\n", name ); + Con_DPrintf( S_WARN "Struct %s not found in delta_info\n", name ); // found nothing return NULL; @@ -427,7 +427,7 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags, { if( !Q_strcmp( pField->name, pName )) { - MsgDev( D_NOTE, "Delta_Add: %s->%s already existing\n", pStructName, pName ); + Con_Reportf( "Delta_Add: %s->%s already existing\n", pStructName, pName ); return false; // field already exist } } @@ -436,13 +436,13 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags, pFieldInfo = Delta_FindFieldInfo( dt->pInfo, pName ); if( !pFieldInfo ) { - MsgDev( D_ERROR, "Delta_Add: couldn't find description for %s->%s\n", pStructName, pName ); + Con_DPrintf( S_ERROR "Delta_Add: couldn't find description for %s->%s\n", pStructName, pName ); return false; } if( dt->numFields + 1 > dt->maxFields ) { - MsgDev( D_WARN, "Delta_Add: can't add %s->%s encoder list is full\n", pStructName, pName ); + Con_DPrintf( S_WARN "Delta_Add: can't add %s->%s encoder list is full\n", pStructName, pName ); return false; // too many fields specified (duplicated ?) } @@ -543,28 +543,28 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt *delta_script = COM_ParseFile( *delta_script, token ); if( Q_strcmp( token, "(" )) { - MsgDev( D_ERROR, "Delta_ParseField: expected '(', found '%s' instead\n", token ); + Con_DPrintf( S_ERROR "Delta_ParseField: expected '(', found '%s' instead\n", token ); return false; } // read the variable name if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) { - MsgDev( D_ERROR, "Delta_ParseField: missing field name\n" ); + Con_DPrintf( S_ERROR "Delta_ParseField: missing field name\n" ); return false; } pFieldInfo = Delta_FindFieldInfo( pInfo, token ); if( !pFieldInfo ) { - MsgDev( D_ERROR, "Delta_ParseField: unable to find field %s\n", token ); + Con_DPrintf( S_ERROR "Delta_ParseField: unable to find field %s\n", token ); return false; } *delta_script = COM_ParseFile( *delta_script, token ); if( Q_strcmp( token, "," )) { - MsgDev( D_ERROR, "Delta_ParseField: expected ',', found '%s' instead\n", token ); + Con_DPrintf( S_ERROR "Delta_ParseField: expected ',', found '%s' instead\n", token ); return false; } @@ -605,7 +605,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt if( Q_strcmp( token, "," )) { - MsgDev( D_ERROR, "Delta_ParseField: expected ',', found '%s' instead\n", token ); + Con_DPrintf( S_ERROR "Delta_ParseField: expected ',', found '%s' instead\n", token ); return false; } @@ -613,7 +613,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) { - MsgDev( D_ERROR, "Delta_ReadField: %s field bits argument is missing\n", pField->name ); + Con_DPrintf( S_ERROR "Delta_ReadField: %s field bits argument is missing\n", pField->name ); return false; } @@ -622,14 +622,14 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt *delta_script = COM_ParseFile( *delta_script, token ); if( Q_strcmp( token, "," )) { - MsgDev( D_ERROR, "Delta_ReadField: expected ',', found '%s' instead\n", token ); + Con_DPrintf( S_ERROR "Delta_ReadField: expected ',', found '%s' instead\n", token ); return false; } // read delta-multiplier if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) { - MsgDev( D_ERROR, "Delta_ReadField: %s missing 'multiplier' argument\n", pField->name ); + Con_DPrintf( S_ERROR "Delta_ReadField: %s missing 'multiplier' argument\n", pField->name ); return false; } @@ -640,14 +640,14 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt *delta_script = COM_ParseFile( *delta_script, token ); if( Q_strcmp( token, "," )) { - MsgDev( D_ERROR, "Delta_ReadField: expected ',', found '%s' instead\n", token ); + Con_DPrintf( S_ERROR "Delta_ReadField: expected ',', found '%s' instead\n", token ); return false; } // read delta-postmultiplier if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) { - MsgDev( D_ERROR, "Delta_ReadField: %s missing 'post_multiply' argument\n", pField->name ); + Con_DPrintf( S_ERROR "Delta_ReadField: %s missing 'post_multiply' argument\n", pField->name ); return false; } @@ -663,7 +663,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt *delta_script = COM_ParseFile( *delta_script, token ); if( Q_strcmp( token, ")" )) { - MsgDev( D_ERROR, "Delta_ParseField: expected ')', found '%s' instead\n", token ); + Con_DPrintf( S_ERROR "Delta_ParseField: expected ')', found '%s' instead\n", token ); return false; } @@ -1911,13 +1911,13 @@ void Delta_AddEncoder( char *name, pfnDeltaEncode encodeFunc ) if( !dt || !dt->bInitialized ) { - MsgDev( D_ERROR, "Delta_AddEncoder: couldn't find delta with specified custom encode %s\n", name ); + Con_DPrintf( S_ERROR "Delta_AddEncoder: couldn't find delta with specified custom encode %s\n", name ); return; } if( dt->customEncode == CUSTOM_NONE ) { - MsgDev( D_ERROR, "Delta_AddEncoder: %s not supposed for custom encoding\n", dt->pName ); + Con_DPrintf( S_ERROR "Delta_AddEncoder: %s not supposed for custom encoding\n", dt->pName ); return; } diff --git a/engine/common/netchan.h b/engine/common/netchan.h index 6805ea45..7fed5438 100644 --- a/engine/common/netchan.h +++ b/engine/common/netchan.h @@ -69,6 +69,7 @@ GNU General Public License for more details. #define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 ) #define MASTERSERVER_ADR "ms.xash.su:27010" +#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" #define PORT_MASTER 27010 #define PORT_CLIENT 27005 #define PORT_SERVER 27015 diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 41fe15ef..742d065e 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -73,7 +73,7 @@ GNU General Public License for more details. #define svc_director 51 // #define svc_voiceinit 52 // #define svc_voicedata 53 // [byte][short][...] -// reserved +#define svc_deltapacketbones 54 // [short][byte][...] // reserved #define svc_resourcelocation 56 // [string] #define svc_querycvarvalue 57 // [string] diff --git a/engine/common/soundlib/snd_main.c b/engine/common/soundlib/snd_main.c index 415fd7f0..703905b4 100644 --- a/engine/common/soundlib/snd_main.c +++ b/engine/common/soundlib/snd_main.c @@ -117,10 +117,8 @@ load_internal: } } - if( !sound.loadformats || sound.loadformats->ext == NULL ) - MsgDev( D_NOTE, "FS_LoadSound: soundlib offline\n" ); - else if( filename[0] != '#' ) - MsgDev( D_WARN, "FS_LoadSound: couldn't load \"%s\"\n", loadname ); + if( filename[0] != '#' ) + Con_Reportf( S_WARN "FS_LoadSound: couldn't load \"%s\"\n", loadname ); return NULL; } @@ -134,12 +132,9 @@ free WAV buffer */ void FS_FreeSound( wavdata_t *pack ) { - if( pack ) - { - if( pack->buffer ) Mem_Free( pack->buffer ); - Mem_Free( pack ); - } - else MsgDev( D_WARN, "FS_FreeSound: trying to free NULL sound\n" ); + if( !pack ) return; + if( pack->buffer ) Mem_Free( pack->buffer ); + Mem_Free( pack ); } /* @@ -189,9 +184,7 @@ stream_t *FS_OpenStream( const char *filename ) } } - if( !sound.streamformat || sound.streamformat->ext == NULL ) - MsgDev( D_NOTE, "FS_OpenStream: soundlib offline\n" ); - else MsgDev( D_NOTE, "FS_OpenStream: couldn't open \"%s\"\n", loadname ); + Con_Reportf( "FS_OpenStream: couldn't open \"%s\"\n", loadname ); return NULL; } diff --git a/engine/common/soundlib/snd_mp3.c b/engine/common/soundlib/snd_mp3.c index 66d2780f..bc2acbdc 100644 --- a/engine/common/soundlib/snd_mp3.c +++ b/engine/common/soundlib/snd_mp3.c @@ -131,7 +131,7 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) else size = outsize; memcpy( &sound.wav[bytesWrite], out, size ); - bytesWrite += outsize; + bytesWrite += size; } sound.samples = bytesWrite / ( sound.width * sound.channels ); diff --git a/engine/common/soundlib/snd_utils.c b/engine/common/soundlib/snd_utils.c index 8add19be..daef860a 100644 --- a/engine/common/soundlib/snd_utils.c +++ b/engine/common/soundlib/snd_utils.c @@ -200,7 +200,7 @@ qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int out } } - MsgDev( D_NOTE, "Sound_Resample: from[%d bit %d kHz] to [%d bit %d kHz]\n", inwidth * 8, inrate, outwidth * 8, outrate ); + Con_Reportf( "Sound_Resample: from[%d bit %d kHz] to [%d bit %d kHz]\n", inwidth * 8, inrate, outwidth * 8, outrate ); } sc->rate = outrate; @@ -216,10 +216,7 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags ) // check for buffers if( !snd || !snd->buffer ) - { - MsgDev( D_WARN, "Sound_Process: NULL sound\n" ); return false; - } if(( flags & SOUND_RESAMPLE ) && ( width > 0 || rate > 0 )) { diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index 8488f97a..79ff1465 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -290,7 +290,7 @@ void Con_CreateConsole( void ) rect.top = 0; rect.bottom = 364; Q_strncpy( FontName, "Fixedsys", sizeof( FontName )); - Q_strncpy( s_wcd.title, va( "Xash3D %g", XASH_VERSION ), sizeof( s_wcd.title )); + Q_strncpy( s_wcd.title, va( "Xash3D %s", XASH_VERSION ), sizeof( s_wcd.title )); Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path )); fontsize = 8; } @@ -312,7 +312,7 @@ void Con_CreateConsole( void ) if( !RegisterClass( &wc )) { // print into log - MsgDev( D_ERROR, "Can't register window class '%s'\n", SYSCONSOLE ); + Con_DPrintf( S_ERROR "Can't register window class '%s'\n", SYSCONSOLE ); return; } @@ -329,7 +329,7 @@ void Con_CreateConsole( void ) s_wcd.hWnd = CreateWindowEx( WS_EX_DLGMODALFRAME, SYSCONSOLE, s_wcd.title, DEDSTYLE, ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1, NULL, NULL, host.hInst, NULL ); if( s_wcd.hWnd == NULL ) { - MsgDev( D_ERROR, "Can't create window '%s'\n", s_wcd.title ); + Con_DPrintf( S_ERROR "Can't create window '%s'\n", s_wcd.title ); return; } @@ -399,7 +399,7 @@ destroy win32 console void Con_DestroyConsole( void ) { // last text message into console or log - MsgDev( D_NOTE, "Sys_FreeLibrary: Unloading xash.dll\n" ); + Con_Reportf( "Sys_FreeLibrary: Unloading xash.dll\n" ); Sys_CloseLog(); @@ -486,7 +486,12 @@ void Sys_InitLog( void ) if( s_wcd.log_active ) { s_wcd.logfile = fopen( s_wcd.log_path, mode ); - if( !s_wcd.logfile ) MsgDev( D_ERROR, "Sys_InitLog: can't create log file %s\n", s_wcd.log_path ); + + if( !s_wcd.logfile ) + { + MSGBOX( va( "can't create log file %s\n", s_wcd.log_path )); + return; + } fprintf( s_wcd.logfile, "=================================================================================\n" ); fprintf( s_wcd.logfile, "\t%s (build %i) started at %s\n", s_wcd.title, Q_buildnum(), Q_timestamp( TIME_FULL )); diff --git a/engine/common/sys_win.c b/engine/common/sys_win.c index 775baf6d..c476ae6e 100644 --- a/engine/common/sys_win.c +++ b/engine/common/sys_win.c @@ -98,7 +98,7 @@ void Sys_SetClipboardData( const byte *buffer, size_t size ) if( SetClipboardData( CF_DIB, hResult ) == NULL ) { - MsgDev( D_ERROR, "unable to write screenshot\n" ); + Con_Printf( S_ERROR "unable to write screenshot\n" ); GlobalFree( hResult ); } CloseClipboard(); @@ -371,7 +371,7 @@ qboolean Sys_LoadLibrary( dll_info_t *dll ) if( !dll->name || !*dll->name ) return false; // nothing to load - MsgDev( D_NOTE, "Sys_LoadLibrary: Loading %s", dll->name ); + Con_Reportf( "Sys_LoadLibrary: Loading %s", dll->name ); if( dll->fcts ) { @@ -398,14 +398,14 @@ qboolean Sys_LoadLibrary( dll_info_t *dll ) goto error; } } - MsgDev( D_NOTE, " - ok\n" ); + Con_Reportf( " - ok\n" ); return true; error: - MsgDev( D_NOTE, " - failed\n" ); + Con_Reportf( " - failed\n" ); Sys_FreeLibrary( dll ); // trying to free if( dll->crash ) Sys_Error( errorstring ); - else MsgDev( D_ERROR, errorstring ); + else Con_DPrintf( "%s%s", S_ERROR, errorstring ); return false; } @@ -427,10 +427,10 @@ qboolean Sys_FreeLibrary( dll_info_t *dll ) if( host.status == HOST_CRASHED ) { // we need to hold down all modules, while MSVC can find error - MsgDev( D_NOTE, "Sys_FreeLibrary: hold %s for debugging\n", dll->name ); + Con_Reportf( "Sys_FreeLibrary: hold %s for debugging\n", dll->name ); return false; } - else MsgDev( D_NOTE, "Sys_FreeLibrary: Unloading %s\n", dll->name ); + else Con_Reportf( "Sys_FreeLibrary: Unloading %s\n", dll->name ); FreeLibrary( dll->link ); dll->link = NULL; diff --git a/engine/common/titles.c b/engine/common/titles.c index 8d77b9ee..23b55fcb 100644 --- a/engine/common/titles.c +++ b/engine/common/titles.c @@ -201,7 +201,7 @@ static int ParseDirective( const char *pText ) } else { - MsgDev( D_ERROR, "unknown token: %s\n", pText ); + Con_DPrintf( S_ERROR "unknown token: %s\n", pText ); } return 1; } @@ -249,7 +249,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize ) if( IsEndOfText( trim )) { - MsgDev( D_ERROR, "TextMessage: unexpected '}' found, line %d\n", lineNumber ); + Con_Reportf( "TextMessage: unexpected '}' found, line %d\n", lineNumber ); return; } Q_strcpy( currentName, trim ); @@ -260,9 +260,9 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize ) int length = Q_strlen( currentName ); // save name on name heap - if( lastNamePos + length > 16384 ) + if( lastNamePos + length > 32768 ) { - MsgDev( D_ERROR, "TextMessage: error while parsing!\n" ); + Con_Reportf( "TextMessage: error while parsing!\n" ); return; } @@ -285,7 +285,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize ) } if( IsStartOfText( trim )) { - MsgDev( D_ERROR, "TextMessage: unexpected '{' found, line %d\n", lineNumber ); + Con_Reportf( "TextMessage: unexpected '{' found, line %d\n", lineNumber ); return; } break; @@ -296,12 +296,12 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize ) if( messageCount >= MAX_MESSAGES ) { - MsgDev( D_WARN, "Too many messages in titles.txt, max is %d\n", MAX_MESSAGES ); + Con_Printf( S_WARN "Too many messages in titles.txt, max is %d\n", MAX_MESSAGES ); break; } } - MsgDev( D_NOTE, "TextMessage: parsed %d text messages\n", messageCount ); + Con_Reportf( "TextMessage: parsed %d text messages\n", messageCount ); nameHeapSize = lastNamePos; textHeapSize = 0; @@ -339,7 +339,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize ) } if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize )) - MsgDev( D_ERROR, "TextMessage: overflow text message buffer!\n" ); + Con_DPrintf( S_ERROR "TextMessage: overflow text message buffer!\n" ); clgame.numTitles = messageCount; } \ No newline at end of file diff --git a/engine/common/world.c b/engine/common/world.c index 2178b957..7ec87b45 100644 --- a/engine/common/world.c +++ b/engine/common/world.c @@ -158,7 +158,6 @@ void World_TransformAABB( matrix4x4 transform, const vec3_t mins, const vec3_t m { if( outmins[i] > outmaxs[i] ) { - MsgDev( D_ERROR, "World_TransformAABB: backwards mins/maxs\n" ); VectorClear( outmins ); VectorClear( outmaxs ); return; diff --git a/engine/common/world.h b/engine/common/world.h index b9e2819e..d5057da3 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -20,10 +20,6 @@ GNU General Public License for more details. #define MOVE_NOMONSTERS 1 // ignore monsters (edicts with flags (FL_MONSTER|FL_FAKECLIENT|FL_CLIENT) set) #define MOVE_MISSILE 2 // extra size for monsters -#define FMOVE_IGNORE_GLASS 0x100 -#define FMOVE_SIMPLEBOX 0x200 -#define FMOVE_MONSTERCLIP 0x400 - #define CONTENTS_NONE 0 // no custom contents specified /* diff --git a/engine/physint.h b/engine/physint.h index 654c09fe..c2538950 100644 --- a/engine/physint.h +++ b/engine/physint.h @@ -140,7 +140,7 @@ typedef struct physics_interface_s // called at end the frame of SV_Physics call void ( *SV_EndFrame )( void ); // obsolete - void (*pfnReserved)( void ); + void (*pfnPrepWorldFrame)( void ); // called through save\restore process void (*pfnCreateEntitiesInRestoreList)( SAVERESTOREDATA *pSaveData, int levelMask, qboolean create_world ); // allocate custom string (e.g. using user implementation of stringtable, not engine strings) diff --git a/engine/server/server.h b/engine/server/server.h index 735021f1..ac19976b 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -387,6 +387,7 @@ extern convar_t sv_unlagpush; extern convar_t sv_unlagsamples; extern convar_t rcon_password; extern convar_t sv_instancedbaseline; +extern convar_t sv_background_freeze; extern convar_t sv_minupdaterate; extern convar_t sv_maxupdaterate; extern convar_t sv_downloadurl; diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index f305c8b2..38861d85 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -116,7 +116,7 @@ void SV_RejectConnection( netadr_t from, char *fmt, ... ) Q_vsnprintf( text, sizeof( text ), fmt, argptr ); va_end( argptr ); - MsgDev( D_REPORT, "%s connection refused. Reason: %s\n", NET_AdrToString( from ), text ); + Con_Reportf( "%s connection refused. Reason: %s\n", NET_AdrToString( from ), text ); Netchan_OutOfBandPrint( NS_SERVER, from, "print\n^1Server was reject the connection:^7 %s", text ); Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" ); } @@ -858,7 +858,7 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg ) char remaining[1024]; int i; - MsgDev( D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString( from ), MSG_GetData( msg ) + 4 ); + Con_Printf( "Rcon from %s:\n%s\n", NET_AdrToString( from ), MSG_GetData( msg ) + 4 ); Log_Printf( "Rcon: \"%s\" from \"%s\"\n", MSG_GetData( msg ) + 4, NET_AdrToString( from )); SV_BeginRedirect( from, RD_PACKET, outputbuf, sizeof( outputbuf ) - 16, SV_FlushRedirect ); @@ -872,7 +872,7 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg ) } Cmd_ExecuteString( remaining ); } - else MsgDev( D_ERROR, "Bad rcon_password.\n" ); + else Con_Printf( S_ERROR "Bad rcon_password.\n" ); SV_EndRedirect(); } @@ -1241,10 +1241,11 @@ void SV_PutClientInServer( sv_client_t *cl ) } } +#ifdef HACKS_RELATED_HLMODS // enable dev-mode to prevent crash cheat-protecting from Invasion mod if( FBitSet( ent->v.flags, FL_GODMODE|FL_NOTARGET ) && !Q_stricmp( GI->gamefolder, "invasion" )) SV_ExecuteClientCommand( cl, "test\n" ); - +#endif // refresh the userinfo and movevars // NOTE: because movevars can be changed during the connection process SetBits( cl->flags, FCL_RESEND_USERINFO|FCL_RESEND_MOVEVARS ); @@ -1965,7 +1966,7 @@ void SV_ExecuteClientCommand( sv_client_t *cl, char *s ) { if( !u->func( cl )) Con_Printf( "'%s' is not valid from the console\n", u->name ); - else MsgDev( D_NOTE, "ucmd->%s()\n", u->name ); + else Con_Reportf( "ucmd->%s()\n", u->name ); break; } } @@ -2095,7 +2096,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) // user out of band message (must be handled in CL_ConnectionlessPacket) if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, buf ); } - else MsgDev( D_ERROR, "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); + else Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); } /* @@ -2139,7 +2140,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg ) if( totalcmds < 0 || totalcmds >= CMD_MASK ) { - MsgDev( D_ERROR, "SV_ParseClientMove: %s sending too many commands %i\n", cl->name, totalcmds ); + Con_Reportf( S_ERROR "SV_ParseClientMove: %s sending too many commands %i\n", cl->name, totalcmds ); SV_DropClient( cl, false ); return; } @@ -2162,12 +2163,16 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg ) if( checksum2 != checksum1 ) { - MsgDev( D_ERROR, "SV_UserMove: failed command checksum for %s (%d != %d)\n", cl->name, checksum2, checksum1 ); + Con_Reportf( S_ERROR "SV_UserMove: failed command checksum for %s (%d != %d)\n", cl->name, checksum2, checksum1 ); return; } cl->packet_loss = packet_loss; + // freeze player for some reasons if loadgame was executed + if( GameState->loadGame ) + return; + // check for pause or frozen if( sv.paused || !CL_IsInGame() || SV_PlayerIsFrozen( player )) { @@ -2274,13 +2279,12 @@ void SV_ParseResourceList( sv_client_t *cl, sizebuf_t *msg ) SV_AddToResourceList( resource, &cl->resourcesneeded ); } - if( sv_allow_upload.value ) - MsgDev( D_REPORT, "Verifying and uploading resources...\n" ); - totalsize = COM_SizeofResourceList( &cl->resourcesneeded, &ri ); if( totalsize != 0 && sv_allow_upload.value ) { + Con_DPrintf( "Verifying and uploading resources...\n" ); + if( totalsize != 0 ) { Con_DPrintf( "Custom resources total %.2fK\n", totalsize / 1024.0 ); @@ -2314,7 +2318,7 @@ void SV_ParseResourceList( sv_client_t *cl, sizebuf_t *msg ) SV_ClearResourceList( &cl->resourcesonhand ); return; } - MsgDev( D_REPORT, "resources to request: %s\n", Q_memprint( totalsize )); + Con_DPrintf( "resources to request: %s\n", Q_memprint( totalsize )); } cl->upstate = us_processing; @@ -2334,7 +2338,7 @@ void SV_ParseCvarValue( sv_client_t *cl, sizebuf_t *msg ) if( svgame.dllFuncs2.pfnCvarValue != NULL ) svgame.dllFuncs2.pfnCvarValue( cl->edict, value ); - MsgDev( D_REPORT, "Cvar query response: name:%s, value:%s\n", cl->name, value ); + Con_Reportf( "Cvar query response: name:%s, value:%s\n", cl->name, value ); } /* @@ -2354,7 +2358,7 @@ void SV_ParseCvarValue2( sv_client_t *cl, sizebuf_t *msg ) if( svgame.dllFuncs2.pfnCvarValue2 != NULL ) svgame.dllFuncs2.pfnCvarValue2( cl->edict, requestID, name, value ); - MsgDev( D_REPORT, "Cvar query response: name:%s, request ID %d, cvar:%s, value:%s\n", cl->name, requestID, name, value ); + Con_Reportf( "Cvar query response: name:%s, request ID %d, cvar:%s, value:%s\n", cl->name, requestID, name, value ); } /* @@ -2368,7 +2372,6 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg ) { qboolean move_issued = false; client_frame_t *frame; - char *s; int c; ASSERT( cl->frames != NULL ); @@ -2394,7 +2397,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg ) { if( MSG_CheckOverflow( msg )) { - MsgDev( D_ERROR, "SV_ReadClientMessage: clc_bad\n" ); + Con_DPrintf( S_ERROR "incoming overflow for %s\n", cl->name ); SV_DropClient( cl, false ); return; } @@ -2418,10 +2421,9 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg ) SV_ParseClientMove( cl, msg ); break; case clc_stringcmd: - s = MSG_ReadString( msg ); - // malicious users may try using too many string commands - SV_ExecuteClientCommand( cl, s ); - if( cl->state == cs_zombie ) return; // disconnect command + SV_ExecuteClientCommand( cl, MSG_ReadString( msg )); + if( cl->state == cs_zombie ) + return; // disconnect command break; case clc_resourcelist: SV_ParseResourceList( cl, msg ); @@ -2436,7 +2438,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg ) SV_ParseCvarValue2( cl, msg ); break; default: - MsgDev( D_ERROR, "clc_bad\n" ); + Con_DPrintf( S_ERROR "%s: clc_bad\n", cl->name ); SV_DropClient( cl, false ); return; } diff --git a/engine/server/sv_cmds.c b/engine/server/sv_cmds.c index 692fe5f1..ea704538 100644 --- a/engine/server/sv_cmds.c +++ b/engine/server/sv_cmds.c @@ -248,7 +248,8 @@ void SV_MapBackground_f( void ) if( SV_Active() && !sv.background ) { - MsgDev( D_ERROR, "can't set background map while game is active\n" ); + if( GameState->nextstate == STATE_RUNFRAME ) + Con_Printf( S_ERROR "can't set background map while game is active\n" ); return; } diff --git a/engine/server/sv_custom.c b/engine/server/sv_custom.c index e0fb73c3..4da79d95 100644 --- a/engine/server/sv_custom.c +++ b/engine/server/sv_custom.c @@ -313,7 +313,7 @@ void SV_MoveToOnHandList( sv_client_t *cl, resource_t *pResource ) { if( !pResource ) { - MsgDev( D_REPORT, "Null resource passed to SV_MoveToOnHandList\n" ); + Con_Reportf( "Null resource passed to SV_MoveToOnHandList\n" ); return; } @@ -325,7 +325,7 @@ void SV_AddToResourceList( resource_t *pResource, resource_t *pList ) { if( pResource->pPrev != NULL || pResource->pNext != NULL ) { - MsgDev( D_ERROR, "Resource already linked\n" ); + Con_Reportf( S_ERROR "Resource already linked\n" ); return; } @@ -524,7 +524,7 @@ void SV_BatchUploadRequest( sv_client_t *cl ) } else { - MsgDev( D_ERROR, "Non customization in upload queue!\n" ); + Con_Reportf( S_ERROR "Non customization in upload queue!\n" ); SV_MoveToOnHandList( cl, p ); } } diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index e87e5ab0..98e19aac 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -138,7 +138,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_ } // if we are full, silently discard entities - if( ents->num_entities < MAX_VISIBLE_PACKET ) + if( ents->num_entities < ( MAX_VISIBLE_PACKET - 1 )) { ents->num_entities++; // entity accepted c_fullsend++; // debug counter @@ -729,7 +729,7 @@ void SV_SendClientDatagram( sv_client_t *cl ) { if( MSG_GetNumBytesWritten( &cl->datagram ) < MSG_GetNumBytesLeft( &msg )) MSG_WriteBits( &msg, MSG_GetData( &cl->datagram ), MSG_GetNumBitsWritten( &cl->datagram )); - else MsgDev( D_WARN, "Ignoring unreliable datagram for %s, would overflow on msg\n", cl->name ); + else Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow on msg\n", cl->name ); } MSG_Clear( &cl->datagram ); @@ -791,14 +791,14 @@ void SV_UpdateToReliableMessages( void ) // clear the server datagram if it overflowed. if( MSG_CheckOverflow( &sv.datagram )) { - MsgDev( D_ERROR, "sv.datagram overflowed!\n" ); + Con_DPrintf( S_ERROR "sv.datagram overflowed!\n" ); MSG_Clear( &sv.datagram ); } // clear the server datagram if it overflowed. if( MSG_CheckOverflow( &sv.spec_datagram )) { - MsgDev( D_ERROR, "sv.spec_datagram overflowed!\n" ); + Con_DPrintf( S_ERROR "sv.spec_datagram overflowed!\n" ); MSG_Clear( &sv.spec_datagram ); } @@ -823,7 +823,7 @@ void SV_UpdateToReliableMessages( void ) } else { - MsgDev( D_WARN, "Ignoring unreliable datagram for %s, would overflow\n", cl->name ); + Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name ); } if( FBitSet( cl->flags, FCL_HLTV_PROXY )) @@ -834,7 +834,7 @@ void SV_UpdateToReliableMessages( void ) } else { - MsgDev( D_WARN, "Ignoring spectator datagram for %s, would overflow\n", cl->name ); + Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name ); } } } @@ -889,7 +889,7 @@ void SV_SendClientMessages( void ) MSG_Clear( &cl->netchan.message ); MSG_Clear( &cl->datagram ); SV_BroadcastPrintf( NULL, "%s overflowed\n", cl->name ); - MsgDev( D_WARN, "reliable overflow for %s\n", cl->name ); + Con_DPrintf( S_ERROR "reliable overflow for %s\n", cl->name ); SV_DropClient( cl, false ); SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); cl->netchan.cleartime = 0.0; // don't choke this message @@ -1006,6 +1006,12 @@ void SV_InactivateClients( void ) COM_ClearCustomizationList( &cl->customdata, false ); memset( cl->physinfo, 0, MAX_PHYSINFO_STRING ); + + // NOTE: many mods sending messages that must be applied on a next level + // e.g. CryOfFear sending HideHud and PlayMp3 that affected after map change + if( svgame.globals->changelevel ) + continue; + MSG_Clear( &cl->netchan.message ); MSG_Clear( &cl->datagram ); } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index c15374ad..d5fe83e6 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -1194,24 +1194,29 @@ pfnSetModel */ void pfnSetModel( edict_t *e, const char *m ) { + char name[MAX_QPATH]; model_t *mod; int i; if( !SV_IsValidEdict( e )) return; - if( COM_CheckString( m )) + if( *m == '\\' || *m == '/' ) m++; + Q_strncpy( name, m, sizeof( name )); + COM_FixSlashes( name ); + + if( COM_CheckString( name )) { // check to see if model was properly precached for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ ) { - if( !Q_stricmp( sv.model_precache[i], m )) + if( !Q_stricmp( sv.model_precache[i], name )) break; } if( i == MAX_MODELS ) { - Con_Printf( S_ERROR "no precache: %s\n", m ); + Con_Printf( S_ERROR "no precache: %s\n", name ); return; } } @@ -1223,7 +1228,7 @@ void pfnSetModel( edict_t *e, const char *m ) return; } - if( COM_CheckString( m )) + if( COM_CheckString( name )) { e->v.model = MAKE_STRING( sv.model_precache[i] ); e->v.modelindex = i; @@ -1250,18 +1255,23 @@ pfnModelIndex */ int pfnModelIndex( const char *m ) { + char name[MAX_QPATH]; int i; if( !COM_CheckString( m )) return 0; + if( *m == '\\' || *m == '/' ) m++; + Q_strncpy( name, m, sizeof( name )); + COM_FixSlashes( name ); + for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ ) { - if( !Q_stricmp( sv.model_precache[i], m )) + if( !Q_stricmp( sv.model_precache[i], name )) return i; } - Con_Printf( S_ERROR "no precache: %s\n", m ); + Con_Printf( S_ERROR "no precache: %s\n", name ); return 0; } @@ -3421,10 +3431,7 @@ void pfnFadeClientVolume( const edict_t *pEdict, int fadePercent, int fadeOutSec sv_client_t *cl; if(( cl = SV_ClientFromEdict( pEdict, true )) == NULL ) - { - MsgDev( D_ERROR, "SV_FadeClientVolume: client is not spawned!\n" ); return; - } if( FBitSet( cl->flags, FCL_FAKECLIENT )) return; @@ -4575,7 +4582,7 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent ) COM_ParseVector( &pstart, origin, 3 ); Mem_Free( pkvd[i].szValue ); // release old value, so we don't need these - copystring( va( "%g %g %g", origin[0], origin[1], origin[2] - 16.0f )); + pkvd[i].szValue = copystring( va( "%g %g %g", origin[0], origin[1], origin[2] - 16.0f )); } #endif if( !Q_strcmp( pkvd[i].szKeyName, "light" )) diff --git a/engine/server/sv_log.c b/engine/server/sv_log.c index fa02154a..f2dcc1db 100644 --- a/engine/server/sv_log.c +++ b/engine/server/sv_log.c @@ -73,7 +73,7 @@ void Log_Open( void ) } if( fp ) svs.log.file = fp; - Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/%.2f/%d\")\n", + Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/%s/%d\")\n", szTestFile, Info_ValueForKey( SV_Serverinfo(), "*gamedir" ), PROTOCOL_VERSION, XASH_VERSION, Q_buildnum() ); } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index f70ba8c2..b8831156 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -92,6 +92,7 @@ CVAR_DEFINE_AUTO( sv_skyvec_x, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skylight dir CVAR_DEFINE_AUTO( sv_skyvec_y, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skylight direction by y-axis" ); CVAR_DEFINE_AUTO( sv_skyvec_z, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skylight direction by z-axis" ); CVAR_DEFINE_AUTO( sv_wateralpha, "1", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "world surfaces water transparency factor. 1.0 - solid, 0.0 - fully transparent" ); +CVAR_DEFINE_AUTO( sv_background_freeze, "1", FCVAR_ARCHIVE, "freeze player movement on background maps (e.g. to prevent falling)" ); CVAR_DEFINE_AUTO( showtriggers, "0", FCVAR_LATCH, "debug cvar shows triggers" ); CVAR_DEFINE_AUTO( sv_airmove, "1", FCVAR_SERVER, "obsolete, compatibility issues" ); CVAR_DEFINE_AUTO( sv_version, "", FCVAR_READ_ONLY, "engine version string" ); @@ -512,6 +513,9 @@ void SV_PrepWorldFrame( void ) ClearBits( ent->v.effects, EF_MUZZLEFLASH|EF_NOINTERP ); } + + if( svgame.physFuncs.pfnPrepWorldFrame != NULL ) + svgame.physFuncs.pfnPrepWorldFrame(); } /* @@ -648,9 +652,8 @@ void Master_Add( void ) NET_Config( true ); // allow remote if( !NET_StringToAdr( MASTERSERVER_ADR, &adr )) - MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); - - NET_SendPacket( NS_SERVER, 2, "q\xFF", adr ); + Con_Printf( "can't resolve adr: %s\n", MASTERSERVER_ADR ); + else NET_SendPacket( NS_SERVER, 2, "q\xFF", adr ); } /* @@ -692,9 +695,8 @@ void Master_Shutdown( void ) NET_Config( true ); // allow remote if( !NET_StringToAdr( MASTERSERVER_ADR, &adr )) - MsgDev( D_INFO, "Can't resolve addr: %s\n", MASTERSERVER_ADR ); - - NET_SendPacket( NS_SERVER, 2, "\x62\x0A", adr ); + Con_Printf( "can't resolve addr: %s\n", MASTERSERVER_ADR ); + else NET_SendPacket( NS_SERVER, 2, "\x62\x0A", adr ); } /* @@ -739,7 +741,7 @@ void SV_AddToMaster( netadr_t from, sizebuf_t *msg ) Info_SetValueForKey( s, "os", "w", len ); // Windows Info_SetValueForKey( s, "secure", "0", len ); // server anti-cheat Info_SetValueForKey( s, "lan", "0", len ); // LAN servers doesn't send info to master - Info_SetValueForKey( s, "version", va( "%g", XASH_VERSION ), len ); // server region. 255 -- all regions + Info_SetValueForKey( s, "version", va( "%s", XASH_VERSION ), len ); // server region. 255 -- all regions Info_SetValueForKey( s, "region", "255", len ); // server region. 255 -- all regions Info_SetValueForKey( s, "product", GI->gamefolder, len ); // product? Where is the difference with gamedir? @@ -847,13 +849,14 @@ void SV_Init( void ) Cvar_RegisterVariable (&violence_hgibs); Cvar_RegisterVariable (&mp_logecho); Cvar_RegisterVariable (&mp_logfile); + Cvar_RegisterVariable (&sv_background_freeze); // when we in developer-mode automatically turn cheats on if( host_developer.value ) Cvar_SetValue( "sv_cheats", 1.0f ); MSG_Init( &net_message, "NetMessage", net_message_buffer, sizeof( net_message_buffer )); - Q_snprintf( versionString, sizeof( versionString ), "%s: %.2f,%i,%i", "Xash3D", XASH_VERSION, PROTOCOL_VERSION, Q_buildnum() ); + Q_snprintf( versionString, sizeof( versionString ), "%s: %s,%i,%i", "Xash3D", XASH_VERSION, PROTOCOL_VERSION, Q_buildnum() ); Cvar_FullSet( "sv_version", versionString, FCVAR_READ_ONLY ); SV_ClearGameState (); // delete all temporary *.hl files diff --git a/engine/server/sv_move.c b/engine/server/sv_move.c index bacdcb01..533c52e5 100644 --- a/engine/server/sv_move.c +++ b/engine/server/sv_move.c @@ -74,8 +74,8 @@ realcheck: stop[2] = start[2] - 2.0f * svgame.movevars.stepsize; if( iMode == WALKMOVE_WORLDONLY ) - trace = SV_MoveNoEnts( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent ); - else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, monsterClip ); + trace = SV_MoveNoEnts( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent ); + else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, monsterClip ); if( trace.fraction == 1.0f ) return false; @@ -91,8 +91,8 @@ realcheck: start[1] = stop[1] = y ? maxs[1] : mins[1]; if( iMode == WALKMOVE_WORLDONLY ) - trace = SV_MoveNoEnts( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent ); - else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, monsterClip ); + trace = SV_MoveNoEnts( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent ); + else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, monsterClip ); if( trace.fraction != 1.0f && trace.endpos[2] > bottom ) bottom = trace.endpos[2]; diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index a3bcade7..1b4b2ca6 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -815,8 +815,8 @@ trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int if( blocked ) { // more accuracy blocking code - if( flDamage <= 0.0f ) - *blocked = !VectorCompare( ent->v.origin, end ); // can't move full distance + if( flDamage <= 0.0f && FBitSet( host.features, ENGINE_PHYSICS_PUSHER_EXT )) + *blocked = !VectorCompareEpsilon( ent->v.origin, end, ON_EPSILON ); // can't move full distance else *blocked = true; } @@ -864,9 +864,8 @@ static qboolean SV_CanBlock( edict_t *ent ) if( ent->v.solid == SOLID_NOT || ent->v.solid == SOLID_TRIGGER ) { // clear bounds for deadbody - ent->v.mins[0] = ent->v.mins[1] = 0.0f; - ent->v.maxs[0] = ent->v.maxs[1] = 0.0f; - ent->v.maxs[2] = ent->v.mins[2]; + ent->v.mins[0] = ent->v.mins[1] = 0; + VectorCopy( ent->v.mins, ent->v.maxs ); return false; } @@ -936,7 +935,7 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime ) if( block ) continue; // if the entity is standing on the pusher, it will definately be moved - if( !(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == pusher )) + if( !( FBitSet( check->v.flags, FL_ONGROUND ) && check->v.groundentity == pusher )) { if( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] @@ -2046,7 +2045,7 @@ qboolean SV_InitPhysicsAPI( void ) { if( pPhysIface( SV_PHYSICS_INTERFACE_VERSION, &gPhysicsAPI, &svgame.physFuncs )) { - MsgDev( D_REPORT, "SV_LoadProgs: ^2initailized extended PhysicAPI ^7ver. %i\n", SV_PHYSICS_INTERFACE_VERSION ); + Con_Reportf( "SV_LoadProgs: ^2initailized extended PhysicAPI ^7ver. %i\n", SV_PHYSICS_INTERFACE_VERSION ); if( svgame.physFuncs.SV_CheckFeatures != NULL ) { diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index 5f166a7b..d5198bf6 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -32,6 +32,9 @@ void SV_ClearPhysEnts( void ) qboolean SV_PlayerIsFrozen( edict_t *pClient ) { + if( sv_background_freeze.value && sv.background ) + return true; + if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) return false; @@ -352,10 +355,7 @@ static void pfnStuckTouch( int hitent, pmtrace_t *tr ) } if( svgame.pmove->numtouch >= MAX_PHYSENTS ) - { - MsgDev( D_ERROR, "PM_StuckTouch: MAX_TOUCHENTS limit exceeded\n" ); return; - } VectorCopy( svgame.pmove->velocity, tr->deltavelocity ); tr->ent = hitent; @@ -567,7 +567,7 @@ void SV_InitClientMove( void ) for( i = 0; i < MAX_MAP_HULLS; i++ ) { if( svgame.dllFuncs.pfnGetHullBounds( i, host.player_mins[i], host.player_maxs[i] )) - MsgDev( D_NOTE, "SV: hull%i, player_mins: %g %g %g, player_maxs: %g %g %g\n", i, + Con_Reportf( "SV: hull%i, player_mins: %g %g %g, player_maxs: %g %g %g\n", i, host.player_mins[i][0], host.player_mins[i][1], host.player_mins[i][2], host.player_maxs[i][0], host.player_maxs[i][1], host.player_maxs[i][2] ); } diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index daf4b66d..69dc6123 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -422,7 +422,7 @@ static int IsValidSave( void ) } // ignore autosave during background - if( sv.background ) + if( sv.background || UI_CreditsActive( )) return 0; if( svgame.physFuncs.SV_AllowSaveGame != NULL ) @@ -539,9 +539,6 @@ static qboolean SaveGetName( int lastnum, char *filename ) { int a, b, c; - if( !COM_CheckString( filename )) - return false; - if( lastnum < 0 || lastnum > 999 ) return false; @@ -664,7 +661,7 @@ static void SaveClear( SAVERESTOREDATA *pSaveData ) /* ============= -SaveInit +SaveFinish release global save-restore buffer ============= @@ -1790,7 +1787,7 @@ static int CreateEntityTransitionList( SAVERESTOREDATA *pSaveData, int levelMask } else { - Con_DPrintf( "Transferring %s (%d)\n", STRING( pTable->classname ), NUM_FOR_EDICT( pent )); + Con_Reportf( "Transferring %s (%d)\n", STRING( pTable->classname ), NUM_FOR_EDICT( pent )); if( svgame.dllFuncs.pfnRestore( pent, pSaveData, 0 ) < 0 ) { @@ -1802,7 +1799,7 @@ static int CreateEntityTransitionList( SAVERESTOREDATA *pSaveData, int levelMask { // this can happen during normal processing - PVS is just a guess, // some map areas won't exist in the new map - Con_DPrintf( "Suppressing %s\n", STRING( pTable->classname )); + Con_Reportf( "Suppressing %s\n", STRING( pTable->classname )); SetBits( pent->v.flags, FL_KILLME ); } else @@ -2014,6 +2011,9 @@ qboolean SV_LoadGame( const char *pPath ) if( host.type == HOST_DEDICATED ) return false; + if( UI_CreditsActive( )) + return false; + if( !COM_CheckString( pPath )) return false; diff --git a/engine/server/sv_world.c b/engine/server/sv_world.c index 159d75e3..70d65186 100644 --- a/engine/server/sv_world.c +++ b/engine/server/sv_world.c @@ -28,7 +28,8 @@ typedef struct moveclip_s edict_t *passedict; trace_t trace; int type; // move type - int flags; // trace flags + qboolean ignoretrans; + qboolean monsterclip; } moveclip_t; /* @@ -820,18 +821,18 @@ returns true if the entity is in solid currently */ qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker ) { - trace_t trace; qboolean monsterClip = FBitSet( ent->v.flags, FL_MONSTERCLIP ) ? true : false; + trace_t trace; - if( ent->v.flags & (FL_CLIENT|FL_FAKECLIENT)) + if( FBitSet( ent->v.flags, FL_CLIENT|FL_FAKECLIENT )) { // to avoid falling through tracktrain update client mins\maxs here - if( ent->v.flags & FL_DUCKING ) + if( FBitSet( ent->v.flags, FL_DUCKING )) SV_SetMinMaxSize( ent, svgame.pmove->player_mins[1], svgame.pmove->player_maxs[1], true ); else SV_SetMinMaxSize( ent, svgame.pmove->player_mins[0], svgame.pmove->player_maxs[0], true ); } - trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent, monsterClip ); + trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent, monsterClip ); if( SV_IsValidEdict( blocker ) && SV_IsValidEdict( trace.ent )) { @@ -839,6 +840,7 @@ qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker ) return trace.startsolid; return false; } + return trace.startsolid; } @@ -1159,18 +1161,15 @@ static qboolean SV_ClipToEntity( edict_t *touch, moveclip_t *clip ) if( svgame.dllFuncs2.pfnShouldCollide ) { if( !svgame.dllFuncs2.pfnShouldCollide( touch, clip->passedict )) - return true; // originally this was 'return' but is completely wrong! + return true; } // monsterclip filter (solid custom is a static or dynamic bodies) if( touch->v.solid == SOLID_BSP || touch->v.solid == SOLID_CUSTOM ) { - if( FBitSet( touch->v.flags, FL_MONSTERCLIP )) - { - // func_monsterclip works only with monsters that have same flag! - if( !FBitSet( clip->flags, FMOVE_MONSTERCLIP )) - return true; - } + // func_monsterclip works only with monsters that have same flag! + if( FBitSet( touch->v.flags, FL_MONSTERCLIP ) && !clip->monsterclip ) + return true; } else { @@ -1181,7 +1180,7 @@ static qboolean SV_ClipToEntity( edict_t *touch, moveclip_t *clip ) mod = SV_ModelHandle( touch->v.modelindex ); - if( mod && mod->type == mod_brush && FBitSet( clip->flags, FMOVE_IGNORE_GLASS )) + if( mod && mod->type == mod_brush && clip->ignoretrans ) { // we ignore brushes with rendermode != kRenderNormal and without FL_WORLDBRUSH set if( touch->v.rendermode != kRenderNormal && !FBitSet( touch->v.flags, FL_WORLDBRUSH )) @@ -1226,7 +1225,7 @@ static qboolean SV_ClipToEntity( edict_t *touch, moveclip_t *clip ) if( touch->v.solid == SOLID_CUSTOM ) SV_CustomClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace ); - else if( touch->v.flags & FL_MONSTER ) + else if( FBitSet( touch->v.flags, FL_MONSTER )) SV_ClipMoveToEntity( touch, clip->start, clip->mins2, clip->maxs2, clip->end, &trace ); else SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace ); @@ -1363,13 +1362,14 @@ trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, clip.start = start; clip.end = trace_endpos; clip.type = (type & 0xFF); - clip.flags = (type & 0xFF00); + clip.ignoretrans = type >> 8; + clip.monsterclip = false; clip.passedict = (e) ? e : EDICT_NUM( 0 ); clip.mins = mins; clip.maxs = maxs; if( monsterclip && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) - SetBits( clip.flags, FMOVE_MONSTERCLIP ); + clip.monsterclip = true; if( clip.type == MOVE_MISSILE ) { @@ -1422,7 +1422,8 @@ trace_t SV_MoveNoEnts( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_ clip.start = start; clip.end = trace_endpos; clip.type = (type & 0xFF); - clip.flags = (type & 0xFF00); + clip.ignoretrans = type >> 8; + clip.monsterclip = false; clip.passedict = (e) ? e : EDICT_NUM( 0 ); clip.mins = mins; clip.maxs = maxs;