diff --git a/common/render_api.h b/common/render_api.h index 11cc1334..62b103f7 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -89,7 +89,7 @@ typedef enum TF_UNCOMPRESSED = (1<<5), // don't compress texture in video memory TF_CUBEMAP = (1<<6), // it's cubemap texture TF_DEPTHMAP = (1<<7), // custom texture filter used - TF_INTENSITY = (1<<8), // monochrome intensity image +// reserved TF_LUMINANCE = (1<<9), // force image to grayscale TF_SKYSIDE = (1<<10), // this is a part of skybox TF_CLAMP = (1<<11), // clamp texcoords to [0..1] range @@ -102,10 +102,9 @@ typedef enum TF_TEXTURE_1D = (1<<18), // this is GL_TEXTURE_1D TF_BORDER = (1<<19), // zero clamp for projected textures TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D - TF_STATIC = (1<<21), // obsolete (not used) +// reserved TF_TEXTURE_RECTANGLE= (1<<22), // this is GL_TEXTURE_RECTANGLE - - TF_DXT_FORMAT = (1<<23), // internal flag who indicated DXT-compressed texture +// reserved TF_TEXTURE_2D_ARRAY = (1<<24), // this is 2D texture array (multi-layers) TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage TF_ARB_FLOAT = (1<<26), // float textures diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 4ac42f62..03c1549d 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -326,7 +326,9 @@ qboolean CL_ProcessOverviewCmds( usercmd_t *cmd ) { ref_overview_t *ov = &clgame.overView; int sign = 1; - float step = 100.0f * (cl.time - cl.oldtime); + float size = world.size[!ov->rotated] / world.size[ov->rotated]; + float step = (2.0f / size) * host.realframetime; + float step2 = step * 100.0f * (2.0f / ov->flZoom); if( !gl_overview->integer || gl_showtextures->integer ) return false; @@ -339,22 +341,22 @@ qboolean CL_ProcessOverviewCmds( usercmd_t *cmd ) if( cmd->buttons & IN_JUMP ) ov->zFar += step; else if( cmd->buttons & IN_DUCK ) ov->zFar -= step; - if( cmd->buttons & IN_FORWARD ) ov->origin[ov->rotated] -= sign * step; - else if( cmd->buttons & IN_BACK ) ov->origin[ov->rotated] += sign * step; + if( cmd->buttons & IN_FORWARD ) ov->origin[ov->rotated] -= sign * step2; + else if( cmd->buttons & IN_BACK ) ov->origin[ov->rotated] += sign * step2; if( ov->rotated ) { if( cmd->buttons & ( IN_RIGHT|IN_MOVERIGHT )) - ov->origin[0] -= sign * step; + ov->origin[0] -= sign * step2; else if( cmd->buttons & ( IN_LEFT|IN_MOVELEFT )) - ov->origin[0] += sign * step; + ov->origin[0] += sign * step2; } else { if( cmd->buttons & ( IN_RIGHT|IN_MOVERIGHT )) - ov->origin[1] += sign * step; + ov->origin[1] += sign * step2; else if( cmd->buttons & ( IN_LEFT|IN_MOVELEFT )) - ov->origin[1] -= sign * step; + ov->origin[1] -= sign * step2; } if( cmd->buttons & IN_ATTACK ) ov->flZoom += step; diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 661cda3e..728b4e45 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -652,8 +652,6 @@ static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int chann case PF_DXT3: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case PF_DXT5: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; } - - SetBits( tex->flags, TF_DXT_FORMAT ); return; } else if( FBitSet( tex->flags, TF_DEPTHMAP )) @@ -693,58 +691,40 @@ static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int chann } else if( compressImage ) { - if( tex->flags & TF_INTENSITY ) + switch( GL_CalcTextureSamples( channelMask )) { - tex->format = GL_COMPRESSED_INTENSITY_ARB; - } - else - { - switch( GL_CalcTextureSamples( channelMask )) - { - case 1: tex->format = GL_LUMINANCE8; break; - case 2: tex->format = GL_LUMINANCE8_ALPHA8; break; - case 3: tex->format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; - case 4: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - } - - tex->flags &= ~TF_INTENSITY; + case 1: tex->format = GL_LUMINANCE8; break; + case 2: tex->format = GL_LUMINANCE8_ALPHA8; break; + case 3: tex->format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; + case 4: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; } } else { // NOTE: not all the types will be compressed - if( tex->flags & TF_INTENSITY ) - { - tex->format = GL_INTENSITY8; - } - else - { - int bits = glw_state.desktopBitsPixel; + int bits = glw_state.desktopBitsPixel; - switch( GL_CalcTextureSamples( channelMask ) ) + switch( GL_CalcTextureSamples( channelMask ) ) + { + case 1: tex->format = GL_LUMINANCE8; break; + case 2: tex->format = GL_LUMINANCE8_ALPHA8; break; + case 3: + switch( bits ) { - case 1: tex->format = GL_LUMINANCE8; break; - case 2: tex->format = GL_LUMINANCE8_ALPHA8; break; - case 3: - switch( bits ) - { - case 16: tex->format = GL_RGB5; break; - case 32: tex->format = GL_RGB8; break; - default: tex->format = GL_RGB; break; - } - break; - case 4: - default: - switch( bits ) - { - case 16: tex->format = GL_RGBA4; break; - case 32: tex->format = GL_RGBA8; break; - default: tex->format = GL_RGBA; break; - } - break; + case 16: tex->format = GL_RGB5; break; + case 32: tex->format = GL_RGB8; break; + default: tex->format = GL_RGB; break; } - - tex->flags &= ~TF_INTENSITY; + break; + case 4: + default: + switch( bits ) + { + case 16: tex->format = GL_RGBA4; break; + case 32: tex->format = GL_RGBA8; break; + default: tex->format = GL_RGBA; break; + } + break; } } } diff --git a/engine/common/common.c b/engine/common/common.c index 4af629c8..469e4e3a 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -418,6 +418,25 @@ byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) return COM_LoadFileForMe( filename, pLength ); } +/* +============= +COM_LoadFile + +============= +*/ +int COM_SaveFile( const char *filename, const void *data, long len ) +{ + // check for empty filename + if( !filename || !*filename ) + return false; + + // check for null data + if( !data || len <= 0 ) + return false; + + return FS_WriteFile( filename, data, len ); +} + /* ============= COM_FreeFile diff --git a/engine/common/common.h b/engine/common/common.h index b149be78..deeeff42 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -695,6 +695,7 @@ qboolean SV_Active( void ); cvar_t *pfnCvar_RegisterClientVariable( const char *szName, const char *szValue, int flags ); cvar_t *pfnCvar_RegisterGameUIVariable( const char *szName, const char *szValue, int flags ); char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize ); +int COM_SaveFile( const char *filename, const void *data, long len ); byte* COM_LoadFileForMe( const char *filename, int *pLength ); cvar_t *pfnCVarGetPointer( const char *szVarName ); int pfnDrawConsoleString( int x, int y, char *string ); diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 91b84bc2..69e5d29a 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -67,7 +67,7 @@ qboolean Cmd_GetMapList( const char *s, char *completedname, int length ) int ver = -1, mapver = -1, lumpofs = 0, lumplen = 0; const char *ext = FS_FileExtension( t->filenames[i] ); char *ents = NULL, *pfile; - qboolean paranoia = false; + int version = 0; qboolean gearbox = false; if( Q_stricmp( ext, "bsp" )) continue; @@ -108,8 +108,7 @@ qboolean Cmd_GetMapList( const char *s, char *completedname, int length ) hdrext = (dextrahdr_t *)((byte *)buf + sizeof( dheader31_t )); else hdrext = (dextrahdr_t *)((byte *)buf + sizeof( dheader_t )); - if( hdrext->id == IDEXTRAHEADER && hdrext->version == EXTRA_VERSION ) - paranoia = true; + if( hdrext->id == IDEXTRAHEADER ) version = hdrext->version; Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename )); FS_StripExtension( entfilename ); @@ -163,11 +162,17 @@ qboolean Cmd_GetMapList( const char *s, char *completedname, int length ) break; case HLBSP_VERSION: if( gearbox ) Q_strncpy( buf, "Blue-Shift", sizeof( buf )); - else if( paranoia ) Q_strncpy( buf, "Paranoia 2", sizeof( buf )); + else if( version == 1 ) Q_strncpy( buf, "XashXT old format", sizeof( buf )); + else if( version == 2 ) Q_strncpy( buf, "Paranoia 2: Savior", sizeof( buf )); + else if( version == 3 ) Q_strncpy( buf, "not supported", sizeof( buf )); + else if( version == 4 ) Q_strncpy( buf, "Half-Life extended", sizeof( buf )); else Q_strncpy( buf, "Half-Life", sizeof( buf )); break; case XTBSP_VERSION: - if( paranoia ) Q_strncpy( buf, "Paranoia 2", sizeof( buf )); + if( version == 1 ) Q_strncpy( buf, "XashXT old format", sizeof( buf )); + else if( version == 2 ) Q_strncpy( buf, "Paranoia 2: Savior", sizeof( buf )); + else if( version == 3 ) Q_strncpy( buf, "not supported", sizeof( buf )); + else if( version == 4 ) Q_strncpy( buf, "Xash3D extended", sizeof( buf )); else Q_strncpy( buf, "Xash3D", sizeof( buf )); break; default: Q_strncpy( buf, "??", sizeof( buf )); break; diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index df1d4fda..5b23ac9d 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -2400,8 +2400,9 @@ qboolean FS_WriteFile( const char *filename, const void *data, long len ) return false; } - FS_Write (file, data, len); - FS_Close (file); + FS_Write( file, data, len ); + FS_Close( file ); + return true; } diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 8e8ffa85..c2c94e5b 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -142,6 +142,9 @@ void Mod_TesselatePolygon( msurface_t *surf, model_t *mod, float tessSize ); int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int listsize, int *lastleaf ); int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis ); qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits ); +int Mod_CheckLump( const char *filename, const int lump, int *lumpsize ); +int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ); +int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize ); void Mod_BuildSurfacePolygons( msurface_t *surf, mextrasurf_t *info ); void Mod_AmbientLevels( const vec3_t p, byte *pvolumes ); int Mod_SampleSizeForFace( msurface_t *surf ); diff --git a/engine/common/model.c b/engine/common/model.c index 72f2cfee..69554e32 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -22,6 +22,7 @@ GNU General Public License for more details. #include "gl_local.h" #include "features.h" #include "client.h" +#include "physint.h" // LUMP_ error codes #define MAX_SIDE_VERTS 512 // per one polygon @@ -3336,4 +3337,235 @@ model_t *Mod_Handle( int handle ) return NULL; } return com_models[handle]; +} + +/* +================== +Mod_CheckLump + +check lump for existing +================== +*/ +int Mod_CheckLump( const char *filename, const int lump, int *lumpsize ) +{ + file_t *f = FS_Open( filename, "rb", true ); + byte buffer[sizeof( dheader31_t ) + sizeof( dextrahdr_t )]; + size_t prefetch_size = sizeof( buffer ); + dextrahdr_t *extrahdr; + dheader_t *header; + + if( !f ) return LUMP_LOAD_COULDNT_OPEN; + + if( FS_Read( f, buffer, prefetch_size ) != prefetch_size ) + { + FS_Close( f ); + return LUMP_LOAD_BAD_HEADER; + } + + header = (dheader_t *)buffer; + + if( header->version != HLBSP_VERSION && header->version != XTBSP_VERSION ) + { + FS_Close( f ); + return LUMP_LOAD_BAD_VERSION; + } + + // BSP31 and BSP30 have different offsets + if( header->version == XTBSP_VERSION ) + extrahdr = (dextrahdr_t *)((byte *)buffer + sizeof( dheader31_t )); + else extrahdr = (dextrahdr_t *)((byte *)buffer + sizeof( dheader_t )); + + if( extrahdr->id != IDEXTRAHEADER || extrahdr->version != EXTRA_VERSION ) + { + FS_Close( f ); + return LUMP_LOAD_NO_EXTRADATA; + } + + if( lump < 0 || lump >= EXTRA_LUMPS ) + { + FS_Close( f ); + return LUMP_LOAD_INVALID_NUM; + } + + if( extrahdr->lumps[lump].filelen <= 0 ) + { + FS_Close( f ); + return LUMP_LOAD_NOT_EXIST; + } + + if( lumpsize ) + *lumpsize = extrahdr->lumps[lump].filelen; + + FS_Close( f ); + + return LUMP_LOAD_OK; +} + +/* +================== +Mod_ReadLump + +reading random lump by user request +================== +*/ +int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ) +{ + file_t *f = FS_Open( filename, "rb", true ); + byte buffer[sizeof( dheader31_t ) + sizeof( dextrahdr_t )]; + size_t prefetch_size = sizeof( buffer ); + dextrahdr_t *extrahdr; + dheader_t *header; + byte *data; + int length; + + if( !f ) return LUMP_LOAD_COULDNT_OPEN; + + if( FS_Read( f, buffer, prefetch_size ) != prefetch_size ) + { + FS_Close( f ); + return LUMP_LOAD_BAD_HEADER; + } + + header = (dheader_t *)buffer; + + if( header->version != HLBSP_VERSION && header->version != XTBSP_VERSION ) + { + FS_Close( f ); + return LUMP_LOAD_BAD_VERSION; + } + + // BSP31 and BSP30 have different offsets + if( header->version == XTBSP_VERSION ) + extrahdr = (dextrahdr_t *)((byte *)buffer + sizeof( dheader31_t )); + else extrahdr = (dextrahdr_t *)((byte *)buffer + sizeof( dheader_t )); + + if( extrahdr->id != IDEXTRAHEADER || extrahdr->version != EXTRA_VERSION ) + { + FS_Close( f ); + return LUMP_LOAD_NO_EXTRADATA; + } + + if( lump < 0 || lump >= EXTRA_LUMPS ) + { + FS_Close( f ); + return LUMP_LOAD_INVALID_NUM; + } + + if( extrahdr->lumps[lump].filelen <= 0 ) + { + FS_Close( f ); + return LUMP_LOAD_NOT_EXIST; + } + + data = malloc( extrahdr->lumps[lump].filelen + 1 ); + length = extrahdr->lumps[lump].filelen; + + if( !data ) + { + FS_Close( f ); + return LUMP_LOAD_MEM_FAILED; + } + + FS_Seek( f, extrahdr->lumps[lump].fileofs, SEEK_SET ); + + if( FS_Read( f, data, length ) != length ) + { + Mem_Free( data ); + FS_Close( f ); + return LUMP_LOAD_CORRUPTED; + } + + data[length] = 0; // write term + FS_Close( f ); + + if( lumpsize ) + *lumpsize = length; + *lumpdata = data; + + return LUMP_LOAD_OK; +} + +/* +================== +Mod_SaveLump + +writing lump by user request +only empty lumps is allows +================== +*/ +int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize ) +{ + file_t *f = FS_Open( filename, "e+b", true ); + byte buffer[sizeof( dheader31_t ) + sizeof( dextrahdr_t )]; + size_t prefetch_size = sizeof( buffer ); + dextrahdr_t *extrahdr; + dheader_t *header; + + if( !f ) return LUMP_SAVE_COULDNT_OPEN; + + if( !lumpdata || lumpsize <= 0 ) + return LUMP_SAVE_NO_DATA; + + if( FS_Read( f, buffer, prefetch_size ) != prefetch_size ) + { + FS_Close( f ); + return LUMP_SAVE_BAD_HEADER; + } + + header = (dheader_t *)buffer; + + if( header->version != HLBSP_VERSION && header->version != XTBSP_VERSION ) + { + FS_Close( f ); + return LUMP_SAVE_BAD_VERSION; + } + + // BSP31 and BSP30 have different offsets + if( header->version == XTBSP_VERSION ) + extrahdr = (dextrahdr_t *)((byte *)buffer + sizeof( dheader31_t )); + else extrahdr = (dextrahdr_t *)((byte *)buffer + sizeof( dheader_t )); + + if( extrahdr->id != IDEXTRAHEADER || extrahdr->version != EXTRA_VERSION ) + { + FS_Close( f ); + return LUMP_SAVE_NO_EXTRADATA; + } + + if( lump < 0 || lump >= EXTRA_LUMPS ) + { + FS_Close( f ); + return LUMP_SAVE_INVALID_NUM; + } + + if( extrahdr->lumps[lump].filelen != 0 ) + { + FS_Close( f ); + return LUMP_SAVE_ALREADY_EXIST; + } + + FS_Seek( f, 0, SEEK_END ); + + // will be saved later + extrahdr->lumps[lump].fileofs = FS_Tell( f ); + extrahdr->lumps[lump].filelen = lumpsize; + + if( FS_Write( f, lumpdata, lumpsize ) != lumpsize ) + { + FS_Close( f ); + return LUMP_SAVE_CORRUPTED; + } + + // update the header + if( header->version == XTBSP_VERSION ) + FS_Seek( f, sizeof( dheader31_t ), SEEK_SET ); + else FS_Seek( f, sizeof( dheader_t ), SEEK_SET ); + + if( FS_Write( f, extrahdr, sizeof( dextrahdr_t )) != sizeof( dextrahdr_t )) + { + FS_Close( f ); + return LUMP_SAVE_CORRUPTED; + } + + FS_Close( f ); + return LUMP_SAVE_OK; } \ No newline at end of file diff --git a/engine/physint.h b/engine/physint.h index 14f068ce..d528d917 100644 --- a/engine/physint.h +++ b/engine/physint.h @@ -26,6 +26,28 @@ GNU General Public License for more details. #define SERVER_LOADING 1 #define SERVER_ACTIVE 2 +// LUMP reading errors +#define LUMP_LOAD_OK 0 +#define LUMP_LOAD_COULDNT_OPEN 1 +#define LUMP_LOAD_BAD_HEADER 2 +#define LUMP_LOAD_BAD_VERSION 3 +#define LUMP_LOAD_NO_EXTRADATA 4 +#define LUMP_LOAD_INVALID_NUM 5 +#define LUMP_LOAD_NOT_EXIST 6 +#define LUMP_LOAD_MEM_FAILED 7 +#define LUMP_LOAD_CORRUPTED 8 + +// LUMP saving errors +#define LUMP_SAVE_OK 0 +#define LUMP_SAVE_COULDNT_OPEN 1 +#define LUMP_SAVE_BAD_HEADER 2 +#define LUMP_SAVE_BAD_VERSION 3 +#define LUMP_SAVE_NO_EXTRADATA 4 +#define LUMP_SAVE_INVALID_NUM 5 +#define LUMP_SAVE_ALREADY_EXIST 6 +#define LUMP_SAVE_NO_DATA 7 +#define LUMP_SAVE_CORRUPTED 8 + typedef struct areanode_s { int axis; // -1 = leaf node @@ -64,6 +86,22 @@ typedef struct server_physics_api_s // static allocations void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ); void (*pfnMemFree)( void *mem, const char *filename, const int fileline ); + + // trace & contents + int (*pfnMaskPointContents)( const float *pos, int groupmask ); + trace_t (*pfnTrace)( const float *p0, float *mins, float *maxs, const float *p1, int type, edict_t *e ); + trace_t (*pfnTraceNoEnts)( const float *p0, float *mins, float *maxs, const float *p1, int type, edict_t *e ); + int (*pfnBoxInPVS)( const float *org, const float *boxmins, const float *boxmaxs ); + + // message handler (missed function to write raw bytes) + void (*pfnWriteBytes)( byte *bytes, int count ); + + // BSP lump management + int (*pfnCheckLump)( const char *filename, const int lump, int *lumpsize ); + int (*pfnReadLump)( const char *filename, const int lump, void **lumpdata, int *lumpsize ); + int (*pfnSaveLump)( const char *filename, const int lump, void *lumpdata, int lumpsize ); + + int (*pfnSaveFile)( const char *filename, const void *data, long len ); } server_physics_api_t; // physic callbacks @@ -109,6 +147,8 @@ typedef struct physics_interface_s const char* (*pfnGetString)( string_t iString ); // helper for restore custom decals that have custom message (e.g. Paranoia) int (*pfnRestoreDecal)( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent ); + // handle custom trigger touching for player + void (*PM_PlayerTouch)( struct playermove_s *ppmove, edict_t *client ); } physics_interface_t; #endif//PHYSINT_H \ No newline at end of file diff --git a/engine/server/server.h b/engine/server/server.h index 4e33e767..8a3a5010 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -555,6 +555,7 @@ edict_t* SV_FindEntityByString( edict_t *pStartEdict, const char *pszField, cons 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 ); +qboolean SV_BoxInPVS( const vec3_t org, const vec3_t absmin, const vec3_t absmax ); void SV_BaselineForEntity( edict_t *pEdict ); void SV_WriteEntityPatch( const char *filename ); char *SV_ReadEntityScript( const char *filename, int *flags ); @@ -571,6 +572,7 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float void SV_CreateStaticEntity( struct sizebuf_s *msg, sv_static_entity_t *ent ); edict_t* pfnPEntityOfEntIndex( int iEntIndex ); int pfnIndexOfEdict( const edict_t *pEdict ); +void pfnWriteBytes( const byte *bytes, int count ); void SV_UpdateBaseVelocity( edict_t *ent ); byte *pfnSetFatPVS( const float *org ); byte *pfnSetFatPAS( const float *org ); diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index c2a41d46..d625bfea 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -529,7 +529,7 @@ SV_BoxInPVS check brush boxes in fat pvs ============== */ -static qboolean SV_BoxInPVS( const vec3_t org, const vec3_t absmin, const vec3_t absmax ) +qboolean SV_BoxInPVS( const vec3_t org, const vec3_t absmin, const vec3_t absmax ) { byte *vis = Mod_GetPVSForPoint( org ); @@ -2115,6 +2115,9 @@ static int pfnTraceMonsterHull( edict_t *pEdict, const float *v1, const float *v return 1; } + if( pEdict != pentToSkip ) + MsgDev( D_ERROR, "TRACE_MONSTER_HULL: pEdict != pentToSkip\n" ); + trace = SV_Move( v1, pEdict->v.mins, pEdict->v.maxs, v2, fNoMonsters, pentToSkip ); if( ptr ) SV_ConvertTrace( ptr, &trace ); @@ -2640,6 +2643,18 @@ void pfnWriteCoord( float flValue ) svgame.msg_realsize += 2; } +/* +============= +pfnWriteBytes + +============= +*/ +void pfnWriteBytes( const byte *bytes, int count ) +{ + MSG_WriteBytes( &sv.multicast, bytes, count ); + svgame.msg_realsize += count; +} + /* ============= pfnWriteString diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 5829ef8a..adde6358 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -232,21 +232,23 @@ qboolean SV_PlayerRunThink( edict_t *ent, float frametime, double time ) { float thinktime; - if(!( ent->v.flags & (FL_KILLME|FL_DORMANT ))) + if( !FBitSet( ent->v.flags, FL_KILLME|FL_DORMANT )) { thinktime = ent->v.nextthink; - if( thinktime <= 0.0f || thinktime > time + frametime ) + if( thinktime <= 0.0f || (time + frametime) < thinktime ) return true; - if( thinktime > time ) - thinktime = time; + if( thinktime < time ) + thinktime = time; // don't let things stay in the past. + // it is possible to start that way + // by a trigger with a local time. ent->v.nextthink = 0.0f; svgame.globals->time = thinktime; svgame.dllFuncs.pfnThink( ent ); } - if( ent->v.flags & FL_KILLME ) + if( FBitSet( ent->v.flags, FL_KILLME )) SV_FreeEdict( ent ); return !ent->free; @@ -1929,6 +1931,26 @@ static void pfnMem_Free( void *mem, const char *filename, const int fileline ) _Mem_Free( mem, filename, fileline ); } +/* +============= +pfnPointContents + +============= +*/ +static int pfnPointContents( const float *pos, int groupmask ) +{ + int oldmask, cont; + + if( !pos ) return CONTENTS_NONE; + oldmask = svs.groupmask; + + svs.groupmask = groupmask; + cont = SV_PointContents( pos ); + svs.groupmask = oldmask; // restore old mask + + return cont; +} + static server_physics_api_t gPhysicsAPI = { SV_LinkEdict, @@ -1951,6 +1973,15 @@ static server_physics_api_t gPhysicsAPI = GL_TextureData, pfnMem_Alloc, pfnMem_Free, + pfnPointContents, + SV_Move, + SV_MoveNoEnts, + SV_BoxInPVS, + pfnWriteBytes, + Mod_CheckLump, + Mod_ReadLump, + Mod_SaveLump, + COM_SaveFile, }; /* diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index 3e57a7d0..b17f0142 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -1095,29 +1095,37 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed ) // copy results back to client SV_FinishPMove( svgame.pmove, cl ); - - // link into place and touch triggers - SV_LinkEdict( clent, true ); - VectorCopy( clent->v.velocity, oldvel ); // save velocity - // touch other objects - for( i = 0; i < svgame.pmove->numtouch; i++ ) + if( svgame.physFuncs.PM_PlayerTouch != NULL ) { - // never touch the objects when "playersonly" is active - if( i == MAX_PHYSENTS || ( sv.hostflags & SVF_PLAYERSONLY )) - break; - - pmtrace = &svgame.pmove->touchindex[i]; - touch = EDICT_NUM( svgame.pmove->physents[pmtrace->ent].info ); - if( touch == clent ) continue; - - VectorCopy( pmtrace->deltavelocity, clent->v.velocity ); - SV_ConvertPMTrace( &trace, pmtrace, touch ); - SV_Impact( touch, clent, &trace ); + // run custom impact function + svgame.physFuncs.PM_PlayerTouch( svgame.pmove, clent ); } + else + { + // link into place and touch triggers + SV_LinkEdict( clent, true ); + VectorCopy( clent->v.velocity, oldvel ); // save velocity - // restore velocity - VectorCopy( oldvel, clent->v.velocity ); + // touch other objects + for( i = 0; i < svgame.pmove->numtouch; i++ ) + { + // never touch the objects when "playersonly" is active + if( i == MAX_PHYSENTS || ( sv.hostflags & SVF_PLAYERSONLY )) + break; + + pmtrace = &svgame.pmove->touchindex[i]; + touch = EDICT_NUM( svgame.pmove->physents[pmtrace->ent].info ); + if( touch == clent ) continue; + + VectorCopy( pmtrace->deltavelocity, clent->v.velocity ); + SV_ConvertPMTrace( &trace, pmtrace, touch ); + SV_Impact( touch, clent, &trace ); + } + + // restore velocity + VectorCopy( oldvel, clent->v.velocity ); + } svgame.pmove->numtouch = 0; svgame.globals->time = cl->timebase;