From d52b2b3794baa7578ca7c107632c9c313129ec22 Mon Sep 17 00:00:00 2001 From: g-cont Date: Thu, 24 Oct 2013 00:00:00 +0400 Subject: [PATCH] 24 Oct 2013 --- common/com_model.h | 16 ++- common/entity_state.h | 2 +- common/ivoicetweak.h | 2 + common/r_efx.h | 1 + common/r_studioint.h | 5 +- common/render_api.h | 46 ++++--- common/triangleapi.h | 6 +- engine/cdll_int.h | 112 +++++++---------- engine/client/cl_game.c | 247 ++++++++++++++++++++++++++++--------- engine/client/cl_parse.c | 26 ++-- engine/client/cl_tent.c | 16 ++- engine/client/client.h | 66 +++++----- engine/client/gl_decals.c | 59 ++++++--- engine/client/gl_local.h | 2 +- engine/client/gl_rmain.c | 24 ++-- engine/client/gl_rmisc.c | 20 +++ engine/client/gl_studio.c | 89 ++++++++++++- engine/common/build.c | 2 +- engine/common/cmd.c | 31 +++-- engine/common/common.c | 4 + engine/common/common.h | 13 +- engine/common/host.c | 57 +++++++++ engine/common/net_buffer.h | 2 +- engine/common/protocol.h | 1 + engine/eiface.h | 1 + engine/server/server.h | 7 +- engine/server/sv_client.c | 4 + engine/server/sv_game.c | 165 +++++++++++++++++-------- engine/server/sv_save.c | 17 ++- engine/studio.h | 7 +- 30 files changed, 739 insertions(+), 311 deletions(-) diff --git a/common/com_model.h b/common/com_model.h index 0177ec56..39a29679 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -35,6 +35,7 @@ typedef vec_t vec4_t[4]; #define MIPLEVELS 4 #define VERTEXSIZE 7 #define MAXLIGHTMAPS 4 +#define MAXSTYLES 12 // BSP32 supports up to 12 styles per face #define NUM_AMBIENTS 4 // automatic ambient sounds // model types @@ -126,12 +127,11 @@ struct decal_s { decal_t *pnext; // linked list for each surface msurface_t *psurface; // Surface id for persistence / unlinking - short dx; // Offsets into surface texture - short dy; // (in texture coordinates, so we don't need floats) + float dx; // local texture coordinates + float dy; // + float scale; // Pixel scale short texture; // Decal texture - byte scale; // Pixel scale byte flags; // Decal flags FDECAL_* - short entityIndex; // Entity this is attached to // Xash3D added vec3_t position; // location of the decal center in world space. @@ -216,6 +216,8 @@ typedef struct mextrasurf_s vec3_t origin; // surface origin msurfmesh_t *mesh; // VBO\VA ready surface mesh. Not used by engine but can be used by mod-makers + byte styles[MAXSTYLES]; // expansion for BSP32 (12 lightstyles per surface) + int cached_light[MAXSTYLES]; // values currently used in lightmap int dlight_s, dlight_t; // gl lightmap coordinates for dynamic lightmaps int mirrortexturenum; // gl texnum @@ -223,7 +225,7 @@ typedef struct mextrasurf_s struct mextrasurf_s *mirrorchain; // for gl_texsort drawing struct mextrasurf_s *detailchain; // for detail textures drawing - int reserved[7]; // just for future expansions or mod-makers + int reserved[32]; // just for future expansions or mod-makers } mextrasurf_t; typedef struct hull_s @@ -329,6 +331,8 @@ typedef struct auxvert_s #define MAX_SCOREBOARDNAME 32 #define MAX_INFO_STRING 256 +#include "custom.h" + typedef struct player_info_s { int userid; // User id on server @@ -352,6 +356,8 @@ typedef struct player_info_s float gaitframe; float gaityaw; vec3_t prevgaitorigin; + + customization_t customdata; } player_info_t; // diff --git a/common/entity_state.h b/common/entity_state.h index 5ad57fef..2e0f129d 100644 --- a/common/entity_state.h +++ b/common/entity_state.h @@ -180,7 +180,7 @@ typedef struct local_state_s { entity_state_t playerstate; clientdata_t client; - weapon_data_t weapondata[32]; + weapon_data_t weapondata[64]; } local_state_t; #endif//ENTITY_STATE_H \ No newline at end of file diff --git a/common/ivoicetweak.h b/common/ivoicetweak.h index e4a65668..9c7b6963 100644 --- a/common/ivoicetweak.h +++ b/common/ivoicetweak.h @@ -33,6 +33,8 @@ typedef struct IVoiceTweak_s // Get/set control values. void (*SetControlFloat)( VoiceTweakControl iControl, float value ); float (*GetControlFloat)( VoiceTweakControl iControl ); + + int (*GetSpeakingVolume)( void ); } IVoiceTweak; #endif//IVOICETWEAK_H \ No newline at end of file diff --git a/common/r_efx.h b/common/r_efx.h index 4ad60eef..d21cba27 100644 --- a/common/r_efx.h +++ b/common/r_efx.h @@ -189,6 +189,7 @@ struct efx_api_s void (*R_GetPackedColor)( short *packed, short color ); short (*R_LookupColor)( unsigned char r, unsigned char g, unsigned char b ); void (*R_DecalRemoveAll)( int textureIndex ); // textureIndex points to the decal index in the array, not the actual texture index. + void (*R_FireCustomDecal)( int textureIndex, int entity, int modelIndex, float *position, int flags, float scale ); }; #endif//R_EFX_H \ No newline at end of file diff --git a/common/r_studioint.h b/common/r_studioint.h index 5e5179c5..19365669 100644 --- a/common/r_studioint.h +++ b/common/r_studioint.h @@ -108,8 +108,9 @@ typedef struct engine_studio_api_s void ( *GL_StudioDrawShadow )( void ); void ( *GL_SetRenderMode )( int mode ); - // Xash3D extension - struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e ); + void ( *StudioSetRenderamt )( int iRenderamt ); + void ( *StudioSetCullState )( int iCull ); + void ( *StudioRenderShadow )( int iSprite, float *p1, float *p2, float *p3, float *p4 ); } engine_studio_api_t; typedef struct server_studio_api_s diff --git a/common/render_api.h b/common/render_api.h index 703e7927..49e0c8e0 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -19,7 +19,16 @@ GNU General Public License for more details. #include "lightstyle.h" #include "dlight.h" -#define CL_RENDER_INTERFACE_VERSION 26 +// changes for version 28 +// replace decal_t from software declaration to hardware (matched to normal HL) +// mextrasurf_t->byte styles[12] added +// mextrasurf_t->increased limit of reserved fields (up from 7 to 32) +// replace R_StoreEfrags with him extended version +// formed group for BSP decal manipulating +// move misc functions at end of the interface +// added new export for clearing studio decals + +#define CL_RENDER_INTERFACE_VERSION 28 #define MAX_STUDIO_DECALS 4096 // + unused space of BSP decals #define SURF_INFO( surf, mod ) ((mextrasurf_t *)mod->cache.data + (surf - mod->surfaces)) @@ -89,13 +98,15 @@ typedef enum typedef struct beam_s BEAM; typedef struct particle_s particle_t; -// 10 bytes here +// 12 bytes here typedef struct modelstate_s { short sequence; short frame; // 10 bits multiple by 4, should be enough byte blending[2]; byte controller[4]; + byte body; + byte skin; } modelstate_t; typedef struct decallist_s @@ -105,6 +116,7 @@ typedef struct decallist_s short entityIndex; byte depth; byte flags; + float scale; // this is the surface plane that we hit so that // we can move certain decals across @@ -130,7 +142,7 @@ typedef struct render_api_s void (*R_SetCurrentEntity)( struct cl_entity_s *ent ); // tell engine about both currententity and currentmodel void (*R_SetCurrentModel)( struct model_s *mod ); // change currentmodel but leave currententity unchanged void (*GL_SetWorldviewProjectionMatrix)( const float *glmatrix ); // update viewprojection matrix (tracers uses it) - void (*R_StoreEfrags)( struct efrag_s **ppefrag ); // store efrags for static entities + void (*R_StoreEfrags)( struct efrag_s **ppefrag, int framecount );// store efrags for static entities // Texture tools int (*GL_FindTexture)( const char *name ); @@ -139,15 +151,10 @@ typedef struct render_api_s int (*GL_CreateTexture)( const char *name, int width, int height, const void *buffer, int flags ); void (*GL_FreeTexture)( unsigned int texnum ); - // Draw stuff (decals and particles are drawing by the engine) + // Decals manipulating (draw & remove) void (*DrawSingleDecal)( struct decal_s *pDecal, struct msurface_s *fa ); - void (*GL_DrawParticles)( const float *vieworg, const float *fwd, const float *rt, const float *up, unsigned int clipFlags ); - - // Misc renderer functions - void (*EnvShot)( const float *vieworg, const char *name, qboolean skyshot ); // creates a cubemap or skybox into gfx\env folder - int (*COM_CompareFileTime)( const char *filename1, const char *filename2, int *iCompare ); - void (*Host_Error)( const char *error, ... ); // cause Host Error - int (*SPR_LoadExt)( const char *szPicName, unsigned int texFlags ); // extended version of SPR_Load + float *(*R_DecalSetupVerts)( struct decal_s *pDecal, struct msurface_s *surf, int texture, int *outCount ); + void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only) // AVIkit support void *(*AVI_LoadVideo)( const char *filename, int load_audio, int ignore_hwgamma ); @@ -167,14 +174,17 @@ typedef struct render_api_s void (*GL_TexMatrixIdentity)( void ); void (*GL_CleanUpTextureUnits)( int last ); // pass 0 for clear all the texture units void (*GL_TexGen)( unsigned int coord, unsigned int mode ); - -// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 26 - void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only) - float *(*R_DecalSetupVerts)( struct decal_s *pDecal, struct msurface_s *surf, int texture, int *outCount ); - void (*R_StoreEfragsExt)( struct efrag_s **ppefrag, int framecount ); // store efrags for static entities void (*GL_TextureTarget)( unsigned int target ); // change texture unit mode without bind texture - struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e ); // moved here to avoid incompatibility with IEngineStudio official iface + + // Misc renderer functions + void (*GL_DrawParticles)( const float *vieworg, const float *fwd, const float *rt, const float *up, unsigned int clipFlags ); + void (*EnvShot)( const float *vieworg, const char *name, qboolean skyshot ); // creates a cubemap or skybox into gfx\env folder + int (*COM_CompareFileTime)( const char *filename1, const char *filename2, int *iCompare ); + void (*Host_Error)( const char *error, ... ); // cause Host Error + int (*SPR_LoadExt)( const char *szPicName, unsigned int texFlags ); // extended version of SPR_Load + struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e ); const struct ref_overview_s *( *GetOverviewParms )( void ); +// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 28 } render_api_t; // render callbacks @@ -191,6 +201,8 @@ typedef struct render_interface_s void (*R_StudioDecalShoot)( int decalTexture, struct cl_entity_s *ent, const float *start, const float *pos, int flags, modelstate_t *state ); // prepare studio decals for save int (*R_CreateStudioDecalList)( decallist_t *pList, int count, qboolean changelevel ); + // clear decals by engine request (e.g. for demo recording or vid_restart) + void (*R_ClearStudioDecals)( void ); // grab r_speeds message qboolean (*R_SpeedsMessage)( char *out, size_t size ); // replace with built-in R_DrawCubemapView for make skyshots or envshots diff --git a/common/triangleapi.h b/common/triangleapi.h index a12fe3c7..d975a26e 100644 --- a/common/triangleapi.h +++ b/common/triangleapi.h @@ -52,7 +52,11 @@ typedef struct triangleapi_s int (*WorldToScreen)( float *world, float *screen ); // Returns 1 if it's z clipped void (*Fog)( float flFogColor[3], float flStart, float flEnd, int bOn ); //Works just like GL_FOG, flFogColor is r/g/b. void (*ScreenToWorld)( float *screen, float *world ); - + void (*GetMatrix)( const int pname, float *matrix ); + int (*BoxInPVS)( float *mins, float *maxs ); + void (*LightAtPoint)( float *pos, float *value ); + void (*Color4fRendermode)( float r, float g, float b, float a, int rendermode ); + void (*FogParams)( float flDensity, int iFogSkybox ); } triangleapi_t; #endif//TRIANGLEAPI_H \ No newline at end of file diff --git a/engine/cdll_int.h b/engine/cdll_int.h index 2809ff41..05fdaf12 100644 --- a/engine/cdll_int.h +++ b/engine/cdll_int.h @@ -28,6 +28,14 @@ extern "C" { #include "const.h" +#define MAX_ALIAS_NAME 32 + +typedef struct cmdalias_s +{ + struct cmdalias_s *next; + char name[MAX_ALIAS_NAME]; + char *value; +} cmdalias_t; // this file is included by both the engine and the client-dll, // so make sure engine declarations aren't done twice @@ -97,6 +105,8 @@ typedef struct hud_player_info_s char *model; short topcolor; short bottomcolor; + + unsigned __int64 m_nSteamID; } hud_player_info_t; typedef struct cl_enginefuncs_s @@ -250,75 +260,43 @@ typedef struct cl_enginefuncs_s void (*pfnSetMousePos)( int x, int y ); void (*pfnSetMouseEnable)( qboolean fEnable ); - struct cvar_s* (*pfnGetCvarList)( void ); - struct cmd_s* (*pfnGetCmdList)( void ); - char* (*pfnCvarName)( struct cvar_s* cvar ); - char* (*pfnCmdName)( struct cmd_s* cmd ); + // undocumented interface starts here + struct cvar_s* (*pfnGetFirstCvarPtr)( void ); + void* (*pfnGetFirstCmdFunctionHandle)( void ); + void* (*pfnGetNextCmdFunctionHandle)( void *cmdhandle ); + const char* (*pfnGetCmdFunctionName)( void *cmdhandle ); + float (*pfnGetClientOldTime)( void ); + float (*pfnGetGravity)( void ); + struct model_s* (*pfnGetModelByIndex)( int index ); + void (*pfnSetFilterMode)( int mode ); // same as gl_texsort in original Quake + void (*pfnSetFilterColor)( float red, float green, float blue ); + void (*pfnSetFilterBrightness)( float brightness ); + void *(*pfnSequenceGet)( const char *fileName, const char *entryName ); + void (*pfnSPR_DrawGeneric)( int frame, int x, int y, const wrect_t *prc, int blendsrc, int blenddst, int width, int height ); + void *(*pfnSequencePickSentence)( const char *groupName, int pickMethod, int *entryPicked ); + int (*pfnDrawString)( int x, int y, const char *str, int r, int g, int b ); + int (*pfnDrawStringReverse)( int x, int y, const char *str, int r, int g, int b ); + const char *(*LocalPlayerInfo_ValueForKey)( const char* key ); + int (*pfnVGUI2DrawCharacter)( int x, int y, int ch, unsigned int font ); + int (*pfnVGUI2DrawCharacterAdditive)( int x, int y, int ch, int r, int g, int b, unsigned int font ); + unsigned int (*pfnGetApproxWavePlayLen)( char *filename ); + void* (*GetCareerGameUI)( void ); // g-cont. !!!! potential crash-point! + void (*Cvar_Set)( char *name, char *value ); + int (*pfnIsPlayingCareerMatch)( void ); + void (*pfnPlaySoundVoiceByName)( char *szSound, float volume, int pitch ); + void (*pfnPrimeMusicStream)( char *filename, int looping ); + double (*pfnSys_FloatTime)( void ); - float (*pfnGetServerTime)( void ); - float (*pfnGetGravity)( void ); - - const struct model_s* (*pfnPrecacheSprite)( HSPRITE spr ); - - // Appears to modifies hidden cvar gl_texsort. - void (*pfnEnableTexSort)( int enable ); - - // Colour scaling values for screen. Only works when gl_texsort is active. - void (*pfnSetLightmapColor)( float red, float green, float blue ); - - // Final scaling factor for screen. Only works when gl_texsort is active. - void (*pfnSetLightmapScale)( float scale ); - - // Seems to be a client entry point to the pfnSequenceGet function introduced for CS:CZ - void* (*pfnSequenceGet)( const char *fileName, const char *entryName ); - - // Draws a sprite on the screen - parameters are likely incorrect. - void (*pfnSPR_DrawGeneric)( int frame, int x, int y, const wrect_t *prc, int blendsrc, int blenddst, int u3, int u4 ); - - // Seems to be a client entry point to the pfnSequencePickSentence function introduced for CS:CZ - void* (*pfnSequencePickSentence)( const char *groupName, int pickMethod, int *picked ); - - // localizes hud string, uses Legacy font from skin def - // also supports unicode strings - int (*pfnDrawLocalizedHudString)( int x, int y, const char* str, int r, int g, int b ); - - // i can't get this to work for some reason, don't use this - int (*pfnDrawLocalizedConsoleString)( int x, int y, const char* str ); - - // gets keyvalue for local player, useful for querying vgui menus or autohelp - const char *(*LocalPlayerInfo_ValueForKey)( const char* key ); - - void (*pfnDrawText)( int x, int y, const char* text, unsigned long font ); - int (*pfnDrawUnicodeCharacter)( int x, int y, short number, int r, int g, int b, unsigned long hfont ); - - // Seems to be a client entry point to the pfnGetApproxWavePlayLen function introduced for CS:CZ - unsigned int (*pfnGetApproxWavePlayLen)( char *filename ); - - // for condition zero, returns interface from GameUI - void* (*GetCareerGameInterface)( void ); // g-cont. !!!! potential crash-point! - - // Sets cvar value - why is this needed when Cvar_SetValue already exists? - void (*Cvar_Set)( char *name, char *value ); - - // Seems to be a client entry point to the pfnIsCareerMatch function introduced for CS:CZ - int (*pfnIsCareerMatch)( void ); - - // passes pitch as param - void (*pfnStartDynamicSound)( char *filename, float volume, float pitch ); - void (*pfnMP3_InitStream)( char *filename, int flags ); - - float (*pfnSys_FloatTime)( void ); - - void (*pfnProcessTutorMessageDecayBuffer)( int *buffer, int buflen ); - void (*pfnConstructTutorMessageDecayBuffer)( int *buffer, int buflen ); - void (*pfnResetTutorMessageDecayData)( void ); - - // Seems to be an exact copy of the previous StartDynamicSound function??? - void (*pfnStartDynamicSound2)( char *filename, float volume, float pitch ); - - // Same like pfnFillRGBA - with other mode (substractive) - void (*pfnFillRGBA2)( int x, int y, int width, int height, int r, int g, int b, int a ); + // decay funcs + void (*pfnProcessTutorMessageDecayBuffer)( int *buffer, int buflen ); + void (*pfnConstructTutorMessageDecayBuffer)( int *buffer, int buflen ); + void (*pfnResetTutorMessageDecayData)( void ); + void (*pfnPlaySoundByNameAtPitch)( char *szSound, float volume, int pitch ); + void (*pfnFillRGBABlend)( int x, int y, int width, int height, int r, int g, int b, int a ); + int (*pfnGetAppID)( void ); + cmdalias_t *(*pfnGetAliases)( void ); + void (*pfnVguiWrap2_GetMouseDelta)( int *x, int *y ); } cl_enginefunc_t; #define CLDLL_INTERFACE_VERSION 7 diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index c60d2122..23d40454 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -2629,9 +2629,9 @@ pfnGetServerTime ============= */ -float pfnGetServerTime( void ) +float pfnGetClientOldTime( void ) { - return cl.mtime[0]; + return cl.oldtime; } /* @@ -2645,19 +2645,6 @@ float pfnGetGravity( void ) return clgame.movevars.gravity; } -/* -============= -pfnPrecacheSprite - -============= -*/ -const model_t *pfnPrecacheSprite( HSPRITE hSprite ) -{ - if( hSprite <= 0 || hSprite > ( MAX_IMAGES - 1 )) - return NULL; // bad image - return &clgame.sprites[hSprite]; -} - /* ============= pfnEnableTexSort @@ -2706,24 +2693,24 @@ void pfnSPR_DrawGeneric( int frame, int x, int y, const wrect_t *prc, int blends /* ============= -pfnDrawLocalizedHudString +pfnDrawString TODO: implement ============= */ -int pfnDrawLocalizedHudString( int x, int y, const char* str, int r, int g, int b ) +int pfnDrawString( int x, int y, const char *str, int r, int g, int b ) { return 0; } /* ============= -pfnDrawLocalizedConsoleString +pfnDrawStringReverse TODO: implement ============= */ -int pfnDrawLocalizedConsoleString( int x, int y, const char* str ) +int pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b ) { return 0; } @@ -2741,23 +2728,24 @@ const char *LocalPlayerInfo_ValueForKey( const char* key ) /* ============= -pfnDrawText +pfnVGUI2DrawCharacter TODO: implement ============= */ -void pfnDrawText( int x, int y, const char* text, unsigned long font ) +int pfnVGUI2DrawCharacter( int x, int y, int ch, unsigned int font ) { + return 0; } /* ============= -pfnDrawUnicodeCharacter +pfnVGUI2DrawCharacterAdditive TODO: implement ============= */ -int pfnDrawUnicodeCharacter( int x, int y, short number, int r, int g, int b, unsigned long hfont ) +int pfnVGUI2DrawCharacterAdditive( int x, int y, int ch, int r, int g, int b, unsigned int font ) { return 0; } @@ -2776,11 +2764,11 @@ void *GetCareerGameInterface( void ) /* ============= -pfnStartDynamicSound +pfnPlaySoundVoiceByName ============= */ -void pfnStartDynamicSound( char *filename, float volume, float pitch ) +void pfnPlaySoundVoiceByName( char *filename, float volume, int pitch ) { int hSound = S_RegisterSound( filename ); S_StartSound( NULL, cl.refdef.viewentity, CHAN_AUTO, hSound, volume, ATTN_NORM, pitch, SND_STOP_LOOPING ); @@ -2792,7 +2780,7 @@ pfnMP3_InitStream ============= */ -void pfnMP3_InitStream( char *filename, int flags ) +void pfnMP3_InitStream( char *filename, int looping ) { if( !filename ) { @@ -2800,8 +2788,7 @@ void pfnMP3_InitStream( char *filename, int flags ) return; } - // g-cont. flag 1 is probably 'LOOP' - if( flags & 1 ) + if( looping ) { S_StartBackgroundTrack( filename, filename, 0 ); } @@ -2813,22 +2800,11 @@ void pfnMP3_InitStream( char *filename, int flags ) /* ============= -pfnSys_FloatTime +pfnPlaySoundByNameAtPitch ============= */ -float pfnSys_FloatTime( void ) -{ - return (float)Sys_DoubleTime(); -} - -/* -============= -pfnStartDynamicSound2 - -============= -*/ -void pfnStartDynamicSound2( char *filename, float volume, float pitch ) +void pfnPlaySoundByNameAtPitch( char *filename, float volume, int pitch ) { int hSound = S_RegisterSound( filename ); S_StartSound( NULL, cl.refdef.viewentity, CHAN_STATIC, hSound, volume, ATTN_NORM, pitch, SND_STOP_LOOPING ); @@ -2836,11 +2812,11 @@ void pfnStartDynamicSound2( char *filename, float volume, float pitch ) /* ============= -pfnFillRGBA2 +pfnFillRGBABlend ============= */ -void pfnFillRGBA2( int x, int y, int width, int height, int r, int g, int b, int a ) +void pfnFillRGBABlend( int x, int y, int width, int height, int r, int g, int b, int a ) { r = bound( 0, r, 255 ); g = bound( 0, g, 255 ); @@ -2859,6 +2835,28 @@ void pfnFillRGBA2( int x, int y, int width, int height, int r, int g, int b, int pglColor4ub( 255, 255, 255, 255 ); } +/* +============= +pfnGetAppID + +============= +*/ +int pfnGetAppID( void ) +{ + return 220; // standard Valve value +} + +/* +============= +pfnVguiWrap2_GetMouseDelta + +TODO: implement +============= +*/ +void pfnVguiWrap2_GetMouseDelta( int *x, int *y ) +{ +} + /* ================= TriApi implementation @@ -3149,6 +3147,76 @@ void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ) pglHint( GL_FOG_HINT, GL_NICEST ); } +/* +============= +TriGetMatrix + +very strange export +============= +*/ +void TriGetMatrix( const int pname, float *matrix ) +{ + pglGetFloatv( pname, matrix ); +} + +/* +============= +TriBoxInPVS + +check box in pvs (absmin, absmax) +============= +*/ +int TriBoxInPVS( float *mins, float *maxs ) +{ + return Mod_BoxVisible( mins, maxs, Mod_GetCurrentVis( )); +} + +/* +============= +TriLightAtPoint + +NOTE: dlights are ignored +============= +*/ +void TriLightAtPoint( float *pos, float *value ) +{ + color24 ambient; + + if( !pos || !value ) + return; + + R_LightForPoint( pos, &ambient, false, false, 0.0f ); + + value[0] = (float)ambient.r * 255.0f; + value[1] = (float)ambient.g * 255.0f; + value[2] = (float)ambient.b * 255.0f; +} + +/* +============= +TriColor4fRendermode + +Heavy legacy of Quake... +============= +*/ +void TriColor4fRendermode( float r, float g, float b, float a, int rendermode ) +{ + if( rendermode == kRenderTransAlpha ) + pglColor4f( r, g, b, a ); + else pglColor4f( r * a, g * a, b * a, 1.0f ); +} + +/* +============= +TriForParams + +============= +*/ +void TriFogParams( float flDensity, int iFogSkybox ) +{ + // FIXME: implement +} + /* ================= DemoApi implementation @@ -3455,6 +3523,18 @@ float Voice_GetControlFloat( VoiceTweakControl iControl ) return 1.0f; } +/* +================= +Voice_GetSpeakingVolume + +================= +*/ +int Voice_GetSpeakingVolume( void ) +{ + // TODO: implement + return 255; +} + // shared between client and server triangleapi_t gTriApi = { @@ -3473,6 +3553,11 @@ triangleapi_t gTriApi = R_WorldToScreen, // NOTE: XPROJECT, YPROJECT should be done in client.dll TriFog, R_ScreenToWorld, + TriGetMatrix, + TriBoxInPVS, + TriLightAtPoint, + TriColor4fRendermode, + TriFogParams, }; static efx_api_t gEfxApi = @@ -3610,6 +3695,7 @@ static IVoiceTweak gVoiceApi = Voice_EndVoiceTweakMode, Voice_SetControlFloat, Voice_GetControlFloat, + Voice_GetSpeakingVolume, }; // engine callbacks @@ -3717,35 +3803,38 @@ static cl_enginefunc_t gEngfuncs = pfnSetMousePos, pfnSetMouseEnable, Cvar_GetList, - Cmd_GetList, - Cvar_GetName, + Cmd_GetFirstFunctionHandle, + Cmd_GetNextFunctionHandle, Cmd_GetName, - pfnGetServerTime, + pfnGetClientOldTime, pfnGetGravity, - pfnPrecacheSprite, + Mod_Handle, pfnEnableTexSort, pfnSetLightmapColor, pfnSetLightmapScale, pfnSequenceGet, pfnSPR_DrawGeneric, pfnSequencePickSentence, - pfnDrawLocalizedHudString, - pfnDrawLocalizedConsoleString, + pfnDrawString, + pfnDrawStringReverse, LocalPlayerInfo_ValueForKey, - pfnDrawText, - pfnDrawUnicodeCharacter, + pfnVGUI2DrawCharacter, + pfnVGUI2DrawCharacterAdditive, Sound_GetApproxWavePlayLen, GetCareerGameInterface, Cvar_Set, pfnIsCareerMatch, - pfnStartDynamicSound, + pfnPlaySoundVoiceByName, pfnMP3_InitStream, - pfnSys_FloatTime, + Sys_DoubleTime, pfnProcessTutorMessageDecayBuffer, pfnConstructTutorMessageDecayBuffer, pfnResetTutorMessageDecayData, - pfnStartDynamicSound2, - pfnFillRGBA2, + pfnPlaySoundByNameAtPitch, + pfnFillRGBABlend, + pfnGetAppID, + Cmd_AliasGetList, + pfnVguiWrap2_GetMouseDelta, }; void CL_UnloadProgs( void ) @@ -3778,6 +3867,8 @@ qboolean CL_LoadProgs( const char *name ) { static playermove_t gpMove; const dllfunc_t *func; + CL_EXPORT_FUNCS F; // export 'F' + qboolean critical_exports = true; if( clgame.hInstance ) CL_UnloadProgs(); @@ -3803,24 +3894,58 @@ qboolean CL_LoadProgs( const char *name ) for( func = cdll_exports; func && func->name; func++ ) *func->func = NULL; + // trying to get single export named 'F' + if(( F = (void *)Com_GetProcAddress( clgame.hInstance, "F" )) != NULL ) + { + MsgDev( D_NOTE, "CL_LoadProgs: found single callback export\n" ); + + // trying to fill interface now + F( &clgame.dllFuncs ); + + // check critical functions again + for( func = cdll_exports; func && func->name; func++ ) + { + if( func->func == NULL ) + break; // BAH critical function was missed + } + + // because all the exports are loaded through function 'F" + if( !func || !func->name ) + critical_exports = false; + } + for( func = cdll_exports; func && func->name != NULL; func++ ) { + if( *func->func != NULL ) + continue; // already get through 'F' + // functions are cleared before all the extensions are evaluated if(!( *func->func = (void *)Com_GetProcAddress( clgame.hInstance, func->name ))) { MsgDev( D_NOTE, "CL_LoadProgs: failed to get address of %s proc\n", func->name ); - Com_FreeLibrary( clgame.hInstance ); - clgame.hInstance = NULL; - return false; + + if( critical_exports ) + { + Com_FreeLibrary( clgame.hInstance ); + clgame.hInstance = NULL; + return false; + } } } - // clear new exports - for( func = cdll_new_exports; func && func->name; func++ ) - *func->func = NULL; + // it may be loaded through 'F' so we don't need to clear them + if( critical_exports ) + { + // clear new exports + for( func = cdll_new_exports; func && func->name; func++ ) + *func->func = NULL; + } for( func = cdll_new_exports; func && func->name != NULL; func++ ) { + if( *func->func != NULL ) + continue; // already get through 'F' + // 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 ))) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 5e952476..987200b8 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -489,9 +489,11 @@ CL_ParseStaticDecal */ void CL_ParseStaticDecal( sizebuf_t *msg ) { - vec3_t origin; - int decalIndex, entityIndex, modelIndex; - int flags; + vec3_t origin; + int decalIndex, entityIndex, modelIndex; + cl_entity_t *ent = NULL; + float scale; + int flags; BF_ReadVec3Coord( msg, origin ); decalIndex = BF_ReadWord( msg ); @@ -501,8 +503,9 @@ void CL_ParseStaticDecal( sizebuf_t *msg ) modelIndex = BF_ReadWord( msg ); else modelIndex = 0; flags = BF_ReadByte( msg ); + scale = (float)BF_ReadWord( msg ) / 4096.0f; - CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, origin, flags ); + CL_FireCustomDecal( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, origin, flags|FDECAL_CLIPTEST, scale ); } /* @@ -1103,8 +1106,8 @@ void CL_ParseStudioDecal( sizebuf_t *msg ) BF_ReadVec3Coord( msg, pos ); BF_ReadVec3Coord( msg, start ); - decalIndex = BF_ReadShort( msg ); - entityIndex = BF_ReadShort( msg ); + decalIndex = BF_ReadWord( msg ); + entityIndex = BF_ReadWord( msg ); flags = BF_ReadByte( msg ); state.sequence = BF_ReadShort( msg ); @@ -1115,14 +1118,9 @@ void CL_ParseStudioDecal( sizebuf_t *msg ) state.controller[1] = BF_ReadByte( msg ); state.controller[2] = BF_ReadByte( msg ); state.controller[3] = BF_ReadByte( msg ); - - if( cls.state == ca_connected ) - { - // this message came on restore. - // read modelindex in case client models are not linked with entities - // because first client frame has not yet received - modelIndex = BF_ReadShort( msg ); - } + modelIndex = BF_ReadWord( msg ); + state.body = BF_ReadByte( msg ); + state.skin = BF_ReadByte( msg ); if( clgame.drawFuncs.R_StudioDecalShoot != NULL ) { diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 66779678..32a4b895 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -2593,7 +2593,19 @@ normal temporary decal */ void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags ) { - R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, (flags|FDECAL_CLIPTEST), NULL ); + R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, (flags|FDECAL_CLIPTEST), NULL, 1.0f ); +} + +/* +=============== +CL_FireCustomDecal + +custom temporary decal +=============== +*/ +void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags, float scale ) +{ + R_DecalShoot( textureIndex, entityIndex, modelIndex, pos, flags, NULL, scale ); } /* @@ -2605,7 +2617,7 @@ spray custom colored decal (clan logo etc) */ void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos ) { - R_DecalShoot( textureIndex, entityIndex, 0, pos, 0, NULL ); + R_DecalShoot( textureIndex, entityIndex, 0, pos, 0, NULL, 1.0f ); } /* diff --git a/engine/client/client.h b/engine/client/client.h index d82499dc..c4241492 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -292,51 +292,57 @@ typedef struct int flags; // FNETAPI_MULTIPLE_RESPONSE etc } net_request_t; +// new versions of client dlls have a sanigle export with all callbacks +typedef void (*CL_EXPORT_FUNCS)( void *pv ); + +// NOTE: ordering is important! typedef struct { int (*pfnInitialize)( cl_enginefunc_t *pEnginefuncs, int iVersion ); - int (*pfnVidInit)( void ); void (*pfnInit)( void ); - void (*pfnShutdown)( void ); + int (*pfnVidInit)( void ); int (*pfnRedraw)( float flTime, int intermission ); int (*pfnUpdateClientData)( client_data_t *cdata, float flTime ); void (*pfnReset)( void ); void (*pfnPlayerMove)( struct playermove_s *ppmove, int server ); void (*pfnPlayerMoveInit)( struct playermove_s *ppmove ); char (*pfnPlayerMoveTexture)( char *name ); - int (*pfnConnectionlessPacket)( const netadr_t *net_from, const char *args, char *buffer, int *size ); - int (*pfnGetHullBounds)( int hullnumber, float *mins, float *maxs ); - void (*pfnFrame)( double time ); - void (*pfnVoiceStatus)( int entindex, qboolean bTalking ); - void (*pfnDirectorMessage)( int iSize, void *pbuf ); - void (*pfnPostRunCmd)( local_state_t *from, local_state_t *to, usercmd_t *cmd, int runfuncs, double time, uint random_seed ); - int (*pfnKey_Event)( int eventcode, int keynum, const char *pszCurrentBinding ); - void (*pfnDemo_ReadBuffer)( int size, byte *buffer ); - int (*pfnAddEntity)( int type, cl_entity_t *ent, const char *modelname ); - void (*pfnCreateEntities)( void ); - void (*pfnStudioEvent)( const struct mstudioevent_s *event, const cl_entity_t *entity ); - void (*pfnTxferLocalOverrides)( entity_state_t *state, const clientdata_t *client ); - void (*pfnProcessPlayerState)( entity_state_t *dst, const entity_state_t *src ); - void (*pfnTxferPredictionData)( entity_state_t *ps, const entity_state_t *pps, clientdata_t *pcd, const clientdata_t *ppcd, weapon_data_t *wd, const weapon_data_t *pwd ); - void (*pfnTempEntUpdate)( double frametime, double client_time, double cl_gravity, struct tempent_s **ppTempEntFree, struct tempent_s **ppTempEntActive, int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( *Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp )); - int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio ); - void (*pfnChatInputPosition)( int *x, int *y ); - void (*pfnDrawNormalTriangles)( void ); - void (*pfnDrawTransparentTriangles)( void ); - cl_entity_t *(*pfnGetUserEntity)( int index ); - void *(*KB_Find)( const char *name ); - void (*CAM_Think)( void ); // camera stuff - int (*CL_IsThirdPerson)( void ); - void (*CL_CameraOffset)( float *ofs ); - void (*CL_CreateMove)( float frametime, usercmd_t *cmd, int active ); void (*IN_ActivateMouse)( void ); void (*IN_DeactivateMouse)( void ); void (*IN_MouseEvent)( int mstate ); - void (*IN_Accumulate)( void ); void (*IN_ClearStates)( void ); + void (*IN_Accumulate)( void ); + void (*CL_CreateMove)( float frametime, usercmd_t *cmd, int active ); + int (*CL_IsThirdPerson)( void ); + void (*CL_CameraOffset)( float *ofs ); + void *(*KB_Find)( const char *name ); + void (*CAM_Think)( void ); // camera stuff void (*pfnCalcRefdef)( ref_params_t *pparams ); - int (*pfnGetRenderInterface)( int version, render_api_t *renderfuncs, render_interface_t *callback ); + int (*pfnAddEntity)( int type, cl_entity_t *ent, const char *modelname ); + void (*pfnCreateEntities)( void ); + void (*pfnDrawNormalTriangles)( void ); + void (*pfnDrawTransparentTriangles)( void ); + void (*pfnStudioEvent)( const struct mstudioevent_s *event, const cl_entity_t *entity ); + void (*pfnPostRunCmd)( local_state_t *from, local_state_t *to, usercmd_t *cmd, int runfuncs, double time, uint random_seed ); + void (*pfnShutdown)( void ); + void (*pfnTxferLocalOverrides)( entity_state_t *state, const clientdata_t *client ); + void (*pfnProcessPlayerState)( entity_state_t *dst, const entity_state_t *src ); + void (*pfnTxferPredictionData)( entity_state_t *ps, const entity_state_t *pps, clientdata_t *pcd, const clientdata_t *ppcd, weapon_data_t *wd, const weapon_data_t *pwd ); + void (*pfnDemo_ReadBuffer)( int size, byte *buffer ); + int (*pfnConnectionlessPacket)( const netadr_t *net_from, const char *args, char *buffer, int *size ); + int (*pfnGetHullBounds)( int hullnumber, float *mins, float *maxs ); + void (*pfnFrame)( double time ); + int (*pfnKey_Event)( int eventcode, int keynum, const char *pszCurrentBinding ); + void (*pfnTempEntUpdate)( double frametime, double client_time, double cl_gravity, struct tempent_s **ppTempEntFree, struct tempent_s **ppTempEntActive, int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( *Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp )); + cl_entity_t *(*pfnGetUserEntity)( int index ); + void (*pfnVoiceStatus)( int entindex, qboolean bTalking ); + void (*pfnDirectorMessage)( int iSize, void *pbuf ); + int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio ); + void (*pfnChatInputPosition)( int *x, int *y ); int (*pfnGetPlayerTeam)( int playerIndex ); + void *(*pfnGetClientFactory)( void ); + // Xash3D extension + int (*pfnGetRenderInterface)( int version, render_api_t *renderfuncs, render_interface_t *callback ); void (*pfnClipMoveToEntity)( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr ); } HUD_FUNCTIONS; @@ -741,8 +747,10 @@ void CL_ClearAllRemaps( void ); int CL_AddEntity( int entityType, cl_entity_t *pEnt ); void CL_WeaponAnim( int iAnim, int body ); void CL_ClearEffects( void ); +void CL_ClearEfrags( void ); void CL_TestLights( void ); void CL_DrawParticlesExternal( const float *vieworg, const float *fwd, const float *rt, const float *up, uint clipFlags ); +void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags, float scale ); void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags ); void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos ); void CL_InitParticles( void ); diff --git a/engine/client/gl_decals.c b/engine/client/gl_decals.c index c6a158e9..4c61fb96 100644 --- a/engine/client/gl_decals.c +++ b/engine/client/gl_decals.c @@ -27,8 +27,8 @@ GNU General Public License for more details. // empirically determined constants for minimizing overalpping decals #define MAX_OVERLAP_DECALS 6 #define DECAL_OVERLAP_DIST 8 -#define FLOAT_TO_SHORT( x ) (short)(x * 32) -#define SHORT_TO_FLOAT( x ) ((float)x * (1.0f/32.0f)) +#define MIN_DECAL_SCALE 0.01f +#define MAX_DECAL_SCALE 10.0f // clip edges #define LEFT_EDGE 0 @@ -212,8 +212,8 @@ void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t tex for( i = 0, v = surf->polys->verts[0]; i < surf->polys->numverts; i++, v += VERTEXSIZE, verts += VERTEXSIZE ) { VectorCopy( v, verts ); // copy model space coordinates - verts[3] = DotProduct( verts, textureSpaceBasis[0] ) - SHORT_TO_FLOAT( pDecal->dx ) + 0.5f; - verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - SHORT_TO_FLOAT( pDecal->dy ) + 0.5f; + verts[3] = DotProduct( verts, textureSpaceBasis[0] ) - pDecal->dx + 0.5f; + verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f; verts[5] = verts[6] = 0.0f; } } @@ -226,8 +226,8 @@ void R_SetupDecalClip( decal_t *pDecal, msurface_t *surf, int texture, vec3_t te // Generate texture coordinates for each vertex in decal s,t space // probably should pre-generate this, store it and use it for decal-decal collisions // as in R_DecalsIntersect() - pDecal->dx = FLOAT_TO_SHORT( DotProduct( pDecal->position, textureSpaceBasis[0] )); - pDecal->dy = FLOAT_TO_SHORT( DotProduct( pDecal->position, textureSpaceBasis[1] )); + pDecal->dx = DotProduct( pDecal->position, textureSpaceBasis[0] ); + pDecal->dy = DotProduct( pDecal->position, textureSpaceBasis[1] ); } // Quick and dirty sutherland Hodgman clipper @@ -505,15 +505,15 @@ static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int // this decal's (pDecal's) [0,0,1,1] clip space, just like we would if we were // clipping a triangle into pDecal's clip space. Vector2Set( vDecalMin, - DotProduct( testPosition[0], testBasis[0] ) - SHORT_TO_FLOAT( pDecal->dx ) + 0.5f, - DotProduct( testPosition[1], testBasis[1] ) - SHORT_TO_FLOAT( pDecal->dy ) + 0.5f ); + DotProduct( testPosition[0], testBasis[0] ) - pDecal->dx + 0.5f, + DotProduct( testPosition[1], testBasis[1] ) - pDecal->dy + 0.5f ); VectorAdd( decalinfo->m_Position, decalExtents[0], testPosition[0] ); VectorAdd( decalinfo->m_Position, decalExtents[1], testPosition[1] ); Vector2Set( vDecalMax, - DotProduct( testPosition[0], testBasis[0] ) - SHORT_TO_FLOAT( pDecal->dx ) + 0.5f, - DotProduct( testPosition[1], testBasis[1] ) - SHORT_TO_FLOAT( pDecal->dy ) + 0.5f ); + DotProduct( testPosition[0], testBasis[0] ) - pDecal->dx + 0.5f, + DotProduct( testPosition[1], testBasis[1] ) - pDecal->dy + 0.5f ); // Now figure out the part of the projection that intersects pDecal's // clip box [0,0,1,1]. @@ -593,8 +593,8 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl if( pdecal->flags & FDECAL_USESAXIS ) VectorCopy( decalinfo->m_SAxis, pdecal->saxis ); - pdecal->dx = FLOAT_TO_SHORT( x ); - pdecal->dy = FLOAT_TO_SHORT( y ); + pdecal->dx = x; + pdecal->dy = y; pdecal->texture = decalinfo->m_iTexture; // set scaling @@ -758,7 +758,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) } // Shoots a decal onto the surface of the BSP. position is the center of the decal in world coords -void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis ) +void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis, float scale ) { decalinfo_t decalInfo; hull_t *hull; @@ -795,7 +795,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos decalInfo.m_pModel = model; hull = &model->hulls[0]; // always use #0 hull - if( ent ) + if( ent && !( flags & FDECAL_LOCAL_SPACE )) { vec3_t pos_l; @@ -811,7 +811,9 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos { VectorSubtract( pos, ent->origin, pos_l ); } + VectorCopy( pos_l, decalInfo.m_Position ); + flags |= FDECAL_LOCAL_SPACE; // decal position moved into local space } else { @@ -842,7 +844,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos if(( height >> 1 ) > decalInfo.m_Size ) decalInfo.m_Size = height >> 1; - decalInfo.m_scale = 1.0f; + decalInfo.m_scale = bound( MIN_DECAL_SCALE, scale, MAX_DECAL_SCALE ); // compute the decal dimensions in world space decalInfo.m_decalWidth = width / decalInfo.m_scale; @@ -1128,6 +1130,7 @@ int R_CreateDecalList( decallist_t *pList, qboolean changelevel ) pList[total].depth = depth; pList[total].flags = decal->flags; + pList[total].scale = decal->scale; R_DecalUnProject( decal, &pList[total] ); FS_FileBase( R_GetTexture( decal->texture )->name, pList[total].name ); @@ -1197,4 +1200,30 @@ void R_EntityRemoveDecals( model_t *mod ) for( p = psurf->pdecals; p; p = p->pnext ) R_DecalUnlink( p ); } +} + +/* +=============== +R_ClearAllDecals + +remove all decals from anything +used for full decals restart +=============== +*/ +void R_ClearAllDecals( void ) +{ + decal_t *pdecal; + int i; + + // because gDecalCount may be zeroed after recach the decal limit + for( i = 0; i < MAX_RENDER_DECALS; i++ ) + { + pdecal = &gDecalPool[i]; + R_DecalUnlink( pdecal ); + } + + if( clgame.drawFuncs.R_ClearStudioDecals ) + { + clgame.drawFuncs.R_ClearStudioDecals(); + } } \ No newline at end of file diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index c6ed4280..975992f6 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -484,7 +484,7 @@ void GL_SetRenderMode( int mode ); void R_RunViewmodelEvents( void ); void R_DrawViewModel( void ); int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); -void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis ); +void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis, float scale ); void R_RemoveEfrags( struct cl_entity_s *ent ); void R_AddEfrags( struct cl_entity_s *ent ); void R_DecalRemoveAll( int texture ); diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index e9afafb6..99e68018 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -1564,11 +1564,6 @@ static int GL_LoadTextureNoFilter( const char *name, const byte *buf, size_t siz return GL_LoadTexture( name, buf, size, flags, NULL ); } -static void GL_StoreEfrags( efrag_t **ppefrag ) -{ - R_StoreEfrags( ppefrag, tr.framecount ); -} - static const ref_overview_t *GL_GetOverviewParms( void ) { return &clgame.overView; @@ -1587,18 +1582,15 @@ static render_api_t gRenderAPI = R_SetCurrentEntity, R_SetCurrentModel, GL_SetWorldviewProjectionMatrix, - GL_StoreEfrags, + R_StoreEfrags, GL_FindTexture, GL_TextureName, GL_LoadTextureNoFilter, GL_CreateTexture, GL_FreeTexture, DrawSingleDecal, - CL_DrawParticlesExternal, - R_EnvShot, - COM_CompareFileTime, - Host_Error, - pfnSPR_LoadExt, + R_DecalSetupVerts, + R_EntityRemoveDecals, AVI_LoadVideo, AVI_GetVideoInfo, AVI_GetAudioInfo, @@ -1614,11 +1606,13 @@ static render_api_t gRenderAPI = GL_LoadIdentityTexMatrix, GL_CleanUpTextureUnits, GL_TexGen, - R_EntityRemoveDecals, - R_DecalSetupVerts, - R_StoreEfrags, GL_TextureTarget, - R_StudioGetTexture, // moved here to avoid incompatibility with official expanded interface of IEngineStduio (HLSDK Update at 30.08.2013) + CL_DrawParticlesExternal, + R_EnvShot, + COM_CompareFileTime, + Host_Error, + pfnSPR_LoadExt, + R_StudioGetTexture, GL_GetOverviewParms, }; diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index c889ea1c..c764e97a 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -384,6 +384,26 @@ imgfilter_t *R_FindTexFilter( const char *texname ) return NULL; } +/* +======================= +R_ClearStaticEntities + +e.g. by demo request +======================= +*/ +void R_ClearStaticEntities( void ) +{ + int i; + + // clear out efrags in case the level hasn't been reloaded + for( i = 0; i < cl.worldmodel->numleafs; i++ ) + cl.worldmodel->leafs[i+1].efrags = NULL; + + clgame.numStatics = 0; + + CL_ClearEfrags (); +} + void R_NewMap( void ) { texture_t *tx; diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index ffcafe05..02e4fc62 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -112,6 +112,7 @@ char g_nCachedBoneNames[MAXSTUDIOBONES][32]; int g_nCachedBones; // number of bones in cache int g_nStudioCount; // for chrome update int g_iRenderMode; // currentmodel rendermode +int g_iBackFaceCull; vec3_t studio_mins, studio_maxs; float studio_radius; @@ -1835,9 +1836,65 @@ mstudiotexture_t *R_StudioGetTexture( cl_entity_t *e ) return ptexture; } +void R_StudioSetRenderamt( int iRenderamt ) +{ + if( !RI.currententity ) return; + + RI.currententity->curstate.renderamt = iRenderamt; + RI.currententity->curstate.renderamt = R_ComputeFxBlend( RI.currententity ); +} + /* =============== -R_SolidEntityCompare +R_StudioSetCullState + +sets true for enable backculling (for left-hand viewmodel) +=============== +*/ +void R_StudioSetCullState( int iCull ) +{ + g_iBackFaceCull = iCull; +} + +/* +=============== +R_StudioRenderShadow + +just a prefab for render shadow +=============== +*/ +void R_StudioRenderShadow( int iSprite, float *p1, float *p2, float *p3, float *p4 ) +{ + if( !p1 || !p2 || !p3 || !p4 ) + return; + + if( TriSpriteTexture( Mod_Handle( iSprite ), 0 )) + { + pglEnable( GL_BLEND ); + pglDisable( GL_ALPHA_TEST ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglColor4f( 0.0f, 0.0f, 0.0f, 1.0f ); // render only alpha + + pglBegin( GL_QUADS ); + pglTexCoord2f( 0.0f, 0.0f ); + pglVertex3fv( p1 ); + pglTexCoord2f( 0.0f, 1.0f ); + pglVertex3fv( p2 ); + pglTexCoord2f( 1.0f, 1.0f ); + pglVertex3fv( p3 ); + pglTexCoord2f( 1.0f, 0.0f ); + pglVertex3fv( p4 ); + pglEnd(); + + pglDisable( GL_BLEND ); + pglDisable( GL_ALPHA_TEST ); + } +} + +/* +=============== +R_StudioMeshCompare Sorting opaque entities by model type =============== @@ -1972,6 +2029,12 @@ static void R_StudioDrawPoints( void ) pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); pglDepthMask( GL_FALSE ); } + else if( g_nFaceFlags & STUDIO_NF_ALPHA ) + { + GL_SetRenderMode( kRenderTransTexture ); + alpha = RI.currententity->curstate.renderamt * (1.0f / 255.0f); + pglDepthMask( GL_FALSE ); + } else { GL_SetRenderMode( g_iRenderMode ); @@ -2506,6 +2569,9 @@ static void R_StudioSetupRenderer( int rendermode ) // enable depthmask on studiomodels if( glState.drawTrans && g_iRenderMode != kRenderTransAdd ) pglDepthMask( GL_TRUE ); + + if( g_iBackFaceCull ) + GL_FrontFace( true ); } /* @@ -2524,6 +2590,10 @@ static void R_StudioRestoreRenderer( void ) pglDepthMask( GL_FALSE ); else pglDepthMask( GL_TRUE ); + if( g_iBackFaceCull ) + GL_FrontFace( false ); + + g_iBackFaceCull = false; m_fDoRemap = false; } @@ -3266,7 +3336,8 @@ void R_DrawViewModel( void ) pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin )); // backface culling for left-handed weapons - if( r_lefthand->integer == 1 ) GL_FrontFace( !glState.frontFace ); + if( r_lefthand->integer == 1 || g_iBackFaceCull ) + GL_FrontFace( !glState.frontFace ); pStudioDraw->StudioDrawModel( STUDIO_RENDER ); @@ -3274,7 +3345,8 @@ void R_DrawViewModel( void ) pglDepthRange( gldepthmin, gldepthmax ); // backface culling for left-handed weapons - if( r_lefthand->integer == 1 ) GL_FrontFace( !glState.frontFace ); + if( r_lefthand->integer == 1 || g_iBackFaceCull ) + GL_FrontFace( !glState.frontFace ); RI.currententity = NULL; RI.currentmodel = NULL; @@ -3583,7 +3655,9 @@ static engine_studio_api_t gStudioAPI = pfnIsHardware, GL_StudioDrawShadow, GL_SetRenderMode, - R_StudioGetTexture, // Xash3D + R_StudioSetRenderamt, + R_StudioSetCullState, + R_StudioRenderShadow, }; static r_studio_interface_t gStudioDraw = @@ -3608,8 +3682,15 @@ void CL_InitStudioAPI( void ) if( !clgame.dllFuncs.pfnGetStudioModelInterface ) return; + MsgDev( D_NOTE, "InitStudioAPI " ); + if( clgame.dllFuncs.pfnGetStudioModelInterface( STUDIO_INTERFACE_VERSION, &pStudioDraw, &gStudioAPI )) + { + MsgDev( D_NOTE, "- ok\n" ); return; + } + + MsgDev( D_NOTE, "- failed\n" ); // NOTE: we always return true even if game interface was not correct // because we need Draw our StudioModels diff --git a/engine/common/build.c b/engine/common/build.c index e3740ba1..e9be7615 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; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index e6225fa2..9b629b61 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -19,14 +19,6 @@ GNU General Public License for more details. #define MAX_CMD_BUFFER 16384 #define MAX_CMD_LINE 1024 -#define MAX_ALIAS_NAME 32 - -typedef struct cmdalias_s -{ - struct cmdalias_s *next; - char name[MAX_ALIAS_NAME]; - char *value; -} cmdalias_t; typedef struct { @@ -429,16 +421,37 @@ char *Cmd_Args( void ) return cmd_args; } +/* +============ +Cmd_AliasGetList +============ +*/ +struct cmdalias_s *Cmd_AliasGetList( void ) +{ + return cmd_alias; +} + /* ============ Cmd_GetList ============ */ -cmd_t *Cmd_GetList( void ) +struct cmd_s *Cmd_GetFirstFunctionHandle( void ) { return cmd_functions; } +/* +============ +Cmd_GetNext +============ +*/ +struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd ) +{ + return (cmd) ? cmd->next : NULL; +} + + /* ============ Cmd_GetName diff --git a/engine/common/common.c b/engine/common/common.c index e38ac2a1..244bc37d 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -504,6 +504,7 @@ used by CS:CZ */ void *pfnSequenceGet( const char *fileName, const char *entryName ) { + Msg( "Sequence_Get: file %s, entry %s\n", fileName, entryName ); return NULL; } @@ -516,6 +517,9 @@ used by CS:CZ */ void *pfnSequencePickSentence( const char *groupName, int pickMethod, int *picked ) { + Msg( "Sequence_PickSentence: group %s, pickMethod %i\n", groupName, pickMethod ); + *picked = 0; + return NULL; } diff --git a/engine/common/common.h b/engine/common/common.h index f9b3f2c7..40a5d707 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -612,6 +612,7 @@ qboolean Host_NewGame( const char *mapName, qboolean loadGame ); void Host_EndGame( const char *message, ... ); void Host_AbortCurrentFrame( void ); void Host_RestartAmbientSounds( void ); +void Host_RestartDecals( void ); qboolean CL_ChangeGame( const char *gamefolder, qboolean bReset ); void Host_WriteServerConfig( const char *name ); void Host_WriteOpenGLConfig( void ); @@ -661,6 +662,7 @@ void *Cache_Check( byte *mempool, struct cache_user_s *c ); edict_t* pfnPEntityOfEntIndex( int iEntIndex ); void pfnGetModelBounds( model_t *mod, float *mins, float *maxs ); void pfnGetGameDir( char *szGetGameDir ); +int pfnDecalIndex( const char *m ); int pfnGetModelType( model_t *mod ); int pfnIsMapValid( char *filename ); void Con_DPrintf( char *fmt, ... ); @@ -771,7 +773,13 @@ int COM_ExpandFilename( const char *fileName, char *nameOutBuffer, int nameOutBu struct pmtrace_s *PM_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe ); void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch ); void SV_StartMusic( const char *curtrack, const char *looptrack, fs_offset_t position ); +void SV_CreateDecal( struct sizebuf_s *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale ); +void SV_CreateStudioDecal( struct sizebuf_s *msg, const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex, +int flags, struct modelstate_s *state ); +struct sizebuf_s *SV_GetReliableDatagram( void ); int R_CreateDecalList( struct decallist_s *pList, qboolean changelevel ); +void R_ClearAllDecals( void ); +void R_ClearStaticEntities( void ); qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position ); struct cl_entity_s *CL_GetEntityByIndex( int index ); struct cl_entity_s *CL_GetLocalPlayer( void ); @@ -828,10 +836,11 @@ void TrimSpace( const char *source, char *dest ); void GL_FreeImage( const char *name ); void VID_RestoreGamma( void ); void UI_SetActiveMenu( qboolean fActive ); -struct cmd_s *Cmd_GetList( void ); +struct cmd_s *Cmd_GetFirstFunctionHandle( void ); +struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd ); +struct cmdalias_s *Cmd_AliasGetList( void ); char *Cmd_GetName( struct cmd_s *cmd ); cvar_t *Cvar_GetList( void ); -char *Cvar_GetName( cvar_t *cvar ); typedef struct autocomplete_list_s { diff --git a/engine/common/host.c b/engine/common/host.c index f56977a6..e2989fc4 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -20,6 +20,7 @@ GNU General Public License for more details. #include "mathlib.h" #include "input.h" #include "features.h" +#include "render_api.h" // decallist_t typedef void (*pfnChangeGame)( const char *progname ); @@ -383,6 +384,62 @@ void Host_RestartAmbientSounds( void ) } } +/* +================= +Host_RestartDecals + +Write all the decals into demo +================= +*/ +void Host_RestartDecals( void ) +{ + decallist_t *entry; + int decalIndex; + int modelIndex; + sizebuf_t *msg; + int i; + + if( !SV_Active( )) + { + return; + } + + // g-cont. add space for studiodecals if present + host.decalList = (decallist_t *)Z_Malloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 ); + host.numdecals = R_CreateDecalList( host.decalList, false ); + + // remove decals from map + R_ClearAllDecals(); + + // write decals into reliable datagram + msg = SV_GetReliableDatagram(); + + // restore decals and write them into network message + for( i = 0; i < host.numdecals; i++ ) + { + entry = &host.decalList[i]; + + decalIndex = pfnDecalIndex( entry->name ); + modelIndex = pfnPEntityOfEntIndex( entry->entityIndex )->v.modelindex; + + // BSP and studio decals has different messages + if( entry->flags & FDECAL_STUDIO ) + { + // NOTE: studio decal trace start saved into impactPlaneNormal + SV_CreateStudioDecal( msg, entry->position, entry->impactPlaneNormal, decalIndex, entry->entityIndex, + modelIndex, entry->flags, &entry->studio_state ); + } + else + { + SV_CreateDecal( msg, entry->position, decalIndex, entry->entityIndex, modelIndex, entry->flags, entry->scale ); + } + } + + Z_Free( host.decalList ); + host.decalList = NULL; + host.numdecals = 0; +} + /* =================== Host_GetConsoleCommands diff --git a/engine/common/net_buffer.h b/engine/common/net_buffer.h index b9b6f4d5..6e3aa237 100644 --- a/engine/common/net_buffer.h +++ b/engine/common/net_buffer.h @@ -35,7 +35,7 @@ _inline int BitByte( int bits ) return PAD_NUMBER( bits, 8 ) >> 3; } -typedef struct +typedef struct sizebuf_s { qboolean bOverflow; // overflow reading or writing const char *pDebugName; // buffer name (pointer to const name) diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 2e743022..27ec3b42 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -135,6 +135,7 @@ GNU General Public License for more details. #define FDECAL_NOCLIP 0x10 // Decal is not clipped by containing polygon #define FDECAL_USESAXIS 0x20 // Uses the s axis field to determine orientation (footprints) #define FDECAL_STUDIO 0x40 // Indicates a studio decal +#define FDECAL_LOCAL_SPACE 0x80 // decal is in local space (any decal after serialization) // Max number of history commands to send ( 2 by default ) in case of dropped packets #define NUM_BACKUP_COMMAND_BITS 4 diff --git a/engine/eiface.h b/engine/eiface.h index 94a8d4a0..64984b10 100644 --- a/engine/eiface.h +++ b/engine/eiface.h @@ -272,6 +272,7 @@ typedef struct enginefuncs_s void (*pfnResetTutorMessageDecayData)( void ); void (*pfnQueryClientCvarValue)( const edict_t *player, const char *cvarName ); void (*pfnQueryClientCvarValue2)( const edict_t *player, const char *cvarName, int requestID ); + int (*CheckParm)( char *parm, char **ppnext ); } enginefuncs_t; // ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138 diff --git a/engine/server/server.h b/engine/server/server.h index 99e18c6a..9bd3901b 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -553,9 +553,6 @@ void SV_SetModel( edict_t *ent, const char *name ); void SV_CopyTraceToGlobal( trace_t *trace ); void SV_SetMinMaxSize( edict_t *e, const float *min, const float *max ); edict_t* SV_FindEntityByString( edict_t *pStartEdict, const char *pszField, const char *pszValue ); -void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags ); -void SV_CreateStudioDecal( const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex, -int flags, struct modelstate_s *state ); void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ); void SV_PlaybackReliableEvent( sizebuf_t *msg, word eventindex, float delay, event_args_t *args ); @@ -572,15 +569,15 @@ sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, qboolean spawned_only ); void SV_SetClientMaxspeed( sv_client_t *cl, float fNewMaxspeed ); int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name ); void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch ); -void SV_CreateStaticEntity( sv_static_entity_t *ent ); +void SV_CreateStaticEntity( struct sizebuf_s *msg, sv_static_entity_t *ent ); edict_t* pfnPEntityOfEntIndex( int iEntIndex ); int pfnIndexOfEdict( const edict_t *pEdict ); void SV_UpdateBaseVelocity( edict_t *ent ); byte *pfnSetFatPVS( const float *org ); byte *pfnSetFatPAS( const float *org ); int pfnPrecacheModel( const char *s ); -int pfnDecalIndex( const char *m ); int pfnNumberOfEntities( void ); +void SV_RestartStaticEnts( void ); _inline edict_t *SV_EDICT_NUM( int n, const char * file, const int line ) { diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index a2ea8d43..7663cca7 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -1963,6 +1963,10 @@ void SV_ExecuteClientCommand( sv_client_t *cl, char *s ) { // resend the ambient sounds for demo recording Host_RestartAmbientSounds(); + // resend all the decals for demo recording + Host_RestartDecals(); + // resend all the static ents for demo recording + SV_RestartStaticEnts(); } } } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 94e12949..7109971c 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -362,6 +362,18 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent ) return numsends; // debug } +/* +======================= +SV_GetReliableDatagram + +Get shared reliable buffer +======================= +*/ +sizebuf_t *SV_GetReliableDatagram( void ) +{ + return &sv.reliable_datagram; +} + /* ======================= SV_CreateDecal @@ -369,23 +381,24 @@ SV_CreateDecal NOTE: static decals only accepted when game is loading ======================= */ -void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags ) +void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale ) { - if( sv.state != ss_loading ) + if( msg == &sv.signon && sv.state != ss_loading ) return; // this can happens if serialized map contain 4096 static decals... - if(( BF_GetNumBytesWritten( &sv.signon ) + 20 ) >= BF_GetMaxBytes( &sv.signon )) + if(( BF_GetNumBytesWritten( msg ) + 20 ) >= BF_GetMaxBytes( msg )) return; // static decals are posters, it's always reliable - BF_WriteByte( &sv.signon, svc_bspdecal ); - BF_WriteVec3Coord( &sv.signon, origin ); - BF_WriteWord( &sv.signon, decalIndex ); - BF_WriteShort( &sv.signon, entityIndex ); + BF_WriteByte( msg, svc_bspdecal ); + BF_WriteVec3Coord( msg, origin ); + BF_WriteWord( msg, decalIndex ); + BF_WriteShort( msg, entityIndex ); if( entityIndex > 0 ) - BF_WriteWord( &sv.signon, modelIndex ); - BF_WriteByte( &sv.signon, flags ); + BF_WriteWord( msg, modelIndex ); + BF_WriteByte( msg, flags ); + BF_WriteWord( msg, scale * 4096 ); } /* @@ -395,9 +408,9 @@ SV_CreateStudioDecal NOTE: static decals only accepted when game is loading ======================= */ -void SV_CreateStudioDecal( const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex, int flags, modelstate_t *state ) +void SV_CreateStudioDecal( sizebuf_t *msg, const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex, int flags, modelstate_t *state ) { - if( sv.state != ss_loading ) + if( msg == &sv.signon && sv.state != ss_loading ) return; // bad model or bad entity (e.g. changelevel) @@ -408,29 +421,29 @@ void SV_CreateStudioDecal( const float *origin, const float *start, int decalInd ASSERT( start ); // this can happens if serialized map contain 4096 static decals... - if(( BF_GetNumBytesWritten( &sv.signon ) + 28 ) >= BF_GetMaxBytes( &sv.signon )) + if(( BF_GetNumBytesWritten( msg ) + 30 ) >= BF_GetMaxBytes( msg )) return; // static decals are posters, it's always reliable - BF_WriteByte( &sv.signon, svc_studiodecal ); - BF_WriteVec3Coord( &sv.signon, origin ); - BF_WriteVec3Coord( &sv.signon, start ); - BF_WriteWord( &sv.signon, decalIndex ); - BF_WriteShort( &sv.signon, entityIndex ); - BF_WriteByte( &sv.signon, flags ); + BF_WriteByte( msg, svc_studiodecal ); + BF_WriteVec3Coord( msg, origin ); + BF_WriteVec3Coord( msg, start ); + BF_WriteWord( msg, decalIndex ); + BF_WriteWord( msg, entityIndex ); + BF_WriteByte( msg, flags ); // write model state - BF_WriteShort( &sv.signon, state->sequence ); - BF_WriteShort( &sv.signon, state->frame ); - BF_WriteByte( &sv.signon, state->blending[0] ); - BF_WriteByte( &sv.signon, state->blending[1] ); - BF_WriteByte( &sv.signon, state->controller[0] ); - BF_WriteByte( &sv.signon, state->controller[1] ); - BF_WriteByte( &sv.signon, state->controller[2] ); - BF_WriteByte( &sv.signon, state->controller[3] ); - - // write additional data (excluded from the game message) - BF_WriteShort( &sv.signon, modelIndex ); + BF_WriteShort( msg, state->sequence ); + BF_WriteShort( msg, state->frame ); + BF_WriteByte( msg, state->blending[0] ); + BF_WriteByte( msg, state->blending[1] ); + BF_WriteByte( msg, state->controller[0] ); + BF_WriteByte( msg, state->controller[1] ); + BF_WriteByte( msg, state->controller[2] ); + BF_WriteByte( msg, state->controller[3] ); + BF_WriteWord( msg, modelIndex ); + BF_WriteByte( msg, state->body ); + BF_WriteByte( msg, state->skin ); } /* @@ -440,38 +453,61 @@ SV_CreateStaticEntity NOTE: static entities only accepted when game is loading ======================= */ -void SV_CreateStaticEntity( sv_static_entity_t *ent ) +void SV_CreateStaticEntity( sizebuf_t *msg, sv_static_entity_t *ent ) { int index, i; // this can happens if serialized map contain too many static entities... - if(( BF_GetNumBytesWritten( &sv.signon ) + 64 ) >= BF_GetMaxBytes( &sv.signon )) + if(( BF_GetNumBytesWritten( msg ) + 64 ) >= BF_GetMaxBytes( msg )) return; index = SV_ModelIndex( ent->model ); - BF_WriteByte( &sv.signon, svc_spawnstatic ); - BF_WriteShort(&sv.signon, index ); - BF_WriteByte( &sv.signon, ent->sequence ); - BF_WriteByte( &sv.signon, ent->frame ); - BF_WriteWord( &sv.signon, ent->colormap ); - BF_WriteByte( &sv.signon, ent->skin ); + BF_WriteByte( msg, svc_spawnstatic ); + BF_WriteShort(msg, index ); + BF_WriteByte( msg, ent->sequence ); + BF_WriteByte( msg, ent->frame ); + BF_WriteWord( msg, ent->colormap ); + BF_WriteByte( msg, ent->skin ); for( i = 0; i < 3; i++ ) { - BF_WriteCoord( &sv.signon, ent->origin[i] ); - BF_WriteBitAngle( &sv.signon, ent->angles[i], 16 ); + BF_WriteCoord( msg, ent->origin[i] ); + BF_WriteBitAngle( msg, ent->angles[i], 16 ); } - BF_WriteByte( &sv.signon, ent->rendermode ); + BF_WriteByte( msg, ent->rendermode ); if( ent->rendermode != kRenderNormal ) { - BF_WriteByte( &sv.signon, ent->renderamt ); - BF_WriteByte( &sv.signon, ent->rendercolor.r ); - BF_WriteByte( &sv.signon, ent->rendercolor.g ); - BF_WriteByte( &sv.signon, ent->rendercolor.b ); - BF_WriteByte( &sv.signon, ent->renderfx ); + BF_WriteByte( msg, ent->renderamt ); + BF_WriteByte( msg, ent->rendercolor.r ); + BF_WriteByte( msg, ent->rendercolor.g ); + BF_WriteByte( msg, ent->rendercolor.b ); + BF_WriteByte( msg, ent->renderfx ); + } +} + +/* +================= +SV_RestartStaticEnts + +Write all the static ents into demo +================= +*/ +void SV_RestartStaticEnts( void ) +{ + sv_static_entity_t *clent; + int i; + + // remove all the static entities on the client + R_ClearStaticEntities(); + + // resend them again + for( i = 0; i < sv.num_static_entities; i++ ) + { + clent = &sv.static_entities[i]; + SV_CreateStaticEntity( &sv.reliable_datagram, clent ); } } @@ -1642,7 +1678,7 @@ static void pfnMakeStatic( edict_t *ent ) clent->rendercolor.b = ent->v.rendercolor[2]; clent->renderfx = ent->v.renderfx; - SV_CreateStaticEntity( clent ); + SV_CreateStaticEntity( &sv.signon, clent ); // remove at end of the frame ent->v.flags |= FL_KILLME; @@ -2420,7 +2456,7 @@ void pfnMessageBegin( int msg_dest, int msg_num, const float *pOrigin, edict_t * if( msg_num < svc_lastmsg ) { svgame.msg_name = NULL; - svgame.msg_index = -1; // this is a system message + svgame.msg_index = -msg_num; // this is a system message if( msg_num == svc_temp_entity ) { @@ -2484,14 +2520,14 @@ void pfnMessageEnd( void ) svgame.msg_started = false; // HACKHACK: clearing HudText in background mode - if( sv.background && svgame.msg[svgame.msg_index].number == svgame.gmsgHudText ) + if( sv.background && svgame.msg_index >= 0 && svgame.msg[svgame.msg_index].number == svgame.gmsgHudText ) { BF_Clear( &sv.multicast ); return; } // check for system message - if( svgame.msg_index == -1 ) + if( svgame.msg_index < 0 ) { if( svgame.msg_size_index != -1 ) { @@ -2551,6 +2587,15 @@ void pfnMessageEnd( void ) return; } + if( svgame.msg_index < 0 && abs( svgame.msg_index ) == svc_studiodecal && svgame.msg_realsize == 27 ) + { + // oldstyle message for svc_studiodecal has missed four additional bytes: + // modelIndex, skin and body. Write it here for backward compatibility + BF_WriteWord( &sv.multicast, 0 ); + BF_WriteByte( &sv.multicast, 0 ); + BF_WriteByte( &sv.multicast, 0 ); + } + if( !VectorIsNull( svgame.msg_org )) org = svgame.msg_org; svgame.msg_dest = bound( MSG_BROADCAST, svgame.msg_dest, MSG_SPEC ); @@ -3284,7 +3329,7 @@ void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int m return; } - SV_CreateDecal( origin, decalIndex, entityIndex, modelIndex, FDECAL_PERMANENT ); + SV_CreateDecal( &sv.signon, origin, decalIndex, entityIndex, modelIndex, FDECAL_PERMANENT, 1.0f ); } /* @@ -4237,6 +4282,25 @@ void pfnQueryClientCvarValue2( const edict_t *player, const char *cvarName, int MsgDev( D_ERROR, "QueryClientCvarValue: tried to send to a non-client!\n" ); } } + +/* +============= +pfnCheckParm + +============= +*/ +static int pfnCheckParm( char *parm, char **ppnext ) +{ + static char str[64]; + + if( Sys_GetParmFromCmdLine( parm, str )) + { + // get the pointer on cmdline param + if( ppnext ) *ppnext = str; + return 1; + } + return 0; +} // engine callbacks static enginefuncs_t gEngfuncs = @@ -4398,6 +4462,7 @@ static enginefuncs_t gEngfuncs = pfnResetTutorMessageDecayData, pfnQueryClientCvarValue, pfnQueryClientCvarValue2, + pfnCheckParm, }; /* diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 2c7e2dd1..841698b8 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -30,7 +30,7 @@ half-life implementation of saverestore system #define SAVEFILE_HEADER (('V'<<24)+('L'<<16)+('A'<<8)+'V') // little-endian "VALV" #define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV" #define SAVEGAME_VERSION 0x0065 // Version 0.65 -#define CLIENT_SAVEGAME_VERSION 0x0067 // Version 0.67 +#define CLIENT_SAVEGAME_VERSION 0x0068 // Version 0.68 #define SAVE_AGED_COUNT 1 #define SAVENAME_LENGTH 128 // matches with MAX_OSPATH @@ -452,7 +452,7 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja if( flags & FDECAL_STUDIO ) { // NOTE: studio decal trace start saved into impactPlaneNormal - SV_CreateStudioDecal( entry->position, entry->impactPlaneNormal, decalIndex, entityIndex, modelIndex, flags, &entry->studio_state ); + SV_CreateStudioDecal( &sv.signon, entry->position, entry->impactPlaneNormal, decalIndex, entityIndex, modelIndex, flags, &entry->studio_state ); return; } else if( adjacent && entityIndex != 0 && !SV_IsValidEdict( pEdict )) @@ -484,7 +484,7 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja { entityIndex = pfnIndexOfEdict( tr.ent ); if( entityIndex > 0 ) modelIndex = tr.ent->v.modelindex; - SV_CreateDecal( tr.endpos, decalIndex, entityIndex, modelIndex, flags ); + SV_CreateDecal( &sv.signon, tr.endpos, decalIndex, entityIndex, modelIndex, flags, entry->scale ); } } } @@ -492,7 +492,7 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja { // global entity is exist on new level so we can apply decal in local space // NOTE: this case also used for transition world decals - SV_CreateDecal( entry->position, decalIndex, entityIndex, modelIndex, flags ); + SV_CreateDecal( &sv.signon, entry->position, decalIndex, entityIndex, modelIndex, flags, entry->scale ); } } @@ -1100,6 +1100,7 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level ) { vec3_t localPos; decallist_t *entry; + word decalScale; byte nameSize; entry = &decalList[i]; @@ -1109,12 +1110,14 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level ) else VectorCopy( entry->position, localPos ); nameSize = Q_strlen( entry->name ) + 1; + decalScale = (entry->scale * 4096); FS_Write( pFile, localPos, sizeof( localPos )); FS_Write( pFile, &nameSize, sizeof( nameSize )); FS_Write( pFile, entry->name, nameSize ); FS_Write( pFile, &entry->entityIndex, sizeof( entry->entityIndex )); FS_Write( pFile, &entry->flags, sizeof( entry->flags )); + FS_Write( pFile, &decalScale, sizeof( decalScale )); FS_Write( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal )); if( entry->flags & FDECAL_STUDIO ) @@ -1275,6 +1278,7 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean { vec3_t localPos; decallist_t *entry; + word decalScale; byte nameSize; entry = &decalList[i]; @@ -1284,12 +1288,15 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean FS_Read( pFile, entry->name, nameSize ); FS_Read( pFile, &entry->entityIndex, sizeof( entry->entityIndex )); FS_Read( pFile, &entry->flags, sizeof( entry->flags )); + FS_Read( pFile, &decalScale, sizeof( decalScale )); FS_Read( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal )); if( pSaveData->fUseLandmark && ( entry->flags & FDECAL_USE_LANDMARK )) VectorAdd( localPos, pSaveData->vecLandmarkOffset, entry->position ); else VectorCopy( localPos, entry->position ); + entry->scale = ((float)decalScale / 4096.0f); + if( entry->flags & FDECAL_STUDIO ) { // read additional data for studio decals @@ -1345,7 +1352,7 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean FS_Read( pFile, &entry->renderfx, sizeof( entry->renderfx )); } - SV_CreateStaticEntity( entry ); + SV_CreateStaticEntity( &sv.signon, entry ); } } diff --git a/engine/studio.h b/engine/studio.h index 8da834be..972fcba6 100644 --- a/engine/studio.h +++ b/engine/studio.h @@ -65,12 +65,10 @@ Studio models are position independent, so the cache manager can move them. #define STUDIO_NF_CHROME 0x0002 #define STUDIO_NF_FULLBRIGHT 0x0004 #define STUDIO_NF_COLORMAP 0x0008 // can changed by colormap command -#define STUDIO_NF_BLENDED 0x0010 // rendering as semitransparent +#define STUDIO_NF_ALPHA 0x0010 // rendering as semitransparent #define STUDIO_NF_ADDITIVE 0x0020 // rendering with additive mode #define STUDIO_NF_TRANSPARENT 0x0040 // use texture with alpha channel -#define STUDIO_NF_BUMPMAP 0x0080 // heightmap that can be transformed into normalmap and heightmap -#define STUDIO_NF_GLOSSMAP 0x0100 // glossmap -#define STUDIO_NF_LUMATEXTURE 0x0200 // optional luma_texture + #define STUDIO_NF_QUAKESKIN 0x8000 // special hack for determine alias skins // motion flags @@ -102,6 +100,7 @@ Studio models are position independent, so the cache manager can move them. #define STUDIO_HAS_NORMALS 0x0001 #define STUDIO_HAS_VERTICES 0x0002 #define STUDIO_HAS_BBOX 0x0004 +#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them typedef struct {