29 Sep 2009
This commit is contained in:
parent
587d7f70f0
commit
d87d09b959
|
@ -1,65 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<pre>
|
||||
<h1>Build Log</h1>
|
||||
<h3>
|
||||
--------------------Configuration: client - Win32 Debug--------------------
|
||||
</h3>
|
||||
<h3>Command Lines</h3>
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F7.tmp" with contents
|
||||
[
|
||||
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "../common" /I "global" /I "hud" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\client\!debug/" /Fo"..\temp\client\!debug/" /Fd"..\temp\client\!debug/" /FD /c
|
||||
"D:\Xash3D\src_main\client\global\dll_int.cpp"
|
||||
]
|
||||
Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F7.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F8.tmp" with contents
|
||||
[
|
||||
msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\client\!debug/client.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /def:".\client.def" /out:"..\temp\client\!debug/client.dll" /implib:"..\temp\client\!debug/client.lib" /pdbtype:sept /libpath:"..\common\libs"
|
||||
"\Xash3D\src_main\temp\client\!debug\dll_int.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_ammo.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_ammohistory.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_battery.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_death.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_flashlight.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_geiger.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_health.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_icons.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_menu.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_message.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_motd.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_msg.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_saytext.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_scoreboard.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_sound.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_statusbar.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_text.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_train.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_warhead.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\hud_zoom.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\tempents.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\triapi.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\utils.obj"
|
||||
"\Xash3D\src_main\temp\client\!debug\view.obj"
|
||||
]
|
||||
Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F8.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F9.bat" with contents
|
||||
[
|
||||
@echo off
|
||||
copy \Xash3D\src_main\temp\client\!debug\client.dll "D:\Xash3D\bin\client.dll"
|
||||
]
|
||||
Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1F9.bat"
|
||||
Compiling...
|
||||
dll_int.cpp
|
||||
Linking...
|
||||
<h3>Output Window</h3>
|
||||
Performing Custom Build Step on \Xash3D\src_main\temp\client\!debug\client.dll
|
||||
‘ª®¯¨à®¢ ® ä ©«®¢: 1.
|
||||
|
||||
|
||||
|
||||
<h3>Results</h3>
|
||||
client.dll - 0 error(s), 0 warning(s)
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -10,6 +10,7 @@
|
|||
#include "hud.h"
|
||||
|
||||
cl_enginefuncs_t g_engfuncs;
|
||||
cl_globalvars_t *gpGlobals;
|
||||
CHud gHUD;
|
||||
|
||||
// main DLL entry point
|
||||
|
@ -42,7 +43,7 @@ static HUD_FUNCTIONS gFunctionTable =
|
|||
//=======================================================================
|
||||
// GetApi
|
||||
//=======================================================================
|
||||
int CreateAPI( HUD_FUNCTIONS *pFunctionTable, cl_enginefuncs_t* pEngfuncsFromEngine )
|
||||
int CreateAPI( HUD_FUNCTIONS *pFunctionTable, cl_enginefuncs_t* pEngfuncsFromEngine, cl_globalvars_t *pGlobals )
|
||||
{
|
||||
if( !pFunctionTable || !pEngfuncsFromEngine )
|
||||
{
|
||||
|
@ -52,6 +53,7 @@ int CreateAPI( HUD_FUNCTIONS *pFunctionTable, cl_enginefuncs_t* pEngfuncsFromEng
|
|||
// copy HUD_FUNCTIONS table to engine, copy engfuncs table from engine
|
||||
memcpy( pFunctionTable, &gFunctionTable, sizeof( HUD_FUNCTIONS ));
|
||||
memcpy( &g_engfuncs, pEngfuncsFromEngine, sizeof( cl_enginefuncs_t ));
|
||||
gpGlobals = pGlobals;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -72,6 +74,15 @@ void HUD_Init( void )
|
|||
|
||||
int HUD_Redraw( float flTime, int state )
|
||||
{
|
||||
static int oldstate;
|
||||
|
||||
if( oldstate == CL_ACTIVE && state == CL_LOADING )
|
||||
{
|
||||
// draw only once to prevent multiply GL_BLEND each frame
|
||||
DrawImageBar( 100, "m_loading" ); // HACKHACK
|
||||
}
|
||||
oldstate = state;
|
||||
|
||||
switch( state )
|
||||
{
|
||||
case CL_DISCONNECTED:
|
||||
|
@ -94,18 +105,13 @@ int HUD_UpdateClientData( client_data_t *cdata, float flTime )
|
|||
return gHUD.UpdateClientData( cdata, flTime );
|
||||
}
|
||||
|
||||
void HUD_UpdateEntityVars( edict_t *ent, skyportal_t *sky, const entity_state_t *state, const entity_state_t *old )
|
||||
void HUD_UpdateEntityVars( edict_t *ent, skyportal_t *sky, const entity_state_t *state, const entity_state_t *prev )
|
||||
{
|
||||
int i;
|
||||
float m_fLerp;
|
||||
const entity_state_t *prev;
|
||||
|
||||
if( state->ed_flags & ESF_NODELTA )
|
||||
prev = state;
|
||||
else prev = old;
|
||||
|
||||
if( state->ed_type == ED_CLIENT && state->ed_flags & ESF_NO_PREDICTION )
|
||||
m_fLerp = 1.0f; // FIXME: use 0.0f ?
|
||||
m_fLerp = 1.0f;
|
||||
else m_fLerp = GetLerpFrac();
|
||||
|
||||
// copy state to progs
|
||||
|
|
|
@ -549,17 +549,18 @@ void DrawImageBar( float percent, const char *szSpriteName, int x, int y )
|
|||
// 27/12/08 moved here from cl_view.c
|
||||
//
|
||||
void V_RenderPlaque( void )
|
||||
{
|
||||
if( gHUD.m_iDrawPlaque )
|
||||
{
|
||||
const char *levelshot;
|
||||
|
||||
levelshot = CVAR_GET_STRING( "cl_levelshot_name" );
|
||||
|
||||
// logo that shows up while upload next level
|
||||
levelshot = CVAR_GET_STRING( "cl_levelshot_name" );
|
||||
DrawImageRectangle( SPR_Load( levelshot ));
|
||||
DrawImageBar( CVAR_GET_FLOAT( "scr_loading" ), "m_loading" );
|
||||
}
|
||||
|
||||
if( !CVAR_GET_FLOAT( "scr_download" )) return;
|
||||
|
||||
DrawImageBar( CVAR_GET_FLOAT( "scr_download" ), "m_download", (ScreenWidth-128)/2, ScreenHeight-60 );
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ extern cl_enginefuncs_t g_engfuncs;
|
|||
|
||||
#include "enginecallback.h"
|
||||
|
||||
extern cl_globalvars_t *gpGlobals;
|
||||
|
||||
extern int HUD_VidInit( void );
|
||||
extern void HUD_Init( void );
|
||||
extern int HUD_Redraw( float flTime, int state );
|
||||
|
@ -70,6 +72,10 @@ typedef struct dllfunction_s
|
|||
}
|
||||
|
||||
#define HOOK_COMMAND( x, y ) (*g_engfuncs.pfnAddCommand)( x, __CmdFunc_##y, "user-defined command" );
|
||||
#define DECLARE_HUDCOMMAND( x ) void __CmdFunc_##x( void ) \
|
||||
{ \
|
||||
gHUD.UserCmd_##x( ); \
|
||||
}
|
||||
#define DECLARE_COMMAND( y, x ) void __CmdFunc_##x( void ) \
|
||||
{ \
|
||||
gHUD.##y.UserCmd_##x( ); \
|
||||
|
|
|
@ -71,6 +71,7 @@ void CHud :: VidInit( void )
|
|||
// Load Sprites
|
||||
// ---------
|
||||
|
||||
m_iDrawPlaque = 1;
|
||||
m_hsprCursor = 0;
|
||||
m_hHudError = 0;
|
||||
m_hHudFont = 0;
|
||||
|
@ -239,6 +240,7 @@ int CHud :: Redraw( float flTime )
|
|||
|
||||
// make levelshot if needed
|
||||
MAKE_LEVELSHOT();
|
||||
m_iDrawPlaque = 1; // clear plaque stuff
|
||||
|
||||
// draw screen fade before hud
|
||||
DrawScreenFade();
|
||||
|
|
|
@ -667,6 +667,9 @@ public:
|
|||
int _cdecl MsgFunc_Particle( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_TempEntity( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
// user commansds
|
||||
void _cdecl UserCmd_LoadingPlaque( void );
|
||||
|
||||
// filled in VidInit
|
||||
struct
|
||||
{
|
||||
|
@ -681,6 +684,7 @@ public:
|
|||
int m_iWeaponBits;
|
||||
int m_fPlayerDead;
|
||||
int m_iIntermission;
|
||||
int m_iDrawPlaque;
|
||||
|
||||
RainData Rain; // buz rain
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ DECLARE_HUDMESSAGE( TempEntity );
|
|||
DECLARE_HUDMESSAGE( ServerName );
|
||||
DECLARE_HUDMESSAGE( ScreenShake );
|
||||
DECLARE_HUDMESSAGE( Intermission );
|
||||
DECLARE_HUDCOMMAND( LoadingPlaque );
|
||||
|
||||
int CHud :: InitMessages( void )
|
||||
{
|
||||
|
@ -70,6 +71,8 @@ int CHud :: InitMessages( void )
|
|||
HOOK_MESSAGE( ScreenFade );
|
||||
HOOK_MESSAGE( ScreenShake );
|
||||
|
||||
HOOK_COMMAND( "plaque", LoadingPlaque );
|
||||
|
||||
viewEntityIndex = 0; // trigger_viewset stuff
|
||||
viewFlags = 0;
|
||||
m_flFOV = 0;
|
||||
|
@ -99,6 +102,12 @@ int CHud :: InitMessages( void )
|
|||
return 1;
|
||||
}
|
||||
|
||||
void CHud :: UserCmd_LoadingPlaque( void )
|
||||
{
|
||||
ALERT( at_console, "SCR_DisablePlaque()\n" );
|
||||
m_iDrawPlaque = 0; // disable plaque rendering
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
// clear all hud data
|
||||
|
|
|
@ -16,6 +16,7 @@ typedef void (*pfnEventHook)( struct event_args_s *args );
|
|||
|
||||
#include "trace_def.h"
|
||||
#include "event_api.h"
|
||||
#include "gameinfo.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -51,6 +52,24 @@ typedef struct client_data_s
|
|||
float mouse_sensitivity; // used for menus and zoomed weapons
|
||||
} client_data_t;
|
||||
|
||||
typedef struct cl_globalvars_s
|
||||
{
|
||||
float time; // time from server
|
||||
float frametime;
|
||||
string_t mapname;
|
||||
|
||||
BOOL deathmatch;
|
||||
BOOL coop;
|
||||
BOOL teamplay;
|
||||
|
||||
int serverflags;
|
||||
int maxClients;
|
||||
int maxEntities;
|
||||
int numEntities; // actual ents count
|
||||
|
||||
dll_gameinfo_t GameInfo; // shared gameinfo
|
||||
} cl_globalvars_t;
|
||||
|
||||
typedef struct cl_enginefuncs_s
|
||||
{
|
||||
// interface validator
|
||||
|
@ -166,6 +185,6 @@ typedef struct
|
|||
void (*pfnStopPitchDrift)( void );
|
||||
} HUD_FUNCTIONS;
|
||||
|
||||
typedef int (*CLIENTAPI)( HUD_FUNCTIONS *pFunctionTable, cl_enginefuncs_t* pEngfuncsFromEngine );
|
||||
typedef int (*CLIENTAPI)( HUD_FUNCTIONS *pFunctionTable, cl_enginefuncs_t* engfuncs, cl_globalvars_t *pGlobals );
|
||||
|
||||
#endif//CLGAME_API_H
|
|
@ -74,7 +74,6 @@ typedef struct entvars_s
|
|||
|
||||
int sequence; // ENG [all], NET [all], animation sequence
|
||||
int gaitsequence; // NET [player], movement animation sequence for player (0 for none)
|
||||
int weaponanim; // NET [all], weaponmodel animation sequencs
|
||||
float frame; // NET [all], % playback position in animation sequences (0..255)
|
||||
float animtime; // NET [all], world time when frame was set
|
||||
float framerate; // NET [all], animation playback rate (-8x to 8x)
|
||||
|
|
|
@ -88,7 +88,6 @@ typedef struct entity_state_s
|
|||
int gaitsequence; // client\nps\bot gaitsequence
|
||||
int viewmodel; // contains viewmodel index
|
||||
int weaponmodel; // contains weaponmodel index
|
||||
int weaponanim; // weaponmodel sequence
|
||||
int weaponbody; // weaponmodel body
|
||||
int weaponskin; // weaponmodel skin
|
||||
float idealpitch; // client idealpitch
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef struct dll_gameinfo_s
|
|||
|
||||
string_t sp_entity; // e.g. info_player_start
|
||||
string_t dm_entity; // e.g. info_player_deathmatch
|
||||
string_t coop_entity; // e.g. info_player_coop
|
||||
string_t ctf_entity; // e.g. info_player_ctf
|
||||
string_t team_entity; // e.g. info_player_team
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ void CL_WriteDemoHeader( const char *name )
|
|||
{
|
||||
char buf_data[MAX_MSGLEN];
|
||||
entity_state_t *state, nullstate;
|
||||
edict_t *ent;
|
||||
sizebuf_t buf;
|
||||
int i, len;
|
||||
|
||||
|
@ -85,12 +84,10 @@ void CL_WriteDemoHeader( const char *name )
|
|||
// baselines
|
||||
Mem_Set( &nullstate, 0, sizeof( nullstate ));
|
||||
|
||||
for( i = 0; i < clgame.numEntities; i++ )
|
||||
for( i = 0; i < clgame.globals->numEntities; i++ )
|
||||
{
|
||||
ent = EDICT_NUM( i );
|
||||
if( ent->free ) continue;
|
||||
state = &ent->pvClientData->baseline;
|
||||
if( !state->modelindex ) continue;
|
||||
state = &cl.entity_baselines[i];
|
||||
if( !state->number ) continue;
|
||||
|
||||
if( buf.cursize + 64 > buf.maxsize )
|
||||
{
|
||||
|
@ -101,7 +98,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
buf.cursize = 0;
|
||||
}
|
||||
MSG_WriteByte( &buf, svc_spawnbaseline );
|
||||
MSG_WriteDeltaEntity( &nullstate, &ent->pvClientData->baseline, &buf, true, true );
|
||||
MSG_WriteDeltaEntity( &nullstate, state, &buf, true, true );
|
||||
}
|
||||
|
||||
MSG_WriteByte( &buf, svc_stufftext );
|
||||
|
|
|
@ -39,12 +39,12 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
|||
entity_state_t *state;
|
||||
|
||||
ent = EDICT_NUM( newnum );
|
||||
state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
|
||||
state = &cl.entity_curstates[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
|
||||
|
||||
if( unchanged ) *state = *old;
|
||||
else MSG_ReadDeltaEntity( msg, old, state, newnum );
|
||||
|
||||
if( state->number == -1 )
|
||||
if( state->number == ( MAX_EDICTS - 1 ))
|
||||
{
|
||||
CL_FreeEdict( ent );
|
||||
return; // entity was delta removed
|
||||
|
@ -52,12 +52,14 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
|||
cl.parse_entities++;
|
||||
frame->num_entities++;
|
||||
|
||||
// some data changes will force no lerping
|
||||
if( state->ed_flags & ESF_NODELTA )
|
||||
if( ent->free )
|
||||
{
|
||||
ent->pvClientData->serverframe = -99;
|
||||
CL_InitEdict( ent );
|
||||
}
|
||||
|
||||
// some data changes will force no lerping
|
||||
if( state->ed_flags & ESF_NODELTA ) ent->pvClientData->serverframe = -99;
|
||||
|
||||
if( ent->pvClientData->serverframe != cl.frame.serverframe - 1 )
|
||||
{
|
||||
// duplicate the current state so lerping doesn't hurt anything
|
||||
|
@ -101,7 +103,7 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
|
|||
}
|
||||
else
|
||||
{
|
||||
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +117,7 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
|
|||
if( msg->error )
|
||||
Host_Error("CL_ParsePacketEntities: end of message[%d > %d]\n", msg->readcount, msg->cursize );
|
||||
|
||||
while( newnum >= clgame.numEntities ) CL_AllocEdict();
|
||||
while( newnum >= clgame.globals->numEntities ) CL_AllocEdict();
|
||||
|
||||
while( oldnum < newnum )
|
||||
{
|
||||
|
@ -130,7 +132,7 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
|
|||
}
|
||||
else
|
||||
{
|
||||
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +148,7 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
|
|||
}
|
||||
else
|
||||
{
|
||||
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
continue;
|
||||
|
@ -155,10 +157,8 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
|
|||
if( oldnum > newnum )
|
||||
{
|
||||
// delta from baseline ?
|
||||
edict_t *ent = EDICT_NUM( newnum );
|
||||
|
||||
Com_Assert( ent->free );
|
||||
CL_DeltaEntity( msg, newframe, newnum, &ent->pvClientData->baseline, false );
|
||||
entity_state_t *baseline = &cl.entity_baselines[newnum];
|
||||
CL_DeltaEntity( msg, newframe, newnum, baseline, false );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -177,59 +177,12 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
|
|||
}
|
||||
else
|
||||
{
|
||||
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
}
|
||||
|
||||
for( ; EDICT_NUM( clgame.numEntities - 1 )->free; clgame.numEntities-- );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_LerpPoint
|
||||
|
||||
Determines the fraction between the last two messages that the objects
|
||||
should be put at.
|
||||
===============
|
||||
*/
|
||||
static float CL_LerpPoint( void )
|
||||
{
|
||||
float f, frac;
|
||||
|
||||
f = cl.mtime[0] - cl.mtime[1];
|
||||
|
||||
if( !f )
|
||||
{
|
||||
cl.time = cl.mtime[0];
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if( f > 0.1 )
|
||||
{
|
||||
// dropped packet, or start of demo
|
||||
cl.mtime[1] = cl.mtime[0] - 0.1f;
|
||||
f = 0.1f;
|
||||
}
|
||||
|
||||
frac = (cl.time - cl.mtime[1]) / f;
|
||||
if( frac < 0 )
|
||||
{
|
||||
if( frac < -0.01f )
|
||||
{
|
||||
cl.time = cl.mtime[1];
|
||||
}
|
||||
frac = 0;
|
||||
}
|
||||
else if( frac > 1.0f )
|
||||
{
|
||||
if( frac > 1.01f )
|
||||
{
|
||||
cl.time = cl.mtime[0];
|
||||
}
|
||||
frac = 1.0f;
|
||||
}
|
||||
return frac;
|
||||
for( ; EDICT_NUM( clgame.globals->numEntities - 1 )->free; clgame.globals->numEntities-- );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -245,10 +198,10 @@ void CL_ParseFrame( sizebuf_t *msg )
|
|||
Mem_Set( &cl.frame, 0, sizeof( cl.frame ));
|
||||
|
||||
cl.frame.serverframe = MSG_ReadLong( msg );
|
||||
cl.frame.servertime = MSG_ReadLong( msg );
|
||||
cl.serverframetime = MSG_ReadLong( msg );
|
||||
cl.frame.deltaframe = MSG_ReadLong( msg );
|
||||
cl.surpressCount = MSG_ReadByte( msg );
|
||||
cl.frame.servertime = cl.mtime[0]; // same as servertime
|
||||
|
||||
// If the frame is delta compressed from data that we
|
||||
// no longer have available, we must suck up the rest of
|
||||
|
@ -285,6 +238,11 @@ void CL_ParseFrame( sizebuf_t *msg )
|
|||
len = MSG_ReadByte( msg );
|
||||
MSG_ReadData( msg, &cl.frame.areabits, len );
|
||||
|
||||
// read packet entities
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_packetentities ) Host_Error("CL_ParseFrame: not packetentities[%d]\n", cmd );
|
||||
CL_ParsePacketEntities( msg, cl.oldframe, &cl.frame );
|
||||
|
||||
// read clientindex
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_playerinfo ) Host_Error( "CL_ParseFrame: not clientindex\n" );
|
||||
|
@ -293,11 +251,6 @@ void CL_ParseFrame( sizebuf_t *msg )
|
|||
if(( idx - 1 ) != cl.playernum )
|
||||
Host_Error( "CL_ParseFrame: invalid playernum (%d should be %d)\n", idx-1, cl.playernum );
|
||||
|
||||
// read packet entities
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_packetentities ) Host_Error("CL_ParseFrame: not packetentities[%d]\n", cmd );
|
||||
CL_ParsePacketEntities( msg, cl.oldframe, &cl.frame );
|
||||
|
||||
// now we can reading delta player state
|
||||
if( cl.oldframe ) cl.frame.ps = MSG_ParseDeltaPlayer( &cl.oldframe->ps, &clent->pvClientData->current );
|
||||
else cl.frame.ps = MSG_ParseDeltaPlayer( NULL, &clent->pvClientData->current );
|
||||
|
@ -309,7 +262,10 @@ void CL_ParseFrame( sizebuf_t *msg )
|
|||
{
|
||||
if( cls.state != ca_active )
|
||||
{
|
||||
cls.state = ca_active;
|
||||
cls.state = ca_active; // client spawned
|
||||
cl.force_refdef = true;
|
||||
|
||||
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
||||
// getting a valid frame message ends the connection process
|
||||
VectorCopy( cl.frame.ps.origin, cl.predicted_origin );
|
||||
VectorCopy( cl.frame.ps.viewangles, cl.predicted_angles );
|
||||
|
@ -333,30 +289,24 @@ CL_AddPacketEntities
|
|||
*/
|
||||
void CL_AddPacketEntities( frame_t *frame )
|
||||
{
|
||||
entity_state_t *s1;
|
||||
edict_t *ent;
|
||||
int pnum;
|
||||
int e, ed_type;
|
||||
|
||||
cl.time = bound( cl.frame.servertime - cl.serverframetime, cl.time, cl.frame.servertime );
|
||||
if( cl_paused->integer ) cl.lerpFrac = 1.0f;
|
||||
else cl.lerpFrac = 1.0 - (cl.frame.servertime - cl.time) / (float)cl.serverframetime;
|
||||
|
||||
for( pnum = 0; pnum < frame->num_entities; pnum++ )
|
||||
for( e = 0; e < clgame.globals->numEntities; e++ )
|
||||
{
|
||||
s1 = &cl_parse_entities[(frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1)];
|
||||
ent = EDICT_NUM( s1->number );
|
||||
|
||||
ent = EDICT_NUM( e );
|
||||
if( ent->free ) continue;
|
||||
|
||||
ed_type = ent->pvClientData->current.ed_type;
|
||||
CL_UpdateEntityFields( ent );
|
||||
|
||||
if( re->AddRefEntity( ent, s1->ed_type ))
|
||||
if( re->AddRefEntity( ent, ed_type ))
|
||||
{
|
||||
if( s1->ed_type == ED_PORTAL && !VectorCompare( ent->v.origin, ent->v.oldorigin ))
|
||||
if( ed_type == ED_PORTAL && !VectorCompare( ent->v.origin, ent->v.oldorigin ))
|
||||
cl.render_flags |= RDF_PORTALINVIEW;
|
||||
}
|
||||
// NOTE: skyportal entity never added to rendering
|
||||
if( s1->ed_type == ED_SKYPORTAL ) cl.render_flags |= RDF_SKYPORTALINVIEW;
|
||||
if( ed_type == ED_SKYPORTAL ) cl.render_flags |= RDF_SKYPORTALINVIEW;
|
||||
}
|
||||
|
||||
if( cl.oldframe && !memcmp( cl.oldframe->areabits, cl.frame.areabits, sizeof( cl.frame.areabits )))
|
||||
|
@ -411,7 +361,7 @@ void CL_GetEntitySoundSpatialization( int entnum, vec3_t origin, vec3_t velocity
|
|||
|
||||
// setup origin and velocity
|
||||
VectorCopy( ent->v.origin, origin );
|
||||
VectorScale( ent->v.velocity, 10, velocity );
|
||||
VectorCopy( ent->v.velocity, velocity );
|
||||
|
||||
// if a brush model, offset the origin
|
||||
if( VectorIsNull( origin ))
|
||||
|
@ -434,19 +384,19 @@ client
|
|||
*/
|
||||
void CL_AddLoopingSounds( void )
|
||||
{
|
||||
entity_state_t *ent;
|
||||
int num, i;
|
||||
edict_t *ent;
|
||||
int sound, e;
|
||||
|
||||
if( cls.state != ca_active ) return;
|
||||
if( cl_paused->integer ) return;
|
||||
if( !cl.audio_prepped ) return;
|
||||
|
||||
for( i = 0; i < cl.frame.num_entities; i++ )
|
||||
for( e = 0; e < clgame.globals->numEntities; e++ )
|
||||
{
|
||||
num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
|
||||
ent = &cl_parse_entities[num];
|
||||
ent = EDICT_NUM( e );
|
||||
if( ent->free ) continue;
|
||||
|
||||
switch( ent->ed_type )
|
||||
switch( ent->pvClientData->current.ed_type )
|
||||
{
|
||||
case ED_MOVER:
|
||||
case ED_AMBIENT:
|
||||
|
@ -454,7 +404,9 @@ void CL_AddLoopingSounds( void )
|
|||
default: continue;
|
||||
}
|
||||
|
||||
if( !ent->soundindex ) continue;
|
||||
S_AddLoopingSound( ent->number, cl.sound_precache[ent->soundindex], 1.0f, ATTN_IDLE );
|
||||
sound = ent->pvClientData->current.soundindex;
|
||||
if( !sound ) continue;
|
||||
|
||||
S_AddLoopingSound( ent->serialnumber, cl.sound_precache[sound], 1.0f, ATTN_IDLE );
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ Render callback for studio models
|
|||
*/
|
||||
edict_t *CL_GetEdictByIndex( int index )
|
||||
{
|
||||
if( index < 0 || index > clgame.numEntities )
|
||||
if( index < 0 || index > clgame.globals->numEntities )
|
||||
{
|
||||
if( index == VMODEL_ENTINDEX ) return &cl.viewent;
|
||||
if( index == WMODEL_ENTINDEX ) return NULL;
|
||||
|
@ -163,12 +163,6 @@ void CL_FadeAlpha( float starttime, float endtime, rgba_t color )
|
|||
|
||||
void CL_DrawHUD( int state )
|
||||
{
|
||||
if( state == CL_LOADING )
|
||||
{
|
||||
// fill unused entries with black color
|
||||
SCR_FillRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, g_color_table[0] );
|
||||
}
|
||||
|
||||
if( state == CL_ACTIVE && !cl.video_prepped )
|
||||
state = CL_LOADING;
|
||||
|
||||
|
@ -352,7 +346,7 @@ edict_t *CL_AllocEdict( void )
|
|||
edict_t *pEdict;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < clgame.numEntities; i++ )
|
||||
for( i = 0; i < clgame.globals->numEntities; i++ )
|
||||
{
|
||||
pEdict = EDICT_NUM( i );
|
||||
// the first couple seconds of client time can involve a lot of
|
||||
|
@ -364,10 +358,10 @@ edict_t *CL_AllocEdict( void )
|
|||
}
|
||||
}
|
||||
|
||||
if( i == clgame.maxEntities )
|
||||
if( i == clgame.globals->maxEntities )
|
||||
Host_Error( "CL_AllocEdict: no free edicts\n" );
|
||||
|
||||
clgame.numEntities++;
|
||||
clgame.globals->numEntities++;
|
||||
pEdict = EDICT_NUM( i );
|
||||
CL_InitEdict( pEdict );
|
||||
|
||||
|
@ -379,12 +373,19 @@ void CL_InitEdicts( void )
|
|||
edict_t *e;
|
||||
int i;
|
||||
|
||||
clgame.maxEntities = com.atoi( cl.configstrings[CS_MAXEDICTS] );
|
||||
clgame.maxClients = com.atoi( cl.configstrings[CS_MAXCLIENTS] );
|
||||
clgame.edicts = Mem_Realloc( cls.mempool, clgame.edicts, sizeof( edict_t ) * clgame.maxEntities );
|
||||
clgame.globals->maxEntities = com.atoi( cl.configstrings[CS_MAXEDICTS] );
|
||||
clgame.globals->maxClients = com.atoi( cl.configstrings[CS_MAXCLIENTS] );
|
||||
clgame.edicts = Mem_Realloc( cls.mempool, clgame.edicts, sizeof( edict_t ) * clgame.globals->maxEntities );
|
||||
|
||||
for( i = 0, e = EDICT_NUM( 0 ); i < clgame.maxEntities; i++, e++ )
|
||||
for( i = 0, e = EDICT_NUM( 0 ); i < clgame.globals->maxEntities; i++, e++ )
|
||||
e->free = true; // mark all edicts as freed
|
||||
|
||||
clgame.globals->mapname = MAKE_STRING( cl.configstrings[CS_NAME] );
|
||||
|
||||
clgame.globals->deathmatch = Cvar_VariableInteger( "deathmatch" );
|
||||
clgame.globals->coop = Cvar_VariableInteger( "coop" );
|
||||
clgame.globals->teamplay = Cvar_VariableInteger( "teamplay" );
|
||||
clgame.globals->serverflags = 0; // FIXME: make CS_SERVERFLAGS
|
||||
}
|
||||
|
||||
void CL_FreeEdicts( void )
|
||||
|
@ -392,7 +393,7 @@ void CL_FreeEdicts( void )
|
|||
int i;
|
||||
edict_t *ent;
|
||||
|
||||
for( i = 0; i < clgame.numEntities; i++ )
|
||||
for( i = 0; i < clgame.globals->numEntities; i++ )
|
||||
{
|
||||
ent = EDICT_NUM( i );
|
||||
if( ent->free ) continue;
|
||||
|
@ -401,7 +402,7 @@ void CL_FreeEdicts( void )
|
|||
|
||||
// clear globals
|
||||
StringTable_Clear( clgame.hStringTable );
|
||||
clgame.numEntities = 0;
|
||||
clgame.globals->numEntities = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1402,11 +1403,13 @@ void CL_UnloadProgs( void )
|
|||
bool CL_LoadProgs( const char *name )
|
||||
{
|
||||
static CLIENTAPI GetClientAPI;
|
||||
static cl_globalvars_t gpGlobals;
|
||||
string libpath;
|
||||
|
||||
if( clgame.hInstance ) CL_UnloadProgs();
|
||||
|
||||
// fill it in
|
||||
clgame.globals = &gpGlobals;
|
||||
Com_BuildPath( name, libpath );
|
||||
cls.mempool = Mem_AllocPool( "Client Edicts Zone" );
|
||||
clgame.private = Mem_AllocPool( "Client Private Zone" );
|
||||
|
@ -1422,7 +1425,7 @@ bool CL_LoadProgs( const char *name )
|
|||
return false;
|
||||
}
|
||||
|
||||
if( !GetClientAPI( &clgame.dllFuncs, &gEngfuncs ))
|
||||
if( !GetClientAPI( &clgame.dllFuncs, &gEngfuncs, clgame.globals ))
|
||||
{
|
||||
MsgDev( D_ERROR, "CL_LoadProgs: can't init client API\n" );
|
||||
return false;
|
||||
|
|
|
@ -713,8 +713,7 @@ void CL_WritePacket( void )
|
|||
{
|
||||
bool noDelta = false;
|
||||
|
||||
if( cl_nodelta->integer ) noDelta = true;
|
||||
if( !cl.frame.valid || cls.demowaiting || cls.netchan.incoming_sequence != cl.frame.serverframe )
|
||||
if( cl_nodelta->integer || !cl.frame.valid || cls.demowaiting )
|
||||
noDelta = true;
|
||||
|
||||
// begin a client move command
|
||||
|
|
|
@ -38,7 +38,6 @@ cvar_t *cl_particlelod;
|
|||
|
||||
cvar_t *cl_shownet;
|
||||
cvar_t *cl_showmiss;
|
||||
cvar_t *cl_showclamp;
|
||||
cvar_t *cl_mouselook;
|
||||
cvar_t *cl_paused;
|
||||
|
||||
|
@ -54,8 +53,6 @@ client_static_t cls;
|
|||
client_t cl;
|
||||
clgame_static_t clgame;
|
||||
|
||||
entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
|
||||
|
||||
extern cvar_t *allow_download;
|
||||
//======================================================================
|
||||
|
||||
|
@ -441,8 +438,9 @@ void CL_Changing_f( void )
|
|||
if( cls.download ) return;
|
||||
|
||||
S_StopAllSounds();
|
||||
cl.audio_prepped = false; // don't play ambients
|
||||
cls.state = ca_connected; // not active anymore, but not disconnected
|
||||
Msg( "\nChanging map...\n" );
|
||||
Msg( "\nchanging map...\n" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -459,9 +457,10 @@ void CL_Reconnect_f( void )
|
|||
if( cls.download ) return;
|
||||
|
||||
S_StopAllSounds ();
|
||||
Cmd_ExecuteString( "plaque\n" ); // disable plaque draw on change map
|
||||
|
||||
if( cls.state == ca_connected )
|
||||
{
|
||||
Msg( "reconnecting...\n" );
|
||||
cls.state = ca_connected;
|
||||
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_Print( &cls.netchan.message, "new" );
|
||||
|
@ -708,7 +707,7 @@ void CL_PrepVideo( void )
|
|||
return; // no map loaded
|
||||
|
||||
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
||||
Msg( "CL_PrepRefresh: %s\n", cl.configstrings[CS_NAME] );
|
||||
MsgDev( D_LOAD, "CL_PrepRefresh: %s\n", cl.configstrings[CS_NAME] );
|
||||
// let the render dll load the map
|
||||
FS_FileBase( cl.configstrings[CS_MODELS+1], mapname );
|
||||
re->BeginRegistration( mapname, pe->VisData()); // load map
|
||||
|
@ -737,9 +736,10 @@ void CL_PrepVideo( void )
|
|||
re->EndRegistration( cl.configstrings[CS_SKYNAME] );
|
||||
Cvar_SetValue( "scr_loading", 100.0f ); // all done
|
||||
|
||||
Con_ClearNotify(); // clear any lines of console text
|
||||
if( host.developer <= 2 ) Con_ClearNotify(); // clear any lines of console text
|
||||
SCR_UpdateScreen();
|
||||
cl.video_prepped = true;
|
||||
cl.force_refdef = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1087,7 +1087,6 @@ void CL_InitLocal( void )
|
|||
|
||||
cl_shownet = Cvar_Get( "cl_shownet", "0", 0, "client show network packets" );
|
||||
cl_showmiss = Cvar_Get( "cl_showmiss", "0", 0, "client show network errors" );
|
||||
cl_showclamp = Cvar_Get( "cl_showclamp", "0", CVAR_ARCHIVE, "show client clamping" );
|
||||
cl_timeout = Cvar_Get( "cl_timeout", "120", 0, "connect timeout (in-seconds)" );
|
||||
|
||||
rcon_client_password = Cvar_Get( "rcon_password", "", 0, "remote control client password" );
|
||||
|
@ -1200,7 +1199,7 @@ void CL_Frame( int time )
|
|||
SCR_MakeScreenShot();
|
||||
|
||||
// update audio
|
||||
S_Update( cl.playernum + 1, cl.refdef.vieworg, vec3_origin, cl.refdef.forward, cl.refdef.up );
|
||||
S_Update( cl.playernum + 1, cl.refdef.simorg, cl.refdef.simvel, cl.refdef.forward, cl.refdef.up );
|
||||
|
||||
// advance local effects for next frame
|
||||
CL_RunDLights ();
|
||||
|
|
|
@ -230,11 +230,11 @@ CL_ParseServerData
|
|||
*/
|
||||
void CL_ParseServerData( sizebuf_t *msg )
|
||||
{
|
||||
char *str;
|
||||
string str, title;
|
||||
const char *levelshot_ext[] = { "tga", "jpg", "png" };
|
||||
int i;
|
||||
|
||||
MsgDev( D_INFO, "Serverdata packet received.\n" );
|
||||
MsgDev( D_NOTE, "Serverdata packet received.\n" );
|
||||
|
||||
// wipe the client_t struct
|
||||
CL_ClearState();
|
||||
|
@ -248,9 +248,9 @@ void CL_ParseServerData( sizebuf_t *msg )
|
|||
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
|
||||
|
||||
cl.servercount = MSG_ReadLong( msg );
|
||||
cl.serverframetime = MSG_ReadLong( msg );
|
||||
cl.playernum = MSG_ReadShort( msg );
|
||||
str = MSG_ReadString( msg );
|
||||
com.strncpy( str, MSG_ReadString( msg ), MAX_STRING );
|
||||
com.strncpy( title, MSG_ReadString( msg ), MAX_STRING );
|
||||
|
||||
// get splash name
|
||||
Cvar_Set( "cl_levelshot_name", va( "levelshots/%s", str ));
|
||||
|
@ -266,6 +266,7 @@ void CL_ParseServerData( sizebuf_t *msg )
|
|||
}
|
||||
// seperate the printfs so the server message can have a color
|
||||
Msg("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
|
||||
Msg( "^2%s\n", title );
|
||||
|
||||
// need to prep refresh at next oportunity
|
||||
cl.video_prepped = false;
|
||||
|
@ -281,19 +282,15 @@ void CL_ParseBaseline( sizebuf_t *msg )
|
|||
{
|
||||
int newnum;
|
||||
entity_state_t nullstate;
|
||||
edict_t *ent;
|
||||
entity_state_t *baseline;
|
||||
|
||||
Mem_Set( &nullstate, 0, sizeof( nullstate ));
|
||||
newnum = MSG_ReadBits( msg, NET_WORD );
|
||||
|
||||
if( !clgame.numEntities ) CL_InitEdicts();
|
||||
if( !newnum ) CL_InitEdicts();
|
||||
|
||||
// increase edicts
|
||||
while( newnum >= clgame.numEntities ) CL_AllocEdict();
|
||||
ent = EDICT_NUM( newnum );
|
||||
|
||||
Com_Assert( ent->pvClientData == NULL );
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &ent->pvClientData->baseline, newnum );
|
||||
baseline = &cl.entity_baselines[newnum];
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, baseline, newnum );
|
||||
}
|
||||
|
||||
void CL_ParseMoveVars( int number )
|
||||
|
@ -520,10 +517,6 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
|||
case svc_print:
|
||||
Con_Print( va( "^6%s\n", MSG_ReadString( msg )));
|
||||
break;
|
||||
case svc_time:
|
||||
cl.mtime[1] = cl.mtime[0];
|
||||
cl.mtime[0] = MSG_ReadLong( msg );
|
||||
break;
|
||||
case svc_frame:
|
||||
CL_ParseFrame( msg );
|
||||
break;
|
||||
|
|
|
@ -62,9 +62,9 @@ void V_SetupRefDef( void )
|
|||
cl.refdef.health = clent->v.health;
|
||||
cl.refdef.movetype = clent->v.movetype;
|
||||
cl.refdef.idealpitch = clent->v.ideal_pitch;
|
||||
cl.refdef.num_entities = clgame.numEntities;
|
||||
cl.refdef.max_entities = clgame.maxEntities;
|
||||
cl.refdef.maxclients = clgame.maxClients;
|
||||
cl.refdef.num_entities = clgame.globals->numEntities;
|
||||
cl.refdef.max_entities = clgame.globals->maxEntities;
|
||||
cl.refdef.maxclients = clgame.globals->maxClients;
|
||||
cl.refdef.time = cl.time * 0.001f;
|
||||
cl.refdef.frametime = cls.frametime;
|
||||
cl.refdef.demoplayback = cls.demoplayback;
|
||||
|
@ -101,7 +101,7 @@ apply pre-calculated values
|
|||
*/
|
||||
void V_AddViewModel( void )
|
||||
{
|
||||
if( cl.viewent.v.modelindex && !cl.refdef.nextView )
|
||||
if( cl.refdef.nextView ) return; // add viewmodel only at firstperson pass
|
||||
re->AddRefEntity( &cl.viewent, ED_VIEWMODEL );
|
||||
}
|
||||
|
||||
|
@ -134,16 +134,23 @@ void V_RenderView( void )
|
|||
{
|
||||
if( !cl.video_prepped ) return; // still loading
|
||||
|
||||
if( !cl.frame.valid )
|
||||
cl.time = bound( cl.frame.servertime - cl.serverframetime, cl.time, cl.frame.servertime );
|
||||
if( cl_paused->integer ) cl.lerpFrac = 1.0f;
|
||||
else cl.lerpFrac = 1.0 - (cl.frame.servertime - cl.time) / (float)cl.serverframetime;
|
||||
|
||||
// update cl_globalvars
|
||||
clgame.globals->time = cl.time * 0.001f; // clamped
|
||||
clgame.globals->frametime = cl.serverframetime * 0.001f; // !!!
|
||||
|
||||
if( cl.frame.valid && (cl.force_refdef || !cl_paused->integer ))
|
||||
{
|
||||
SCR_FillRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, g_color_table[0] );
|
||||
return;
|
||||
}
|
||||
cl.force_refdef = false;
|
||||
|
||||
V_ClearScene ();
|
||||
CL_AddEntities ();
|
||||
|
||||
V_SetupRefDef ();
|
||||
}
|
||||
|
||||
V_CalcRefDef ();
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,11 @@ typedef struct field_s
|
|||
#define CMD_BACKUP 64 // allow a lot of command backups for very fast systems
|
||||
#define CMD_MASK (CMD_BACKUP - 1)
|
||||
|
||||
// the cl_parse_entities must be large enough to hold UPDATE_BACKUP frames of
|
||||
// entities, so that when a delta compressed message arives from the server
|
||||
// it can be un-deltad from the original
|
||||
#define MAX_PARSE_ENTITIES 2048
|
||||
|
||||
//
|
||||
// the client_t structure is wiped completely at every
|
||||
// server map change
|
||||
|
@ -81,7 +86,7 @@ typedef struct
|
|||
|
||||
bool video_prepped; // false if on new level or new ref dll
|
||||
bool audio_prepped; // false if on new level or new snd dll
|
||||
|
||||
bool force_refdef; // vid has changed, so we can't use a paused refdef
|
||||
int parse_entities; // index (not anded off) into cl_parse_entities[]
|
||||
|
||||
int cmd_number;
|
||||
|
@ -125,6 +130,9 @@ typedef struct
|
|||
int serverframetime; // server frametime
|
||||
char configstrings[MAX_CONFIGSTRINGS][CS_SIZE];
|
||||
|
||||
entity_state_t entity_curstates[MAX_PARSE_ENTITIES];
|
||||
entity_state_t entity_baselines[MAX_EDICTS]; // keep all baselines in one global array
|
||||
|
||||
// locally derived information from server state
|
||||
cmodel_t *models[MAX_MODELS];
|
||||
cmodel_t *worldmodel;
|
||||
|
@ -173,8 +181,6 @@ typedef enum
|
|||
struct cl_priv_s
|
||||
{
|
||||
int serverframe; // if not current, this ent isn't in the frame
|
||||
|
||||
entity_state_t baseline; // delta from this if not from a previous frame
|
||||
entity_state_t current;
|
||||
entity_state_t prev; // will always be valid, but might just be a copy of current
|
||||
};
|
||||
|
@ -226,10 +232,9 @@ typedef struct
|
|||
char centerPrint[1024];
|
||||
int centerPrintLines;
|
||||
|
||||
int maxClients;
|
||||
int numEntities;
|
||||
int maxEntities;
|
||||
cl_globalvars_t *globals;
|
||||
user_message_t *msg[MAX_USER_MESSAGES];
|
||||
|
||||
int numMessages; // actual count of user messages
|
||||
int hStringTable; // stringtable handle
|
||||
|
||||
|
@ -319,7 +324,6 @@ extern cvar_t *cl_run;
|
|||
extern cvar_t *cl_font;
|
||||
extern cvar_t *cl_anglespeedkey;
|
||||
extern cvar_t *cl_showmiss;
|
||||
extern cvar_t *cl_showclamp;
|
||||
extern cvar_t *cl_particles;
|
||||
extern cvar_t *cl_particlelod;
|
||||
extern cvar_t *cl_testentities;
|
||||
|
@ -331,13 +335,6 @@ extern cvar_t *scr_centertime;
|
|||
extern cvar_t *scr_showpause;
|
||||
extern cvar_t *con_font;
|
||||
|
||||
// the cl_parse_entities must be large enough to hold UPDATE_BACKUP frames of
|
||||
// entities, so that when a delta compressed message arives from the server
|
||||
// it can be un-deltad from the original
|
||||
#define MAX_PARSE_ENTITIES 1024
|
||||
|
||||
extern entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
|
||||
|
||||
//=============================================================================
|
||||
|
||||
bool CL_CheckOrDownloadFile( const char *filename );
|
||||
|
@ -463,7 +460,7 @@ bool CL_RenderTrace( const vec3_t start, const vec3_t mins, const vec3_t maxs, c
|
|||
|
||||
_inline edict_t *CL_EDICT_NUM( int n, const char *file, const int line )
|
||||
{
|
||||
if((n >= 0) && (n < clgame.maxEntities))
|
||||
if((n >= 0) && (n < clgame.globals->maxEntities))
|
||||
return clgame.edicts + n;
|
||||
Host_Error( "CL_EDICT_NUM: bad number %i (called at %s:%i)\n", n, file, line );
|
||||
return NULL;
|
||||
|
|
|
@ -117,6 +117,7 @@ void Host_Main( void );
|
|||
void Host_Free( void );
|
||||
void Host_SetServerState( int state );
|
||||
int Host_ServerState( void );
|
||||
int Host_CompareFileTime( long ft1, long ft2 );
|
||||
void Host_AbortCurrentFrame( void );
|
||||
void Host_WriteDefaultConfig( void );
|
||||
void Host_WriteConfig( void );
|
||||
|
|
|
@ -260,8 +260,9 @@ void Con_Init( void )
|
|||
Cmd_AddCommand( "messagemode", Con_MessageMode_f, "input a chat message to say to everyone" );
|
||||
Cmd_AddCommand( "messagemode2", Con_MessageMode2_f, "input a chat message to say to only your team" );
|
||||
Cmd_AddCommand( "clear", Con_Clear_f, "clear console history" );
|
||||
con.initialized = true;
|
||||
|
||||
MsgDev( D_NOTE, "Console initialized.\n" );
|
||||
con.initialized = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -559,19 +560,17 @@ void Con_DrawConsole( void )
|
|||
// check for console width changes from a vid mode change
|
||||
Con_CheckResize ();
|
||||
|
||||
if( cls.state == ca_connecting || cls.state == ca_connected )
|
||||
{
|
||||
if( host.developer >= 4 ) con.displayFrac = 0.5f; // keep console open
|
||||
else if( host.developer >= 2 ) Con_DrawNotify(); // draw notify lines
|
||||
}
|
||||
|
||||
// if disconnected, render console full screen
|
||||
switch( cls.state )
|
||||
{
|
||||
case ca_uninitialized:
|
||||
break;
|
||||
case ca_connected:
|
||||
case ca_connecting:
|
||||
if( host.developer >= 2 )
|
||||
{
|
||||
// -dev 1 probably nothing print while loading
|
||||
Con_DrawSolidConsole( 0.5f );
|
||||
}
|
||||
break;
|
||||
case ca_disconnected:
|
||||
if( cls.key_dest != key_menu )
|
||||
{
|
||||
|
@ -579,6 +578,14 @@ void Con_DrawConsole( void )
|
|||
cls.key_dest = key_console;
|
||||
}
|
||||
break;
|
||||
case ca_connected:
|
||||
case ca_connecting:
|
||||
if( host.developer )
|
||||
{
|
||||
// force to show console always for -dev 3 and higher
|
||||
if( con.displayFrac ) Con_DrawSolidConsole( con.displayFrac );
|
||||
}
|
||||
break;
|
||||
case ca_active:
|
||||
case ca_cinematic:
|
||||
if( con.displayFrac ) Con_DrawSolidConsole( con.displayFrac );
|
||||
|
|
|
@ -416,6 +416,51 @@ bool Cmd_GetMusicList( const char *s, char *completedname, int length )
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetSavesList
|
||||
|
||||
Prints or complete movie filename
|
||||
=====================================
|
||||
*/
|
||||
bool Cmd_GetSavesList( const char *s, char *completedname, int length )
|
||||
{
|
||||
search_t *t;
|
||||
string matchbuf;
|
||||
int i, numsaves;
|
||||
|
||||
t = FS_Search( va( "save/%s*.bin", s ), true );
|
||||
if( !t ) return false;
|
||||
|
||||
FS_FileBase( t->filenames[0], matchbuf );
|
||||
if( completedname && length ) com.strncpy( completedname, matchbuf, length );
|
||||
if( t->numfilenames == 1 ) return true;
|
||||
|
||||
for( i = 0, numsaves = 0; i < t->numfilenames; i++ )
|
||||
{
|
||||
const char *ext = FS_FileExtension( t->filenames[i] );
|
||||
|
||||
if( com.stricmp( ext, "bin" )) continue;
|
||||
FS_FileBase( t->filenames[i], matchbuf );
|
||||
Msg( "%16s\n", matchbuf );
|
||||
numsaves++;
|
||||
}
|
||||
Msg( "\n^3 %i saves found.\n", numsaves );
|
||||
Mem_Free( t );
|
||||
|
||||
// cut shortestMatch to the amount common with s
|
||||
if( completedname && length )
|
||||
{
|
||||
for( i = 0; matchbuf[i]; i++ )
|
||||
{
|
||||
if( com.tolower( completedname[i] ) != com.tolower( matchbuf[i] ))
|
||||
completedname[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetSoundList
|
||||
|
@ -727,6 +772,8 @@ autocomplete_list_t cmd_list[] =
|
|||
{ "give", Cmd_GetItemsList },
|
||||
{ "drop", Cmd_GetItemsList },
|
||||
{ "game", Cmd_GetGamesList },
|
||||
{ "save", Cmd_GetSavesList },
|
||||
{ "load", Cmd_GetSavesList },
|
||||
{ "map", Cmd_GetMapList },
|
||||
{ NULL }, // termiantor
|
||||
};
|
||||
|
|
|
@ -42,7 +42,6 @@ static net_field_t ent_fields[] =
|
|||
{ ES_FIELD(skin), NET_BYTE, false }, // 255 skins
|
||||
{ ES_FIELD(body), NET_BYTE, false }, // 255 bodies
|
||||
{ ES_FIELD(weaponmodel), NET_WORD, false }, // p_model index, not name
|
||||
{ ES_FIELD(weaponanim), NET_WORD, false }, // 1024 sequences
|
||||
{ ES_FIELD(weaponbody), NET_BYTE, false }, // 255 bodies
|
||||
{ ES_FIELD(weaponskin), NET_BYTE, false }, // 255 skins
|
||||
{ ES_FIELD(contents), NET_LONG, false }, // full range contents
|
||||
|
@ -666,9 +665,10 @@ void _MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t
|
|||
if( to == NULL )
|
||||
{
|
||||
if( from == NULL ) return;
|
||||
|
||||
// a NULL to is a delta remove message
|
||||
MSG_WriteBits( msg, from->number, NWDesc[NET_WORD].name, NET_WORD );
|
||||
MSG_WriteBits( msg, -99, NWDesc[NET_LONG].name, NET_LONG );
|
||||
MSG_WriteBits( msg, 0xFFFF, NWDesc[NET_LONG].name, NET_LONG );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -730,12 +730,12 @@ void MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *
|
|||
*to = *from;
|
||||
to->number = number;
|
||||
|
||||
if(*(int *)&msg->data[msg->readcount] == -99 )
|
||||
if(*(int *)&msg->data[msg->readcount] == 0xFFFF )
|
||||
{
|
||||
// check for a remove
|
||||
MSG_ReadLong( msg );
|
||||
Mem_Set( to, 0, sizeof( *to ));
|
||||
to->number = -1;
|
||||
to->number = MAX_EDICTS - 1; // entity was removed
|
||||
return;
|
||||
}
|
||||
for( i = 0, field = ent_fields; field->name; i++, field++ )
|
||||
|
|
|
@ -68,7 +68,6 @@ enum svc_ops_e
|
|||
svc_setview, // [short] entity number
|
||||
svc_print, // [byte] id [string] null terminated string
|
||||
svc_crosshairangle, // [short][short][short]
|
||||
svc_time, // [long] sv.time
|
||||
};
|
||||
|
||||
// client to server
|
||||
|
|
|
@ -6,86 +6,6 @@
|
|||
--------------------Configuration: engine - Win32 Debug--------------------
|
||||
</h3>
|
||||
<h3>Command Lines</h3>
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP22B.tmp" with contents
|
||||
[
|
||||
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "common" /I "server" /I "client" /I "uimenu" /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\engine\!debug/" /Fo"..\temp\engine\!debug/" /Fd"..\temp\engine\!debug/" /FD /c
|
||||
"D:\Xash3D\src_main\engine\server\sv_phys.c"
|
||||
]
|
||||
Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP22B.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP22C.tmp" with contents
|
||||
[
|
||||
user32.lib msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\engine\!debug/engine.pdb" /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\temp\engine\!debug/engine.dll" /implib:"..\temp\engine\!debug/engine.lib" /pdbtype:sept
|
||||
"\Xash3D\src_main\temp\engine\!debug\cinematic.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_cmds.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_demo.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_effects.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_frame.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_game.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_input.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_main.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_parse.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_phys.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_scrn.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\cl_view.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\com_library.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\con_keys.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\con_main.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\con_utils.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\engfuncs.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\engine.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\host.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\infostring.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\input.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\net_chan.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\net_huff.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\net_msg.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_client.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_cmds.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_frame.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_game.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_init.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_main.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_move.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_phys.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_save.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\sv_world.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_advanced.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_audio.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_controls.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_credits.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_defaults.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_demos.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_gameoptions.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_gotosite.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_ingame.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_loadgame.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_main.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_menu.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_mods.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_multiplayer.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_network.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_options.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_performance.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_playersetup.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_qmenu.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_quit.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_savegame.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_singleplayer.obj"
|
||||
"\Xash3D\src_main\temp\engine\!debug\ui_video.obj"
|
||||
]
|
||||
Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP22C.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP22D.bat" with contents
|
||||
[
|
||||
@echo off
|
||||
copy \Xash3D\src_main\temp\engine\!debug\engine.dll "D:\Xash3D\bin\engine.dll"
|
||||
]
|
||||
Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP22D.bat"
|
||||
Compiling...
|
||||
sv_phys.c
|
||||
Linking...
|
||||
<h3>Output Window</h3>
|
||||
Performing Custom Build Step on \Xash3D\src_main\temp\engine\!debug\engine.dll
|
||||
‘Ş®Ż¨ŕ®˘ ® ä ©«®˘: 1.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,19 @@ cvar_t *host_registered;
|
|||
// these cvars will be duplicated on each client across network
|
||||
int Host_ServerState( void ) { return Cvar_VariableInteger( "host_serverstate" ); }
|
||||
|
||||
int Host_CompareFileTime( long ft1, long ft2 )
|
||||
{
|
||||
if( ft1 < ft2 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if( ft1 > ft2 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Host_InitPhysic( void )
|
||||
{
|
||||
static physic_imp_t pi;
|
||||
|
@ -659,6 +672,9 @@ Host_Shutdown
|
|||
*/
|
||||
void Host_Free( void )
|
||||
{
|
||||
if( host.state == HOST_SHUTDOWN )
|
||||
return;
|
||||
|
||||
host.state = HOST_SHUTDOWN; // prepare host to normal shutdown
|
||||
com.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
|
||||
|
||||
|
|
|
@ -60,8 +60,9 @@ typedef struct server_s
|
|||
sv_state_t state; // precache commands are only valid during load
|
||||
|
||||
bool loadgame; // client begins should reuse existing entity
|
||||
bool changelevel; // chnage map, reconnect clients, transfer entities, merge globals
|
||||
|
||||
int time; // always sv.framenum * 50 msec
|
||||
int time; // sv.time += sv.frametime
|
||||
int frametime;
|
||||
int framenum;
|
||||
int net_framenum;
|
||||
|
@ -70,6 +71,7 @@ typedef struct server_s
|
|||
int lastchecktime; // for monster ai
|
||||
|
||||
string name; // map name, or cinematic name
|
||||
string startspot; // player_start name on nextmap
|
||||
cmodel_t *models[MAX_MODELS];
|
||||
cmodel_t *worldmodel;
|
||||
|
||||
|
@ -175,6 +177,9 @@ struct sv_priv_s
|
|||
vec3_t moved_angles; // push old angles
|
||||
physbody_t *physbody; // ptr to phys body
|
||||
|
||||
size_t pvdata_size; // member size of alloceed pvPrivateData
|
||||
// (used by SV_CopyEdict)
|
||||
|
||||
// baselines
|
||||
entity_state_t s; // this is a player_state too
|
||||
};
|
||||
|
@ -228,6 +233,9 @@ typedef struct
|
|||
byte *private; // server.dll private pool
|
||||
byte *temppool; // for parse, save and restore edicts
|
||||
|
||||
edict_t *saved_edicts; // holds the client edicts during changelevel
|
||||
int num_saved_edicts;
|
||||
|
||||
// library exports table
|
||||
word *ordinals;
|
||||
dword *funcs;
|
||||
|
@ -288,7 +296,6 @@ extern cvar_t *sv_rollspeed;
|
|||
extern cvar_t *sv_maxspeed;
|
||||
extern cvar_t *sv_maxclients;
|
||||
extern cvar_t *sv_physics;
|
||||
extern cvar_t *sv_showclamp;
|
||||
extern sv_client_t *sv_client;
|
||||
|
||||
//===========================================================
|
||||
|
@ -317,8 +324,10 @@ void Master_Packet (void);
|
|||
// sv_init.c
|
||||
//
|
||||
void SV_InitGame( void );
|
||||
void SV_Map( char *levelstring, char *savename );
|
||||
void SV_SpawnServer( const char *server, const char *savename );
|
||||
void SV_ActivateServer( void );
|
||||
void SV_DeactivateServer( void );
|
||||
void SV_LevelInit( const char *newmap, const char *oldmap, const char *savename );
|
||||
void SV_SpawnServer( const char *server, const char *startspot );
|
||||
int SV_FindIndex( const char *name, int start, int end, bool create );
|
||||
void SV_ClassifyEdict( edict_t *ent );
|
||||
|
||||
|
@ -365,7 +374,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
|
|||
void SV_SetIdealPitch( sv_client_t *cl );
|
||||
|
||||
//
|
||||
// sv_ccmds.c
|
||||
// sv_cmds.c
|
||||
//
|
||||
void SV_Status_f( void );
|
||||
void SV_Newgame_f( void );
|
||||
|
@ -384,8 +393,11 @@ void SV_LoadProgs( const char *name );
|
|||
void SV_UnloadProgs( void );
|
||||
void SV_FreeEdicts( void );
|
||||
void SV_InitEdict( edict_t *pEdict );
|
||||
bool SV_CopyEdict( edict_t *out, edict_t *in );
|
||||
void SV_ConfigString( int index, const char *val );
|
||||
void SV_SetModel( edict_t *ent, const char *name );
|
||||
void SV_PopClients( void );
|
||||
void SV_PushClients( void );
|
||||
void SV_CreatePhysBody( edict_t *ent );
|
||||
void SV_SetPhysForce( edict_t *ent );
|
||||
void SV_SetMassCentre( edict_t *ent);
|
||||
|
@ -396,6 +408,7 @@ void SV_SpawnEntities( const char *mapname, script_t *entities );
|
|||
edict_t* SV_AllocPrivateData( edict_t *ent, string_t className );
|
||||
string_t SV_AllocString( const char *szValue );
|
||||
const char *SV_GetString( string_t iString );
|
||||
bool SV_MapIsValid( const char *filename, const char *spawn_entity );
|
||||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
||||
|
||||
_inline edict_t *SV_EDICT_NUM( int n, const char * file, const int line )
|
||||
|
@ -425,9 +438,12 @@ void SV_TouchTriggers (edict_t *ent);
|
|||
//
|
||||
// sv_save.c
|
||||
//
|
||||
void SV_WriteSaveFile( const char *name, bool autosave );
|
||||
void SV_MergeLevelFile( const char *name );
|
||||
void SV_ChangeLevel( bool bUseLandmark, const char *mapname, const char *start );
|
||||
void SV_WriteSaveFile( const char *name, bool autosave, bool bUseLandmark );
|
||||
void SV_ReadSaveFile( const char *name );
|
||||
void SV_ReadLevelFile( const char *name );
|
||||
const char *SV_GetLatestSave( void );
|
||||
//============================================================
|
||||
|
||||
//
|
||||
|
|
|
@ -560,7 +560,7 @@ void SV_PutClientInServer( edict_t *ent )
|
|||
ent->pvServerData->s.ed_type = ED_CLIENT; // init edict type
|
||||
ent->free = false;
|
||||
|
||||
if( !sv.loadgame )
|
||||
if( !sv.changelevel && !sv.loadgame )
|
||||
{
|
||||
// fisrt entering
|
||||
svgame.dllFuncs.pfnClientPutInServer( ent );
|
||||
|
@ -582,6 +582,10 @@ void SV_PutClientInServer( edict_t *ent )
|
|||
ent->pvServerData->physbody = pe->CreatePlayer( ent, SV_GetModelPtr( ent ), ent->v.origin, ent->v.m_pmatrix );
|
||||
Mem_EmptyPool( svgame.temppool ); // all tempstrings can be freed now
|
||||
|
||||
// clear any temp states
|
||||
sv.changelevel = false;
|
||||
sv.loadgame = false;
|
||||
|
||||
MsgDev( D_INFO, "level loaded at %g sec\n", (Sys_Milliseconds() - svs.timestart) * 0.001f );
|
||||
}
|
||||
|
||||
|
@ -617,9 +621,9 @@ void SV_New_f( sv_client_t *cl )
|
|||
MSG_WriteByte( &cl->netchan.message, svc_serverdata );
|
||||
MSG_WriteLong( &cl->netchan.message, PROTOCOL_VERSION);
|
||||
MSG_WriteLong( &cl->netchan.message, svs.spawncount );
|
||||
MSG_WriteLong( &cl->netchan.message, sv.frametime );
|
||||
MSG_WriteShort( &cl->netchan.message, playernum );
|
||||
MSG_WriteString( &cl->netchan.message, sv.configstrings[CS_NAME] );
|
||||
MSG_WriteString( &cl->netchan.message, STRING( EDICT_NUM( 0 )->v.message )); // Map Message
|
||||
|
||||
// game server
|
||||
if( sv.state == ss_active )
|
||||
|
|
|
@ -193,6 +193,7 @@ For development work
|
|||
void SV_Map_f( void )
|
||||
{
|
||||
string filename;
|
||||
char *spawn_entity;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
|
@ -200,28 +201,40 @@ void SV_Map_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
com.snprintf( filename, MAX_STRING, "%s.bsp", Cmd_Argv(1));
|
||||
if( !FS_FileExists( va("maps/%s", filename )))
|
||||
// determine spawn entity classname
|
||||
if( Cvar_VariableInteger( "deathmatch" ))
|
||||
spawn_entity = GI->dm_entity;
|
||||
else if( Cvar_VariableInteger( "coop" ))
|
||||
spawn_entity = GI->coop_entity;
|
||||
else if( Cvar_VariableInteger( "teamplay" ))
|
||||
spawn_entity = GI->team_entity;
|
||||
else spawn_entity = GI->sp_entity;
|
||||
|
||||
com.strncpy( filename, Cmd_Argv( 1 ), sizeof( filename ));
|
||||
if( !SV_MapIsValid( filename, spawn_entity ))
|
||||
{
|
||||
Msg( "Can't loading %s\n", filename );
|
||||
Msg( "SV_NewMap: invalid map %s\n", filename );
|
||||
return;
|
||||
}
|
||||
|
||||
SV_InitGame(); // reset previous state
|
||||
sv.loadgame = false; // set right state
|
||||
sv.changelevel = false;
|
||||
|
||||
if( com.strcmp( sv.name, filename ))
|
||||
SV_InitGame ();
|
||||
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
SV_SendClientMessages();
|
||||
SV_SpawnServer( filename, NULL );
|
||||
SV_BroadcastCommand( "reconnect\n" );
|
||||
|
||||
// archive server state
|
||||
com.strncpy( svs.mapname, filename, sizeof( svs.mapname ) - 1 );
|
||||
SV_LevelInit( filename, NULL, NULL );
|
||||
SV_ActivateServer ();
|
||||
}
|
||||
|
||||
void SV_Newgame_f( void )
|
||||
{
|
||||
// FIXME: do some clear operations
|
||||
// FIXME: parse newgame script
|
||||
com.strncpy( host.finalmsg, "end game", MAX_STRING );
|
||||
SV_Shutdown( false ); // completely shutdown server, disconncet clients and unload progs
|
||||
|
||||
// FIXME: parse newgame script or somewhat
|
||||
|
||||
Cbuf_ExecuteText( EXEC_APPEND, va( "map %s\n", GI->startmap ));
|
||||
}
|
||||
|
||||
|
@ -241,18 +254,20 @@ void SV_Load_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
com.snprintf( filename, MAX_STRING, "%s.bin", Cmd_Argv( 1 ));
|
||||
if(!FS_FileExists( va( "save/%s", filename )))
|
||||
com.strncpy( filename, Cmd_Argv( 1 ), sizeof( filename ));
|
||||
if(WAD_Check( va( "save/%s.bin", filename )) != 1 )
|
||||
{
|
||||
Msg( "Can't loading %s\n", filename );
|
||||
return;
|
||||
}
|
||||
|
||||
sv.loadgame = true; // set right state
|
||||
sv.changelevel = false;
|
||||
|
||||
SV_ReadSaveFile( filename );
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
SV_SendClientMessages();
|
||||
SV_SpawnServer( svs.mapname, filename );
|
||||
SV_BroadcastCommand( "reconnect\n" );
|
||||
SV_SpawnServer( svs.mapname, NULL );
|
||||
SV_LevelInit( svs.mapname, NULL, filename );
|
||||
SV_ActivateServer();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -268,7 +283,7 @@ void SV_Save_f( void )
|
|||
Msg( "Usage: save <name>\n" );
|
||||
return;
|
||||
}
|
||||
SV_WriteSaveFile( Cmd_Argv( 1 ), false );
|
||||
SV_WriteSaveFile( Cmd_Argv( 1 ), false, true );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -298,7 +313,7 @@ SV_AutoSave_f
|
|||
*/
|
||||
void SV_AutoSave_f( void )
|
||||
{
|
||||
SV_WriteSaveFile( "autosave", true );
|
||||
SV_WriteSaveFile( "autosave", true, true );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -310,52 +325,37 @@ Saves the state of the map just being exited and goes to a new map.
|
|||
*/
|
||||
void SV_ChangeLevel_f( void )
|
||||
{
|
||||
string filename;
|
||||
char *spawn_entity;
|
||||
int c = Cmd_Argc();
|
||||
|
||||
if( c != 2 && c != 3 )
|
||||
// determine spawn entity classname
|
||||
if( Cvar_VariableInteger( "deathmatch" ))
|
||||
spawn_entity = GI->dm_entity;
|
||||
else if( Cvar_VariableInteger( "coop" ))
|
||||
spawn_entity = GI->coop_entity;
|
||||
else if( Cvar_VariableInteger( "teamplay" ))
|
||||
spawn_entity = GI->team_entity;
|
||||
else spawn_entity = GI->sp_entity;
|
||||
|
||||
if( !SV_MapIsValid( Cmd_Argv( 1 ), spawn_entity ))
|
||||
{
|
||||
Msg ("Usage: changelevel <map> [landmark]\n");
|
||||
Msg( "SV_ChangeLevel: invalid map %s\n", Cmd_Argv( 1 ));
|
||||
return;
|
||||
}
|
||||
|
||||
com.snprintf( filename, MAX_STRING, "%s.bsp", Cmd_Argv(1));
|
||||
if(!FS_FileExists(va("maps/%s", filename )))
|
||||
if( sv.state != ss_active )
|
||||
{
|
||||
Msg("Can't loading %s\n", filename );
|
||||
// just load map
|
||||
Cbuf_AddText( va( "map %s\n", Cmd_Argv( 1 )));
|
||||
return;
|
||||
}
|
||||
|
||||
if( sv.state == ss_active )
|
||||
switch( c )
|
||||
{
|
||||
bool *savedFree;
|
||||
sv_client_t *cl;
|
||||
int i;
|
||||
|
||||
// clear all the client free flags before saving so that
|
||||
// when the level is re-entered, the clients will spawn
|
||||
// at spawn points instead of occupying body shells
|
||||
savedFree = Z_Malloc( sv_maxclients->integer * sizeof( bool ));
|
||||
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
|
||||
{
|
||||
savedFree[i] = cl->edict->free;
|
||||
cl->edict->free = true;
|
||||
case 2: SV_ChangeLevel( false, Cmd_Argv( 1 ), NULL ); break;
|
||||
case 3: SV_ChangeLevel( true, Cmd_Argv( 1 ), Cmd_Argv( 2 )); break;
|
||||
default: Msg( "Usage: changelevel <map> [landmark]\n" ); break;
|
||||
}
|
||||
SV_WriteSaveFile( "autosave", true );
|
||||
// we must restore these for clients to transfer over correctly
|
||||
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
|
||||
cl->edict->free = savedFree[i];
|
||||
Mem_Free( savedFree );
|
||||
}
|
||||
|
||||
SV_InitGame(); // reset previous state
|
||||
SV_BroadcastCommand("changing\n");
|
||||
SV_SendClientMessages();
|
||||
SV_SpawnServer( filename, NULL );
|
||||
SV_BroadcastCommand ("reconnect\n");
|
||||
|
||||
// archive server state
|
||||
com.strncpy( svs.mapname, filename, sizeof( svs.mapname ) - 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -377,6 +377,21 @@ void SV_Restart_f( void )
|
|||
Cbuf_AddText( va( "map %s\n", filename ));
|
||||
}
|
||||
|
||||
void SV_Reload_f( void )
|
||||
{
|
||||
const char *save;
|
||||
string loadname;
|
||||
|
||||
if( sv.state != ss_active ) return;
|
||||
save = SV_GetLatestSave();
|
||||
if( save )
|
||||
{
|
||||
FS_FileBase( save, loadname );
|
||||
Cbuf_AddText( va( "load %s\n", loadname ));
|
||||
}
|
||||
else Cbuf_AddText( "newgame\n" ); // begin new game
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Kick_f
|
||||
|
@ -564,6 +579,7 @@ void SV_InitOperatorCommands( void )
|
|||
Cmd_AddCommand( "newgame", SV_Newgame_f, "begin new game" );
|
||||
Cmd_AddCommand( "changelevel", SV_ChangeLevel_f, "changing level" );
|
||||
Cmd_AddCommand( "restart", SV_Restart_f, "restarting current level" );
|
||||
Cmd_AddCommand( "reload", SV_Reload_f, "continue from latest save or restart level" );
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
|
@ -591,6 +607,7 @@ void SV_KillOperatorCommands( void )
|
|||
Cmd_RemoveCommand( "newgame" );
|
||||
Cmd_RemoveCommand( "changelevel" );
|
||||
Cmd_RemoveCommand( "restart" );
|
||||
Cmd_RemoveCommand( "reload" );
|
||||
Cmd_RemoveCommand( "sectorlist" );
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
|
|
|
@ -141,13 +141,17 @@ void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t
|
|||
|
||||
if( newnum == oldnum )
|
||||
{
|
||||
bool newentity = false;
|
||||
|
||||
// delta update from old position
|
||||
// because the force parm is false, this will not result
|
||||
// in any bytes being emited if the entity has not changed at all
|
||||
// note that players are always 'newentities', this updates their oldorigin always
|
||||
// and prevents warping
|
||||
MSG_WriteDeltaEntity( oldent, newent, msg, false,
|
||||
(newent->ed_type == ED_CLIENT) || (newent->ed_type == ED_PORTAL));
|
||||
if( newent->ed_type == ED_CLIENT ) newentity = true;
|
||||
if( newent->ed_type == ED_PORTAL ) newentity = true;
|
||||
|
||||
MSG_WriteDeltaEntity( oldent, newent, msg, false, newentity );
|
||||
oldindex++;
|
||||
newindex++;
|
||||
continue;
|
||||
|
@ -358,11 +362,9 @@ void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
|
|||
}
|
||||
}
|
||||
|
||||
MSG_WriteByte( msg, svc_time );
|
||||
MSG_WriteLong( msg, sv.time ); // send a servertime before each frame
|
||||
|
||||
MSG_WriteByte( msg, svc_frame );
|
||||
MSG_WriteLong( msg, sv.framenum );
|
||||
MSG_WriteLong( msg, sv.time ); // send a servertime each frame
|
||||
MSG_WriteLong( msg, sv.frametime );
|
||||
MSG_WriteLong( msg, lastframe ); // what we are delta'ing from
|
||||
MSG_WriteByte( msg, cl->surpressCount ); // rate dropped packets
|
||||
|
@ -372,14 +374,14 @@ void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
|
|||
MSG_WriteByte( msg, frame->areabits_size ); // never more than 255 bytes
|
||||
MSG_WriteData( msg, frame->areabits, frame->areabits_size );
|
||||
|
||||
// delta encode the entities
|
||||
SV_EmitPacketEntities( oldframe, frame, msg );
|
||||
|
||||
// just send an client index
|
||||
// it's safe, because NUM_FOR_EDICT always equal ed->serialnumber,
|
||||
// thats shared across network
|
||||
MSG_WriteByte( msg, svc_playerinfo );
|
||||
MSG_WriteByte( msg, frame->index );
|
||||
|
||||
// delta encode the entities
|
||||
SV_EmitPacketEntities( oldframe, frame, msg );
|
||||
}
|
||||
|
||||
|
||||
|
@ -559,6 +561,8 @@ void SV_SendClientMessages( void )
|
|||
sv_client_t *cl;
|
||||
int i;
|
||||
|
||||
if( sv.state == ss_dead ) return;
|
||||
|
||||
// send a message to each connected client
|
||||
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
|
||||
{
|
||||
|
|
|
@ -561,6 +561,126 @@ static bool SV_EntitiesIn( int mode, vec3_t v1, vec3_t v2 )
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SV_MapIsValid( const char *filename, const char *spawn_entity )
|
||||
{
|
||||
file_t *f;
|
||||
string entfilename;
|
||||
int ver = -1, lumpofs = 0, lumplen = 0;
|
||||
script_t *ents = NULL;
|
||||
byte buf[MAX_SYSPATH]; // 1 kb
|
||||
bool result = false;
|
||||
|
||||
f = FS_Open( va( "maps/%s.bsp", filename ), "rb" );
|
||||
|
||||
if( f )
|
||||
{
|
||||
string check_entity;
|
||||
|
||||
Mem_Set( buf, 0, MAX_SYSPATH );
|
||||
FS_Read( f, buf, MAX_SYSPATH );
|
||||
|
||||
if( !memcmp( buf, "IBSP", 4 ) || !memcmp( buf, "RBSP", 4 ) || !memcmp( buf, "FBSP", 4 ))
|
||||
{
|
||||
dheader_t *header = (dheader_t *)buf;
|
||||
ver = LittleLong(((int *)buf)[1]);
|
||||
|
||||
switch( ver )
|
||||
{
|
||||
case Q3IDBSP_VERSION: // quake3 arena
|
||||
case RTCWBSP_VERSION: // return to castle wolfenstein
|
||||
case RFIDBSP_VERSION: // raven or qfusion bsp
|
||||
lumpofs = LittleLong( header->lumps[LUMP_ENTITIES].fileofs );
|
||||
lumplen = LittleLong( header->lumps[LUMP_ENTITIES].filelen );
|
||||
break;
|
||||
default:
|
||||
FS_Close( f );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_Close( f );
|
||||
return false;
|
||||
}
|
||||
|
||||
com.strncpy( entfilename, va( "maps/%s.ent", filename ), sizeof( entfilename ));
|
||||
ents = Com_OpenScript( entfilename, NULL, 0 );
|
||||
|
||||
if( !ents && lumplen >= 10 )
|
||||
{
|
||||
char *entities = NULL;
|
||||
|
||||
FS_Seek( f, lumpofs, SEEK_SET );
|
||||
entities = (char *)Z_Malloc( lumplen + 1 );
|
||||
FS_Read( f, entities, lumplen );
|
||||
ents = Com_OpenScript( "ents", entities, lumplen + 1 );
|
||||
Mem_Free( entities ); // no reason to keep it
|
||||
}
|
||||
|
||||
if( ents )
|
||||
{
|
||||
// if there are entities to parse, a missing message key just
|
||||
// means there is no title, so clear the message string now
|
||||
token_t token;
|
||||
|
||||
check_entity[0] = 0;
|
||||
while( Com_ReadToken( ents, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &token ))
|
||||
{
|
||||
if( !com.strcmp( token.string, "classname" ))
|
||||
{
|
||||
// check classname for spawn entity
|
||||
Com_ReadString( ents, false, check_entity );
|
||||
if( !com.stricmp( spawn_entity, check_entity ))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Com_CloseScript( ents );
|
||||
}
|
||||
if( f ) FS_Close( f );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SV_PushClients( void )
|
||||
{
|
||||
edict_t *in, *out;
|
||||
int i;
|
||||
|
||||
svgame.num_saved_edicts = 0;
|
||||
|
||||
// hold the clients in other place
|
||||
for( i = 0; i < sv_maxclients->integer; i++ )
|
||||
{
|
||||
in = EDICT_NUM( i + 1 );
|
||||
out = svgame.saved_edicts + i;
|
||||
|
||||
if( SV_CopyEdict( out, in ))
|
||||
svgame.num_saved_edicts++;
|
||||
}
|
||||
}
|
||||
|
||||
void SV_PopClients( void )
|
||||
{
|
||||
edict_t *in, *out;
|
||||
int i;
|
||||
|
||||
// copy clients back to sv.edicts
|
||||
for( i = 0; i < svgame.num_saved_edicts; i++ )
|
||||
{
|
||||
in = svgame.saved_edicts + i;
|
||||
out = EDICT_NUM( i + 1 );
|
||||
|
||||
if( SV_CopyEdict( out, in ))
|
||||
svgame.globals->numClients++;
|
||||
if( svgame.globals->numClients > sv_maxclients->integer )
|
||||
break;
|
||||
}
|
||||
svgame.num_saved_edicts = 0;
|
||||
}
|
||||
|
||||
void SV_InitEdict( edict_t *pEdict )
|
||||
{
|
||||
Com_Assert( pEdict == NULL );
|
||||
|
@ -625,6 +745,41 @@ edict_t *SV_AllocEdict( void )
|
|||
return pEdict;
|
||||
}
|
||||
|
||||
bool SV_CopyEdict( edict_t *out, edict_t *in )
|
||||
{
|
||||
size_t pvdata_size = 0;
|
||||
|
||||
if( in == NULL )
|
||||
return false; // failed to copy
|
||||
if( in->free ) return false; // we can't proceed freed edicts
|
||||
|
||||
// important! we save copy off, not in sv.edicts
|
||||
if( out == NULL ) Host_Error( "SV_CopyEdict: dest == NULL\n" );
|
||||
|
||||
if( in->pvServerData )
|
||||
{
|
||||
if( out->pvServerData == NULL )
|
||||
out->pvServerData = (sv_priv_t *)Mem_Alloc( svgame.mempool, sizeof( sv_priv_t ));
|
||||
Mem_Copy( out->pvServerData, in->pvServerData, sizeof( sv_priv_t ));
|
||||
pvdata_size = in->pvServerData->pvdata_size;
|
||||
}
|
||||
if( in->pvPrivateData )
|
||||
{
|
||||
if( pvdata_size > 0 )
|
||||
{
|
||||
out->pvPrivateData = (void *)Mem_Realloc( svgame.mempool, out->pvPrivateData, pvdata_size );
|
||||
Mem_Copy( out->pvPrivateData, in->pvPrivateData, pvdata_size );
|
||||
}
|
||||
else MsgDev( D_ERROR, "SV_CopyEdict: can't copy pvPrivateData\n" );
|
||||
}
|
||||
|
||||
Mem_Copy( &out->v, &in->v, sizeof( entvars_t )); // copy entvars
|
||||
out->serialnumber = in->serialnumber; // copy serialnumber
|
||||
out->v.pContainingEntity = out; // merge contain entity
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
edict_t* SV_AllocPrivateData( edict_t *ent, string_t className )
|
||||
{
|
||||
const char *pszClassName;
|
||||
|
@ -664,7 +819,7 @@ edict_t* SV_AllocPrivateData( edict_t *ent, string_t className )
|
|||
|
||||
void SV_FreeEdicts( void )
|
||||
{
|
||||
int i;
|
||||
int i = 0;
|
||||
edict_t *ent;
|
||||
|
||||
for( i = 0; i < svgame.globals->numEntities; i++ )
|
||||
|
@ -673,19 +828,6 @@ void SV_FreeEdicts( void )
|
|||
if( ent->free ) continue;
|
||||
SV_FreeEdict( ent );
|
||||
}
|
||||
|
||||
if( !sv.loadgame )
|
||||
{
|
||||
// leave unchanged, because we wan't load it twice
|
||||
StringTable_Clear( svgame.hStringTable );
|
||||
svgame.dllFuncs.pfnServerDeactivate();
|
||||
}
|
||||
|
||||
svgame.globals->maxEntities = GI->max_edicts;
|
||||
svgame.globals->maxClients = sv_maxclients->integer;
|
||||
svgame.globals->numEntities = svgame.globals->maxClients + 1; // clients + world
|
||||
svgame.globals->numClients = 0;
|
||||
svgame.globals->mapname = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -837,10 +979,11 @@ pfnChangeLevel
|
|||
*/
|
||||
void pfnChangeLevel( const char* s1, const char* s2 )
|
||||
{
|
||||
string changelevel_cmd;
|
||||
// make sure we don't issue two changelevels
|
||||
if( sv.changelevel ) return;
|
||||
|
||||
com.snprintf( changelevel_cmd, MAX_STRING, "changelevel %s %s\n", s1, s2 );
|
||||
Cbuf_ExecuteText( EXEC_APPEND, changelevel_cmd );
|
||||
if( !s2 ) Cbuf_AddText( va( "changelevel %s\n", s1 )); // Quake changlevel
|
||||
else Cbuf_AddText( va( "changelevel %s %s\n", s1, s2 )); // Half-Life changelevel
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1174,12 +1317,14 @@ pfnEntitiesInPVS
|
|||
edict_t* pfnEntitiesInPVS( edict_t *pplayer )
|
||||
{
|
||||
edict_t *pEdict, *chain;
|
||||
int i, numents;
|
||||
int i;
|
||||
|
||||
chain = NULL;
|
||||
numents = svgame.globals->numEntities;
|
||||
|
||||
for( i = svgame.globals->maxClients; i < numents; i++ )
|
||||
if( !pplayer || pplayer->free )
|
||||
return chain;
|
||||
|
||||
for( i = svgame.globals->maxClients; i < svgame.globals->numEntities; i++ )
|
||||
{
|
||||
pEdict = EDICT_NUM( i );
|
||||
if( pEdict->free ) continue;
|
||||
|
@ -1202,12 +1347,14 @@ pfnEntitiesInPHS
|
|||
edict_t* pfnEntitiesInPHS( edict_t *pplayer )
|
||||
{
|
||||
edict_t *pEdict, *chain;
|
||||
int i, numents;
|
||||
int i;
|
||||
|
||||
chain = NULL;
|
||||
numents = svgame.globals->numEntities;
|
||||
|
||||
for( i = svgame.globals->maxClients; i < numents; i++ )
|
||||
if( !pplayer || pplayer->free )
|
||||
return chain;
|
||||
|
||||
for( i = svgame.globals->maxClients; i < svgame.globals->numEntities; i++ )
|
||||
{
|
||||
pEdict = EDICT_NUM( i );
|
||||
if( pEdict->free ) continue;
|
||||
|
@ -1832,11 +1979,11 @@ pfnMessageBegin
|
|||
|
||||
=============
|
||||
*/
|
||||
void pfnMessageBegin( int msg_dest, int msg_type, const float *pOrigin, edict_t *ed )
|
||||
void pfnMessageBegin( int msg_dest, int msg_num, const float *pOrigin, edict_t *ed )
|
||||
{
|
||||
// some users can send message with engine index
|
||||
// some malicious users can send message with engine index
|
||||
// reduce number to avoid overflow problems or cheating
|
||||
svgame.msg_index = bound( svc_bad, msg_type, svc_nop );
|
||||
svgame.msg_index = bound( svc_bad, msg_num, svc_nop );
|
||||
|
||||
if( svgame.msg_index >= 0 && svgame.msg_index < MAX_USER_MESSAGES )
|
||||
svgame.msg_name = sv.configstrings[CS_USER_MESSAGES + svgame.msg_index];
|
||||
|
@ -1848,7 +1995,7 @@ void pfnMessageBegin( int msg_dest, int msg_type, const float *pOrigin, edict_t
|
|||
if( pOrigin ) VectorCopy( pOrigin, svgame.msg_org );
|
||||
else VectorClear( svgame.msg_org );
|
||||
|
||||
if( svgame.msg_sizes[msg_type] == -1 )
|
||||
if( svgame.msg_sizes[msg_num] == -1 )
|
||||
{
|
||||
// variable sized messages sent size as first byte
|
||||
svgame.msg_size_index = sv.multicast.cursize;
|
||||
|
@ -1889,17 +2036,23 @@ void pfnMessageEnd( void )
|
|||
else if( svgame.msg_size_index != -1 )
|
||||
{
|
||||
// variable sized message
|
||||
if( svgame.msg_realsize >= 255 )
|
||||
if( svgame.msg_realsize > 255 )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_Message: %s too long (more than 255 bytes)\n", name );
|
||||
MSG_Clear( &sv.multicast );
|
||||
return;
|
||||
}
|
||||
else if( svgame.msg_realsize <= 0 )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_Message: %s writes NULL message\n", name );
|
||||
MSG_Clear( &sv.multicast );
|
||||
return;
|
||||
}
|
||||
sv.multicast.data[svgame.msg_size_index] = svgame.msg_realsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this never happen
|
||||
// this should never happen
|
||||
MsgDev( D_ERROR, "SV_Message: %s have encountered error\n", name );
|
||||
MSG_Clear( &sv.multicast );
|
||||
return;
|
||||
|
@ -1978,7 +2131,8 @@ pfnWriteCoord
|
|||
*/
|
||||
void pfnWriteCoord( float flValue )
|
||||
{
|
||||
union { float f; int l; } dat;
|
||||
ftol_t dat;
|
||||
|
||||
dat.f = flValue;
|
||||
_MSG_WriteBits( &sv.multicast, dat.l, svgame.msg_name, NET_FLOAT, __FILE__, __LINE__ );
|
||||
svgame.msg_realsize += 4;
|
||||
|
@ -2010,7 +2164,7 @@ void pfnWriteString( const char *sz )
|
|||
MSG_WriteString( &sv.multicast, sz );
|
||||
total_size = sv.multicast.cursize - cur_size;
|
||||
|
||||
// some messages with constant string length can be marked as known sized
|
||||
// NOTE: some messages with constant string length can be marked as known sized
|
||||
svgame.msg_realsize += total_size;
|
||||
}
|
||||
|
||||
|
@ -2022,7 +2176,8 @@ pfnWriteEntity
|
|||
*/
|
||||
void pfnWriteEntity( int iValue )
|
||||
{
|
||||
if( iValue < 0 || iValue > svgame.globals->numEntities )
|
||||
// edict -1 it's a viewmodel entity
|
||||
if( iValue < -1 || iValue > svgame.globals->numEntities )
|
||||
Host_Error( "MSG_WriteEntity: invalid entnumber %d\n", iValue );
|
||||
MSG_WriteShort( &sv.multicast, iValue );
|
||||
svgame.msg_realsize += 2;
|
||||
|
@ -2081,9 +2236,12 @@ pfnPvAllocEntPrivateData
|
|||
void *pfnPvAllocEntPrivateData( edict_t *pEdict, long cb )
|
||||
{
|
||||
Com_Assert( pEdict == NULL );
|
||||
Com_Assert( pEdict->free );
|
||||
Com_Assert( pEdict->pvServerData == NULL );
|
||||
|
||||
// to avoid multiple alloc
|
||||
pEdict->pvPrivateData = (void *)Mem_Realloc( svgame.private, pEdict->pvPrivateData, cb );
|
||||
pEdict->pvServerData->pvdata_size = cb;
|
||||
|
||||
return pEdict->pvPrivateData;
|
||||
}
|
||||
|
@ -2190,6 +2348,8 @@ pfnPEntityOfEntIndex
|
|||
*/
|
||||
edict_t* pfnPEntityOfEntIndex( int iEntIndex )
|
||||
{
|
||||
if( iEntIndex < 0 || iEntIndex >= svgame.globals->numEntities )
|
||||
return NULL; // out of range
|
||||
return EDICT_NUM( iEntIndex );
|
||||
}
|
||||
|
||||
|
@ -2538,18 +2698,19 @@ pfnCompareFileTime
|
|||
*/
|
||||
int pfnCompareFileTime( const char *filename1, const char *filename2, int *iCompare )
|
||||
{
|
||||
int time1 = FS_FileTime( filename1 );
|
||||
int time2 = FS_FileTime( filename2 );
|
||||
int bRet = 0;
|
||||
|
||||
if( iCompare )
|
||||
*iCompare = 0;
|
||||
|
||||
if( filename1 && filename2 )
|
||||
{
|
||||
if( time1 > time2 )
|
||||
*iCompare = 1;
|
||||
else if( time1 < time2 )
|
||||
*iCompare = -1;
|
||||
else *iCompare = 0;
|
||||
long ft1 = FS_FileTime( filename1 );
|
||||
long ft2 = FS_FileTime( filename2 );
|
||||
|
||||
*iCompare = Host_CompareFileTime( ft1, ft2 );
|
||||
bRet = 1;
|
||||
}
|
||||
return (time1 != time2);
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2596,88 +2757,18 @@ vaild map must contain one info_player_deatchmatch
|
|||
*/
|
||||
int pfnIsMapValid( char *filename )
|
||||
{
|
||||
file_t *f;
|
||||
string entfilename;
|
||||
int ver = -1, lumpofs = 0, lumplen = 0;
|
||||
script_t *ents = NULL;
|
||||
byte buf[MAX_SYSPATH]; // 1 kb
|
||||
bool result = false;
|
||||
char *spawn_entity;
|
||||
|
||||
f = FS_Open( va( "maps/%s.bsp", filename ), "rb" );
|
||||
// determine spawn entity classname
|
||||
if( Cvar_VariableInteger( "deathmatch" ))
|
||||
spawn_entity = GI->dm_entity;
|
||||
else if( Cvar_VariableInteger( "coop" ))
|
||||
spawn_entity = GI->coop_entity;
|
||||
else if( Cvar_VariableInteger( "teamplay" ))
|
||||
spawn_entity = GI->team_entity;
|
||||
else spawn_entity = GI->sp_entity;
|
||||
|
||||
if( f )
|
||||
{
|
||||
string dm_entity;
|
||||
|
||||
Mem_Set( buf, 0, MAX_SYSPATH );
|
||||
FS_Read( f, buf, MAX_SYSPATH );
|
||||
|
||||
if( !memcmp( buf, "IBSP", 4 ) || !memcmp( buf, "RBSP", 4 ) || !memcmp( buf, "FBSP", 4 ))
|
||||
{
|
||||
dheader_t *header = (dheader_t *)buf;
|
||||
ver = LittleLong(((int *)buf)[1]);
|
||||
|
||||
switch( ver )
|
||||
{
|
||||
case Q3IDBSP_VERSION: // quake3 arena
|
||||
case RTCWBSP_VERSION: // return to castle wolfenstein
|
||||
case RFIDBSP_VERSION: // raven or qfusion bsp
|
||||
lumpofs = LittleLong( header->lumps[LUMP_ENTITIES].fileofs );
|
||||
lumplen = LittleLong( header->lumps[LUMP_ENTITIES].filelen );
|
||||
break;
|
||||
default:
|
||||
FS_Close( f );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_Close( f );
|
||||
return false;
|
||||
}
|
||||
|
||||
com.strncpy( entfilename, va( "maps/%s.ent", filename ), sizeof( entfilename ));
|
||||
ents = Com_OpenScript( entfilename, NULL, 0 );
|
||||
|
||||
if( !ents && lumplen >= 10 )
|
||||
{
|
||||
char *entities = NULL;
|
||||
|
||||
FS_Seek( f, lumpofs, SEEK_SET );
|
||||
entities = (char *)Z_Malloc( lumplen + 1 );
|
||||
FS_Read( f, entities, lumplen );
|
||||
ents = Com_OpenScript( "ents", entities, lumplen + 1 );
|
||||
Mem_Free( entities ); // no reason to keep it
|
||||
}
|
||||
|
||||
if( ents )
|
||||
{
|
||||
// if there are entities to parse, a missing message key just
|
||||
// means there is no title, so clear the message string now
|
||||
token_t token;
|
||||
|
||||
dm_entity[0] = 0;
|
||||
while( Com_ReadToken( ents, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &token ))
|
||||
{
|
||||
if( !com.strcmp( token.string, "{" )) continue;
|
||||
else if( !com.strcmp( token.string, "}" )) break;
|
||||
else if( !com.strcmp( token.string, "classname" ))
|
||||
{
|
||||
// check classname for deathmath entity
|
||||
Com_ReadString( ents, false, dm_entity );
|
||||
if( !com.stricmp( GI->dm_entity, dm_entity ))
|
||||
{
|
||||
// FIXME: use count of spawnpoints as returned result ?
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Com_CloseScript( ents );
|
||||
}
|
||||
if( f ) FS_Close( f );
|
||||
}
|
||||
return result;
|
||||
return SV_MapIsValid( filename, spawn_entity );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3175,12 +3266,11 @@ void SV_SpawnEntities( const char *mapname, script_t *entities )
|
|||
MsgDev( D_NOTE, "SV_SpawnEntities()\n" );
|
||||
|
||||
ent = EDICT_NUM( 0 );
|
||||
SV_InitEdict( ent );
|
||||
ent->v.model = MAKE_STRING( sv.configstrings[CS_MODELS] );
|
||||
if( ent->free ) SV_InitEdict( ent );
|
||||
ent->v.model = MAKE_STRING( sv.configstrings[CS_MODELS+1] );
|
||||
ent->v.modelindex = 1; // world model
|
||||
ent->v.solid = SOLID_BSP;
|
||||
ent->v.movetype = MOVETYPE_PUSH;
|
||||
ent->free = false;
|
||||
|
||||
SV_ConfigString( CS_GRAVITY, sv_gravity->string );
|
||||
SV_ConfigString( CS_MAXVELOCITY, sv_maxvelocity->string );
|
||||
|
@ -3195,12 +3285,15 @@ void SV_SpawnEntities( const char *mapname, script_t *entities )
|
|||
SV_ConfigString( CS_MAXEDICTS, va( "%i", GI->max_edicts ));
|
||||
|
||||
svgame.globals->mapname = MAKE_STRING( sv.name );
|
||||
svgame.globals->startspot = MAKE_STRING( sv.startspot );
|
||||
svgame.globals->time = sv.time * 0.001f;
|
||||
|
||||
// spawn the rest of the entities on the map
|
||||
SV_LoadFromFile( entities );
|
||||
|
||||
// set client fields on player ents
|
||||
if( !sv.loadgame && !sv.changelevel )
|
||||
{
|
||||
for( i = 0; i < svgame.globals->maxClients; i++ )
|
||||
{
|
||||
// setup all clients
|
||||
|
@ -3210,13 +3303,13 @@ void SV_SpawnEntities( const char *mapname, script_t *entities )
|
|||
ent->pvServerData->client->edict = ent;
|
||||
svgame.globals->numClients++;
|
||||
}
|
||||
}
|
||||
MsgDev( D_INFO, "Total %i entities spawned\n", svgame.globals->numEntities );
|
||||
}
|
||||
|
||||
void SV_UnloadProgs( void )
|
||||
{
|
||||
sv.loadgame = false;
|
||||
SV_FreeEdicts();
|
||||
SV_DeactivateServer ();
|
||||
|
||||
svgame.dllFuncs.pfnGameShutdown ();
|
||||
|
||||
|
@ -3226,6 +3319,8 @@ void SV_UnloadProgs( void )
|
|||
Mem_FreePool( &svgame.private );
|
||||
Mem_FreePool( &svgame.temppool );
|
||||
svgame.hInstance = NULL;
|
||||
|
||||
Mem_Set( &svgame, 0, sizeof( svgame ));
|
||||
}
|
||||
|
||||
void SV_LoadProgs( const char *name )
|
||||
|
@ -3276,6 +3371,7 @@ void SV_LoadProgs( const char *name )
|
|||
svgame.globals->maxEntities = GI->max_edicts;
|
||||
svgame.globals->maxClients = sv_maxclients->integer;
|
||||
svgame.edicts = Mem_Alloc( svgame.mempool, sizeof( edict_t ) * svgame.globals->maxEntities );
|
||||
svgame.saved_edicts = Mem_Alloc( svgame.mempool, sizeof( edict_t ) * svgame.globals->maxClients );
|
||||
svgame.globals->numEntities = svgame.globals->maxClients + 1; // clients + world
|
||||
svgame.globals->numClients = 0;
|
||||
for( i = 0, e = svgame.edicts; i < svgame.globals->maxEntities; i++, e++ )
|
||||
|
|
|
@ -144,6 +144,96 @@ void SV_CheckForSavegame( const char *savename )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ActivateServer
|
||||
|
||||
activate server on changed map, run physics
|
||||
================
|
||||
*/
|
||||
void SV_ActivateServer( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
// Activate the DLL server code
|
||||
svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.globals->numEntities, svgame.globals->maxClients );
|
||||
|
||||
// all precaches are complete
|
||||
sv.state = ss_active;
|
||||
Host_SetServerState( sv.state );
|
||||
|
||||
// create a baseline for more efficient communications
|
||||
SV_CreateBaseline();
|
||||
|
||||
// run two frames to allow everything to settle
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
sv.frametime = 100;
|
||||
SV_Physics();
|
||||
}
|
||||
|
||||
// tell what kind of server has been started.
|
||||
if( svgame.globals->maxClients > 1 )
|
||||
{
|
||||
MsgDev( D_INFO, "%i player server started\n", svgame.globals->maxClients );
|
||||
}
|
||||
else
|
||||
{
|
||||
MsgDev( D_INFO, "Game started\n" );
|
||||
}
|
||||
|
||||
// set serverinfo variable
|
||||
Cvar_FullSet( "mapname", sv.name, CVAR_SERVERINFO|CVAR_INIT );
|
||||
|
||||
pe->EndRegistration (); // free unused models
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_DeactivateServer
|
||||
|
||||
deactivate server, free edicts stringtables etc
|
||||
================
|
||||
*/
|
||||
void SV_DeactivateServer( void )
|
||||
{
|
||||
SV_FreeEdicts ();
|
||||
|
||||
Cvar_SetValue( "paused", 0 );
|
||||
|
||||
// leave unchanged, because we wan't load it twice
|
||||
if( !sv.loadgame ) StringTable_Clear( svgame.hStringTable );
|
||||
|
||||
svgame.dllFuncs.pfnServerDeactivate();
|
||||
|
||||
svgame.globals->maxEntities = GI->max_edicts;
|
||||
svgame.globals->maxClients = sv_maxclients->integer;
|
||||
svgame.globals->numEntities = svgame.globals->maxClients + 1; // clients + world
|
||||
svgame.globals->numClients = 0;
|
||||
svgame.globals->mapname = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_LevelInit
|
||||
|
||||
Spawn all entities
|
||||
================
|
||||
*/
|
||||
void SV_LevelInit( const char *newmap, const char *oldmap, const char *savename )
|
||||
{
|
||||
if( sv.loadgame )
|
||||
{
|
||||
if( savename ) SV_ReadLevelFile( savename );
|
||||
else SV_SpawnEntities( newmap, pe->GetEntityScript( ));
|
||||
}
|
||||
else if( sv.changelevel )
|
||||
{
|
||||
SV_ReadSaveFile( savename ); // initialize StringTable and globals
|
||||
SV_MergeLevelFile( savename );// combine moveable entities with newmap
|
||||
}
|
||||
else SV_SpawnEntities( newmap, pe->GetEntityScript());
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -154,24 +244,43 @@ clients along with it.
|
|||
|
||||
================
|
||||
*/
|
||||
void SV_SpawnServer( const char *server, const char *savename )
|
||||
void SV_SpawnServer( const char *server, const char *startspot )
|
||||
{
|
||||
uint i, checksum;
|
||||
int current_skill;
|
||||
int loadgame, changelevel;
|
||||
|
||||
Msg( "SpawnServer [%s]\n", server );
|
||||
Msg( "SpawnServer [^2%s^7]\n", server );
|
||||
|
||||
if( sv.state == ss_dead && !sv.loadgame )
|
||||
SV_InitGame(); // the game is just starting
|
||||
|
||||
SV_BroadcastCommand( "changing\n" );
|
||||
|
||||
if( sv.state == ss_active )
|
||||
{
|
||||
SV_BroadcastCommand( "reconnect\n" );
|
||||
SV_SendClientMessages();
|
||||
SV_DeactivateServer (); // server is shutting down ...
|
||||
}
|
||||
|
||||
svs.timestart = Sys_Milliseconds();
|
||||
svs.spawncount++; // any partially connected client will be restarted
|
||||
|
||||
// save state
|
||||
loadgame = sv.loadgame;
|
||||
changelevel = sv.changelevel;
|
||||
|
||||
sv.state = ss_dead;
|
||||
Host_SetServerState( sv.state );
|
||||
Mem_Set( &sv, 0, sizeof( sv )); // wipe the entire per-level structure
|
||||
|
||||
// wipe the entire per-level structure
|
||||
Mem_Set( &sv, 0, sizeof( sv ));
|
||||
// restore state
|
||||
sv.loadgame = loadgame;
|
||||
sv.changelevel = changelevel;
|
||||
|
||||
// save name for levels that don't set message
|
||||
com.strncpy( sv.configstrings[CS_NAME], server, CS_SIZE );
|
||||
// initialize multicast buffer
|
||||
MSG_Init( &sv.multicast, sv.multicast_buf, sizeof( sv.multicast_buf ));
|
||||
com.strcpy( sv.name, server );
|
||||
|
||||
// leave slots at start for clients only
|
||||
for( i = 0; i < sv_maxclients->integer; i++ )
|
||||
|
@ -182,12 +291,23 @@ void SV_SpawnServer( const char *server, const char *savename )
|
|||
svs.clients[i].lastframe = -1;
|
||||
}
|
||||
|
||||
// make cvars consistant
|
||||
if( Cvar_VariableInteger( "coop" )) Cvar_SetValue( "deathmatch", 0 );
|
||||
current_skill = Q_rint( Cvar_VariableValue( "skill" ));
|
||||
if( current_skill < 0 ) current_skill = 0;
|
||||
if( current_skill > 3 ) current_skill = 3;
|
||||
|
||||
Cvar_SetValue( "skill", (float)current_skill );
|
||||
|
||||
sv.time = 1000;
|
||||
|
||||
com.strncpy( sv.name, server, MAX_STRING );
|
||||
FS_FileBase(server, sv.configstrings[CS_NAME]);
|
||||
FS_FileBase( server, sv.name ); // make sure what server name doesn't contain path and extension
|
||||
com.strncpy( svs.mapname, sv.name, sizeof( svs.mapname ));
|
||||
com.strncpy( sv.configstrings[CS_NAME], sv.name, CS_SIZE);
|
||||
if( startspot ) com.strncpy( sv.startspot, startspot, sizeof( sv.startspot ));
|
||||
else sv.startspot[0] = '\0';
|
||||
|
||||
com.sprintf( sv.configstrings[CS_MODELS+1], "maps/%s", server );
|
||||
com.sprintf( sv.configstrings[CS_MODELS+1], "maps/%s.bsp", sv.name );
|
||||
sv.worldmodel = sv.models[1] = pe->BeginRegistration( sv.configstrings[CS_MODELS+1], false, &checksum );
|
||||
com.sprintf( sv.configstrings[CS_MAPCHECKSUM], "%i", checksum );
|
||||
com.strncpy( sv.configstrings[CS_SKYNAME], "<skybox>", 64 );
|
||||
|
@ -201,40 +321,9 @@ void SV_SpawnServer( const char *server, const char *savename )
|
|||
sv.models[i+1] = pe->RegisterModel(sv.configstrings[CS_MODELS+1+i] );
|
||||
}
|
||||
|
||||
//
|
||||
// spawn the rest of the entities on the map
|
||||
//
|
||||
|
||||
// precache and static commands can be issued during
|
||||
// map initialization
|
||||
// precache and static commands can be issued during map initialization
|
||||
sv.state = ss_loading;
|
||||
Host_SetServerState( sv.state );
|
||||
|
||||
// check for a savegame
|
||||
SV_CheckForSavegame( savename );
|
||||
|
||||
if( sv.loadgame ) SV_ReadLevelFile( savename );
|
||||
else SV_SpawnEntities( sv.name, pe->GetEntityScript());
|
||||
|
||||
svgame.dllFuncs.pfnServerActivate( EDICT_NUM( 0 ), svgame.globals->numEntities, svgame.globals->maxClients );
|
||||
|
||||
// run two frames to allow everything to settle
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
sv.frametime = 100;
|
||||
SV_Physics();
|
||||
}
|
||||
|
||||
// all precaches are complete
|
||||
sv.state = ss_active;
|
||||
Host_SetServerState( sv.state );
|
||||
|
||||
// create a baseline for more efficient communications
|
||||
SV_CreateBaseline();
|
||||
|
||||
// set serverinfo variable
|
||||
Cvar_FullSet( "mapname", sv.name, CVAR_SERVERINFO|CVAR_INIT );
|
||||
pe->EndRegistration(); // free unused models
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -32,7 +32,6 @@ cvar_t *sv_friction;
|
|||
cvar_t *sv_physics;
|
||||
cvar_t *hostname;
|
||||
cvar_t *sv_maxclients;
|
||||
cvar_t *sv_showclamp;
|
||||
cvar_t *public_server; // should heartbeats be sent
|
||||
|
||||
cvar_t *sv_reconnect_limit;// minimum seconds between connect messages
|
||||
|
@ -281,8 +280,7 @@ void SV_RunGameFrame( void )
|
|||
// never get more than one tic behind
|
||||
if( sv.time < svs.realtime )
|
||||
{
|
||||
if( sv_showclamp->integer )
|
||||
MsgDev( D_INFO, "sv highclamp\n" );
|
||||
MsgDev( D_NOTE, "sv.highclamp\n" );
|
||||
svs.realtime = sv.time;
|
||||
}
|
||||
}
|
||||
|
@ -315,8 +313,7 @@ void SV_Frame( int time )
|
|||
// never let the time get too far off
|
||||
if( sv.time - svs.realtime > sv.frametime )
|
||||
{
|
||||
if( sv_showclamp->integer )
|
||||
MsgDev( D_INFO, "sv lowclamp\n" );
|
||||
MsgDev( D_NOTE, "sv.lowclamp\n" );
|
||||
svs.realtime = sv.time - sv.frametime;
|
||||
}
|
||||
NET_Sleep( sv.time - svs.realtime );
|
||||
|
@ -460,7 +457,6 @@ void SV_Init( void )
|
|||
sv_accelerate = Cvar_Get( "sv_accelerate", DEFAULT_ACCEL, 0, "rate at which a player accelerates to sv_maxspeed" );
|
||||
sv_friction = Cvar_Get( "sv_friction", DEFAULT_FRICTION, 0, "how fast you slow down" );
|
||||
sv_physics = Cvar_Get( "cm_physic", "1", CVAR_ARCHIVE|CVAR_LATCH, "change physic model: 0 - Classic Quake Physic, 1 - Physics Engine" );
|
||||
sv_showclamp = Cvar_Get( "sv_showclamp", "1", 0, "show server time clamping" );
|
||||
sv_maxclients = Cvar_Get( "sv_maxclients", "1", CVAR_SERVERINFO|CVAR_LATCH, "server clients limit" );
|
||||
|
||||
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
|
||||
|
@ -514,8 +510,6 @@ void SV_FinalMessage( char *message, bool reconnect )
|
|||
Netchan_Transmit( &cl->netchan, msg.cursize, msg.data );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SV_Shutdown
|
||||
|
@ -534,9 +528,9 @@ void SV_Shutdown( bool reconnect )
|
|||
if( svs.clients ) SV_FinalMessage( host.finalmsg, reconnect );
|
||||
|
||||
Master_Shutdown();
|
||||
if( reconnect )
|
||||
SV_FreeEdicts();
|
||||
else SV_UnloadProgs();
|
||||
|
||||
if( !reconnect ) SV_UnloadProgs ();
|
||||
else SV_DeactivateServer ();
|
||||
|
||||
// free current level
|
||||
Mem_Set( &sv, 0, sizeof( sv ));
|
||||
|
|
|
@ -1222,6 +1222,8 @@ void SV_Physics_Follow( edict_t *ent )
|
|||
if(!SV_RunThink( ent )) return;
|
||||
|
||||
e = ent->v.aiment;
|
||||
if( !e || e->free ) return;
|
||||
|
||||
if(VectorCompare( e->v.angles, ent->v.punchangle ))
|
||||
{
|
||||
// quick case for no rotation
|
||||
|
|
|
@ -21,6 +21,11 @@ typedef struct save_header_s
|
|||
typedef struct game_header_s
|
||||
{
|
||||
int mapCount; // svs.mapcount
|
||||
int serverflags; // svgame.serverflags
|
||||
int total_secrets; // total secrets count
|
||||
int found_secrets; // number of secrets found
|
||||
int total_monsters; // total monsters count
|
||||
int killed_monsters; // number of monsters killed
|
||||
char mapName[CS_SIZE]; // svs.mapname
|
||||
string comment; // svs.comment
|
||||
} game_header_t;
|
||||
|
@ -36,6 +41,11 @@ static TYPEDESCRIPTION gSaveHeader[] =
|
|||
static TYPEDESCRIPTION gGameHeader[] =
|
||||
{
|
||||
DEFINE_FIELD( game_header_t, mapCount, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( game_header_t, serverflags, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( game_header_t, total_secrets, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( game_header_t, found_secrets, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( game_header_t, total_monsters, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( game_header_t, killed_monsters, FIELD_INTEGER ),
|
||||
DEFINE_ARRAY( game_header_t, mapName, FIELD_CHARACTER, CS_SIZE ),
|
||||
DEFINE_ARRAY( game_header_t, comment, FIELD_CHARACTER, MAX_STRING ),
|
||||
};
|
||||
|
@ -157,11 +167,12 @@ static void SV_SaveEngineData( wfile_t *f )
|
|||
SV_AddSaveLump( f, LUMP_GAMECVARS, cvbuffer, numpairs * sizeof( dkeyvalue_t ), true );
|
||||
}
|
||||
|
||||
static void SV_SaveServerData( wfile_t *f )
|
||||
static void SV_SaveServerData( wfile_t *f, const char *name, bool bUseLandMark )
|
||||
{
|
||||
SAVERESTOREDATA *pSaveData;
|
||||
string_t hash_strings[4095];
|
||||
int i, numstrings;
|
||||
int level_flags = 0;
|
||||
ENTITYTABLE *pTable;
|
||||
save_header_t shdr;
|
||||
game_header_t ghdr;
|
||||
|
@ -176,6 +187,22 @@ static void SV_SaveServerData( wfile_t *f )
|
|||
svgame.SaveData.time = svgame.globals->time;
|
||||
pSaveData = svgame.globals->pSaveData = &svgame.SaveData;
|
||||
|
||||
// initialize the ENTITYTABLE
|
||||
pSaveData->tableCount = svgame.globals->numEntities;
|
||||
pSaveData->pTable = Mem_Alloc( svgame.temppool, pSaveData->tableCount * sizeof( ENTITYTABLE ));
|
||||
|
||||
for( i = 0; i < svgame.globals->numEntities; i++ )
|
||||
{
|
||||
pTable = &pSaveData->pTable[i];
|
||||
|
||||
pTable->pent = EDICT_NUM( i );
|
||||
// setup some flags
|
||||
if( pTable->pent->v.flags & FL_CLIENT ) pTable->flags |= FENTTABLE_PLAYER;
|
||||
if( pTable->pent->free ) pTable->flags |= FENTTABLE_REMOVED;
|
||||
}
|
||||
|
||||
pSaveData->fUseLandmark = bUseLandMark;
|
||||
|
||||
// initialize level connections
|
||||
svgame.dllFuncs.pfnBuildLevelList();
|
||||
|
||||
|
@ -187,25 +214,13 @@ static void SV_SaveServerData( wfile_t *f )
|
|||
|
||||
// initialize game header
|
||||
ghdr.mapCount = svs.spawncount;
|
||||
com.strncpy( ghdr.mapName, svs.mapname, CS_SIZE );
|
||||
Mem_Copy( ghdr.comment, svs.comment, MAX_STRING );
|
||||
|
||||
// initialize ENTITYTABLE
|
||||
pSaveData->tableCount = svgame.globals->numEntities;
|
||||
pSaveData->pTable = Mem_Alloc( svgame.temppool, pSaveData->tableCount * sizeof( ENTITYTABLE ));
|
||||
|
||||
for( i = 0; i < svgame.globals->numEntities; i++ )
|
||||
{
|
||||
edict_t *pent = EDICT_NUM( i );
|
||||
|
||||
pTable = &pSaveData->pTable[i];
|
||||
|
||||
pTable->pent = pent;
|
||||
|
||||
// setup some flags
|
||||
if( pent->v.flags & FL_CLIENT ) pTable->flags |= FENTTABLE_PLAYER;
|
||||
if( pent->free ) pTable->flags |= FENTTABLE_REMOVED;
|
||||
}
|
||||
ghdr.serverflags = svgame.globals->serverflags;
|
||||
ghdr.total_secrets = svgame.globals->total_secrets;
|
||||
ghdr.found_secrets = svgame.globals->found_secrets;
|
||||
ghdr.total_monsters = svgame.globals->total_monsters;
|
||||
ghdr.killed_monsters = svgame.globals->killed_monsters;
|
||||
com.strncpy( ghdr.mapName, sv.name, CS_SIZE );
|
||||
Mem_Copy( ghdr.comment, svs.comment, MAX_STRING ); // can't use strncpy!
|
||||
|
||||
// write save header
|
||||
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "Save Header", &shdr, gSaveHeader, ARRAYSIZE( gSaveHeader ));
|
||||
|
@ -215,6 +230,12 @@ static void SV_SaveServerData( wfile_t *f )
|
|||
{
|
||||
LEVELLIST *pList = &pSaveData->levelList[i];
|
||||
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "ADJACENCY", pList, gAdjacency, ARRAYSIZE( gAdjacency ));
|
||||
|
||||
if( sv.changelevel && !com.strcmp( pList->mapName, name ))
|
||||
{
|
||||
level_flags = (1<<i);
|
||||
Msg( "%s set level flags to: %x\n", name, level_flags );
|
||||
}
|
||||
}
|
||||
|
||||
SV_SaveBuffer( f, LUMP_ADJACENCY, false );
|
||||
|
@ -225,7 +246,18 @@ static void SV_SaveServerData( wfile_t *f )
|
|||
edict_t *pent = EDICT_NUM( i );
|
||||
ENTITYTABLE *pTable = &pSaveData->pTable[pSaveData->currentIndex];
|
||||
|
||||
if( !pent->free && pent->v.classname )
|
||||
if( sv.changelevel )
|
||||
{
|
||||
bool bSave = false;
|
||||
|
||||
// check for client ents
|
||||
if( pTable->flags & (FENTTABLE_PLAYER|FENTTABLE_GLOBAL))
|
||||
bSave = true;
|
||||
|
||||
if( pTable->flags & FENTTABLE_MOVEABLE && pTable->flags & level_flags )
|
||||
bSave = true;
|
||||
|
||||
if( bSave )
|
||||
{
|
||||
svgame.dllFuncs.pfnSave( pent, pSaveData );
|
||||
if( pTable->classname && pTable->size )
|
||||
|
@ -234,6 +266,19 @@ static void SV_SaveServerData( wfile_t *f )
|
|||
}
|
||||
else pTable->flags |= FENTTABLE_REMOVED;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// savegame
|
||||
if( !pent->free && pent->v.classname )
|
||||
{
|
||||
svgame.dllFuncs.pfnSave( pent, pSaveData );
|
||||
if( pTable->classname && pTable->size )
|
||||
pTable->id = pent->serialnumber;
|
||||
else pTable->flags |= FENTTABLE_REMOVED;
|
||||
}
|
||||
else pTable->flags |= FENTTABLE_REMOVED;
|
||||
}
|
||||
pSaveData->currentIndex++; // move pointer
|
||||
}
|
||||
|
||||
|
@ -281,7 +326,7 @@ static void SV_SaveServerData( wfile_t *f )
|
|||
SV_WriteSaveFile
|
||||
=============
|
||||
*/
|
||||
void SV_WriteSaveFile( const char *name, bool autosave )
|
||||
void SV_WriteSaveFile( const char *name, bool autosave, bool bUseLandmark )
|
||||
{
|
||||
wfile_t *savfile = NULL;
|
||||
char path[MAX_SYSPATH];
|
||||
|
@ -312,17 +357,18 @@ void SV_WriteSaveFile( const char *name, bool autosave )
|
|||
com.strncpy( svs.comment + CS_SIZE, timestamp( TIME_DATE_ONLY ), CS_TIME );
|
||||
com.strncpy( svs.comment + CS_SIZE + CS_TIME, timestamp( TIME_NO_SECONDS ), CS_TIME );
|
||||
com.strncpy( svs.comment + CS_SIZE + (CS_TIME * 2), svs.mapname, CS_SIZE );
|
||||
MsgDev( D_INFO, "Saving game..." );
|
||||
if( !autosave ) MsgDev( D_INFO, "Saving game..." );
|
||||
|
||||
// write lumps
|
||||
SV_SaveEngineData( savfile );
|
||||
SV_SaveServerData( savfile );
|
||||
SV_SaveServerData( savfile, name, bUseLandmark );
|
||||
StringTable_Save( svgame.hStringTable, savfile ); // must be last
|
||||
|
||||
WAD_Close( savfile );
|
||||
Cbuf_AddText( va( "saveshot %s\n", name )); // write saveshot for preview
|
||||
|
||||
MsgDev( D_INFO, "done.\n" );
|
||||
// write saveshot for preview, but autosave
|
||||
if( !autosave ) Cbuf_AddText( va( "saveshot %s\n", name ));
|
||||
if( !autosave ) MsgDev( D_INFO, "done.\n" );
|
||||
}
|
||||
|
||||
void SV_ReadComment( wfile_t *l )
|
||||
|
@ -396,7 +442,7 @@ void SV_ReadAreaPortals( wfile_t *l )
|
|||
int size;
|
||||
|
||||
in = WAD_Read( l, LUMP_AREASTATE, &size, TYPE_BINDATA );
|
||||
pe->SetAreaPortals( in, size ); // CM_ReadPortalState
|
||||
pe->SetAreaPortals( in, size ); // CM_ReadPortalState();
|
||||
}
|
||||
|
||||
void SV_ReadGlobals( wfile_t *l )
|
||||
|
@ -415,14 +461,25 @@ void SV_ReadGlobals( wfile_t *l )
|
|||
|
||||
// read the game header
|
||||
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "Game Header", &ghdr, gGameHeader, ARRAYSIZE( gGameHeader ));
|
||||
svgame.globals->serverflags= ghdr.serverflags; // across transition flags (e.g. Q1 runes)
|
||||
|
||||
if( sv.loadgame && !sv.changelevel )
|
||||
{
|
||||
Msg( "SV_ReadGlobals()\n" );
|
||||
svs.spawncount = ghdr.mapCount; // restore spawncount
|
||||
svgame.globals->total_secrets = ghdr.total_secrets;
|
||||
svgame.globals->found_secrets = ghdr.found_secrets;
|
||||
svgame.globals->total_monsters = ghdr.total_monsters;
|
||||
svgame.globals->killed_monsters = ghdr.killed_monsters;
|
||||
Mem_Copy( svs.comment, ghdr.comment, MAX_STRING );
|
||||
com.strncpy( svs.mapname, ghdr.mapName, MAX_STRING );
|
||||
}
|
||||
|
||||
// restore global state
|
||||
svgame.dllFuncs.pfnRestoreGlobalState( pSaveData );
|
||||
svgame.dllFuncs.pfnServerDeactivate();
|
||||
|
||||
// FIXME: this is needs ?
|
||||
// svgame.dllFuncs.pfnServerDeactivate();
|
||||
}
|
||||
|
||||
void SV_RestoreEdict( edict_t *ent )
|
||||
|
@ -438,42 +495,79 @@ void SV_ReadEntities( wfile_t *l )
|
|||
LEVELLIST *pList;
|
||||
save_header_t shdr;
|
||||
edict_t *ent;
|
||||
int i;
|
||||
int i, level_flags = 0;
|
||||
int num_moveables = 0;
|
||||
|
||||
// initialize world properly
|
||||
ent = EDICT_NUM( 0 );
|
||||
SV_InitEdict( ent );
|
||||
ent->v.model = MAKE_STRING( sv.configstrings[CS_MODELS] );
|
||||
if( ent->free ) SV_InitEdict( ent );
|
||||
ent->v.model = MAKE_STRING( sv.configstrings[CS_MODELS+1] );
|
||||
ent->v.modelindex = 1; // world model
|
||||
ent->v.solid = SOLID_BSP;
|
||||
ent->v.movetype = MOVETYPE_PUSH;
|
||||
ent->free = false;
|
||||
|
||||
// SAVERESTOREDATA partially initialized, continue filling
|
||||
pSaveData = svgame.globals->pSaveData = &svgame.SaveData;
|
||||
SV_ReadBuffer( l, LUMP_ADJACENCY );
|
||||
|
||||
if( sv.loadgame )
|
||||
{
|
||||
pSaveData->fUseLandmark = true;
|
||||
}
|
||||
else if( sv.changelevel )
|
||||
{
|
||||
if( com.strlen( sv.startspot ))
|
||||
pSaveData->fUseLandmark = true;
|
||||
else pSaveData->fUseLandmark = false; // can be changed later
|
||||
}
|
||||
|
||||
// read save header
|
||||
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "Save Header", &shdr, gSaveHeader, ARRAYSIZE( gSaveHeader ));
|
||||
pSaveData->connectionCount = shdr.numConnections;
|
||||
|
||||
if( sv.loadgame )
|
||||
{
|
||||
SV_ConfigString( CS_MAXCLIENTS, va( "%i", sv_maxclients->integer ));
|
||||
com.strncpy( sv.name, shdr.mapName, MAX_STRING );
|
||||
svgame.globals->mapname = MAKE_STRING( sv.name );
|
||||
|
||||
// holds during changelevel, no needs to save\restore
|
||||
svgame.globals->startspot = MAKE_STRING( sv.startspot );
|
||||
svgame.globals->time = shdr.time;
|
||||
sv.time = svgame.globals->time * 1000;
|
||||
pSaveData->connectionCount = shdr.numConnections;
|
||||
}
|
||||
|
||||
// read ADJACENCY sections
|
||||
for( i = 0; i < pSaveData->connectionCount; i++ )
|
||||
{
|
||||
pList = &pSaveData->levelList[i];
|
||||
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "ADJACENCY", pList, gAdjacency, ARRAYSIZE( gAdjacency ));
|
||||
|
||||
if( sv.changelevel && !com.strcmp( pList->mapName, sv.name ))
|
||||
{
|
||||
level_flags = (1<<i);
|
||||
Msg( "%s get level flags: %x\n", sv.name, level_flags );
|
||||
com.strcpy( pSaveData->szCurrentMap, pList->mapName );
|
||||
com.strcpy( pSaveData->szLandmarkName, pList->landmarkName );
|
||||
VectorCopy( pSaveData->vecLandmarkOffset, pList->vecLandmarkOrigin );
|
||||
pSaveData->time = shdr.time;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize ENTITYTABLE
|
||||
pSaveData->tableCount = shdr.numEntities;
|
||||
pSaveData->pTable = Mem_Alloc( svgame.temppool, pSaveData->tableCount * sizeof( ENTITYTABLE ));
|
||||
while( svgame.globals->numEntities < shdr.numEntities ) SV_AllocEdict(); // allocate edicts
|
||||
|
||||
if( sv.loadgame ) // allocate edicts
|
||||
while( svgame.globals->numEntities < shdr.numEntities ) SV_AllocEdict();
|
||||
else if( sv.changelevel )
|
||||
{
|
||||
// NOTE: we don't need allocate too many ents
|
||||
// just set it number to match with old map and use
|
||||
// SV_InitEdict istead of SV_AllocEdict, first SV_Physics call
|
||||
// will be fixup entities count to actual
|
||||
svgame.globals->numEntities = pSaveData->tableCount;
|
||||
}
|
||||
|
||||
// set client fields on player ents
|
||||
for( i = 0; i < svgame.globals->maxClients; i++ )
|
||||
|
@ -496,17 +590,48 @@ void SV_ReadEntities( wfile_t *l )
|
|||
pTable = &pSaveData->pTable[i];
|
||||
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "ETABLE", pTable, gETable, ARRAYSIZE( gETable ));
|
||||
|
||||
if( sv.loadgame )
|
||||
{
|
||||
if( pTable->flags & FENTTABLE_REMOVED ) SV_FreeEdict( pent );
|
||||
else pent = SV_AllocPrivateData( pent, pTable->classname );
|
||||
}
|
||||
else if( sv.changelevel )
|
||||
{
|
||||
bool bAlloc = false;
|
||||
|
||||
if( pTable->id != pent->serialnumber )
|
||||
// check for client or global entity
|
||||
if( pTable->flags & (FENTTABLE_PLAYER|FENTTABLE_GLOBAL))
|
||||
bAlloc = true;
|
||||
|
||||
if( pTable->flags & FENTTABLE_MOVEABLE && pTable->flags & level_flags )
|
||||
bAlloc = true;
|
||||
|
||||
if( !pTable->id || !pTable->classname )
|
||||
bAlloc = false;
|
||||
|
||||
if( bAlloc )
|
||||
{
|
||||
if( pent->free ) SV_InitEdict( pent );
|
||||
pent = SV_AllocPrivateData( pent, pTable->classname );
|
||||
num_moveables++;
|
||||
}
|
||||
}
|
||||
|
||||
if( sv.loadgame && ( pTable->id != pent->serialnumber ))
|
||||
MsgDev( D_ERROR, "ETABLE id( %i ) != edict->id( %i )\n", pTable->id, pent->serialnumber );
|
||||
|
||||
pTable->pent = pent;
|
||||
}
|
||||
|
||||
Msg( "total %i moveables, %i entities\n", num_moveables, svgame.globals->numEntities );
|
||||
|
||||
if( sv.changelevel )
|
||||
{
|
||||
// spawn all the entities of the newmap
|
||||
SV_SpawnEntities( sv.name, pe->GetEntityScript());
|
||||
}
|
||||
|
||||
SV_ReadBuffer( l, LUMP_BASEENTS );
|
||||
pSaveData->fUseLandmark = true;
|
||||
|
||||
// and read entities ...
|
||||
for( i = 0; i < pSaveData->tableCount; i++ )
|
||||
|
@ -514,12 +639,31 @@ void SV_ReadEntities( wfile_t *l )
|
|||
edict_t *pent = EDICT_NUM( i );
|
||||
pTable = &pSaveData->pTable[i];
|
||||
|
||||
if( sv.loadgame )
|
||||
{
|
||||
// ignore removed edicts
|
||||
if( !pent->free && pTable->classname )
|
||||
{
|
||||
svgame.dllFuncs.pfnRestore( pent, pSaveData, false );
|
||||
SV_RestoreEdict( pent );
|
||||
}
|
||||
}
|
||||
else if( sv.changelevel )
|
||||
{
|
||||
bool bRestore = false;
|
||||
bool bGlobal = (pTable->flags & FENTTABLE_GLOBAL) ? true : false;
|
||||
|
||||
if( pTable->flags & (FENTTABLE_PLAYER|FENTTABLE_GLOBAL)) bRestore = true;
|
||||
if( pTable->flags & FENTTABLE_MOVEABLE && pTable->flags & level_flags )
|
||||
bRestore = true;
|
||||
if( !pTable->id || !pTable->classname ) bRestore = false;
|
||||
|
||||
if( bRestore )
|
||||
{
|
||||
MsgDev( D_INFO, "Transfering %s ( *%i )\n", STRING( pTable->classname ), i );
|
||||
svgame.dllFuncs.pfnRestore( pent, pSaveData, bGlobal );
|
||||
}
|
||||
}
|
||||
pSaveData->currentIndex++;
|
||||
}
|
||||
|
||||
|
@ -538,7 +682,7 @@ void SV_ReadSaveFile( const char *name )
|
|||
char path[MAX_SYSPATH];
|
||||
wfile_t *savfile;
|
||||
|
||||
com.sprintf( path, "save/%s", name );
|
||||
com.sprintf( path, "save/%s.bin", name );
|
||||
savfile = WAD_Open( path, "rb" );
|
||||
|
||||
if( !savfile )
|
||||
|
@ -547,15 +691,17 @@ void SV_ReadSaveFile( const char *name )
|
|||
return;
|
||||
}
|
||||
|
||||
sv.loadgame = true; // to avoid clearing StringTables in SV_Shutdown
|
||||
StringTable_Delete( svgame.hStringTable ); // remove old string table
|
||||
svgame.hStringTable = StringTable_Load( savfile, name );
|
||||
SV_ReadCvars( savfile );
|
||||
|
||||
if( sv.loadgame && !sv.changelevel )
|
||||
{
|
||||
SV_ReadCvars( savfile );
|
||||
SV_InitGame(); // start a new game fresh with new cvars
|
||||
|
||||
// SV_Shutdown will be clear svs ans sv struct, so load it here
|
||||
sv.loadgame = true; // restore state
|
||||
}
|
||||
|
||||
SV_ReadGlobals( savfile );
|
||||
WAD_Close( savfile );
|
||||
}
|
||||
|
@ -570,7 +716,7 @@ void SV_ReadLevelFile( const char *name )
|
|||
char path[MAX_SYSPATH];
|
||||
wfile_t *savfile;
|
||||
|
||||
com.sprintf( path, "save/%s", name );
|
||||
com.sprintf( path, "save/%s.bin", name );
|
||||
savfile = WAD_Open( path, "rb" );
|
||||
|
||||
if( !savfile )
|
||||
|
@ -585,6 +731,71 @@ void SV_ReadLevelFile( const char *name )
|
|||
WAD_Close( savfile );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_MergeLevelFile
|
||||
=============
|
||||
*/
|
||||
void SV_MergeLevelFile( const char *name )
|
||||
{
|
||||
char path[MAX_SYSPATH];
|
||||
wfile_t *savfile;
|
||||
|
||||
com.sprintf( path, "save/%s.bin", name );
|
||||
savfile = WAD_Open( path, "rb" );
|
||||
|
||||
if( !savfile )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_MergeLevel: can't open %s\n", path );
|
||||
return;
|
||||
}
|
||||
|
||||
SV_ReadEntities( savfile );
|
||||
WAD_Close( savfile );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_ChangeLevel
|
||||
=============
|
||||
*/
|
||||
void SV_ChangeLevel( bool bUseLandmark, const char *mapname, const char *start )
|
||||
{
|
||||
string level;
|
||||
string oldlevel;
|
||||
string _startspot;
|
||||
char *startspot;
|
||||
|
||||
if( sv.state != ss_active )
|
||||
{
|
||||
Msg( "SV_ChangeLevel: server not running\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sv.loadgame = false;
|
||||
sv.changelevel = true;
|
||||
|
||||
if( bUseLandmark )
|
||||
{
|
||||
com.strncpy( _startspot, start, MAX_STRING );
|
||||
startspot = _startspot;
|
||||
}
|
||||
else startspot = NULL;
|
||||
|
||||
com.strncpy( level, mapname, MAX_STRING );
|
||||
com.strncpy( oldlevel, sv.name, MAX_STRING );
|
||||
|
||||
// NOTE: we must save state even landmark is missed
|
||||
// so transfer client weapons and env_global states
|
||||
SV_WriteSaveFile( level, true, bUseLandmark );
|
||||
|
||||
SV_SpawnServer( mapname, startspot );
|
||||
|
||||
SV_LevelInit( level, oldlevel, level );
|
||||
|
||||
SV_ActivateServer ();
|
||||
}
|
||||
|
||||
bool SV_GetComment( char *comment, int savenum )
|
||||
{
|
||||
wfile_t *savfile;
|
||||
|
@ -611,3 +822,38 @@ bool SV_GetComment( char *comment, int savenum )
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *SV_GetLatestSave( void )
|
||||
{
|
||||
search_t *f = FS_Search( "save/*.bin", true );
|
||||
int i, found = 0;
|
||||
long newest = 0, ft;
|
||||
string savename;
|
||||
|
||||
if( !f ) return NULL;
|
||||
|
||||
for( i = 0; i < f->numfilenames; i++ )
|
||||
{
|
||||
if( WAD_Check( f->filenames[i] ) != 1 )
|
||||
continue; // corrupted or somewhat
|
||||
|
||||
ft = FS_FileTime( va( "%s/%s", GI->gamedir, f->filenames[i] ));
|
||||
|
||||
// found a match?
|
||||
if( ft > 0 )
|
||||
{
|
||||
// should we use the matche?
|
||||
if( !found || Host_CompareFileTime( newest, ft ) < 0 )
|
||||
{
|
||||
newest = ft;
|
||||
com.strncpy( savename, f->filenames[i], MAX_STRING );
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Mem_Free( f ); // release search
|
||||
|
||||
if( found )
|
||||
return va( "%s", savename ); // move to static memory
|
||||
return NULL;
|
||||
}
|
|
@ -1359,6 +1359,7 @@ void FS_CreateGameInfo( const char *filename )
|
|||
com.strncat( buffer, "\nsp_spawn\t\t\"info_player_start\"", MAX_SYSPATH );
|
||||
com.strncat( buffer, "\ndm_spawn\t\t\"info_player_deathmatch\"", MAX_SYSPATH );
|
||||
com.strncat( buffer, "\nctf_spawn\t\t\"info_player_ctf\"", MAX_SYSPATH );
|
||||
com.strncat( buffer, "\ncoop_spawn\t\t\"info_player_coop\"", MAX_SYSPATH );
|
||||
com.strncat( buffer, "\nteam_spawn\t\"info_player_team\"", MAX_SYSPATH );
|
||||
com.strncat( buffer, "\nplayermins\t\"-32 -32 -32\"", MAX_SYSPATH );
|
||||
com.strncat( buffer, "\nplayermaxs\t\"32 32 32\"", MAX_SYSPATH );
|
||||
|
@ -1400,6 +1401,7 @@ static bool FS_ParseGameInfo( const char *filename, gameinfo_t *GameInfo )
|
|||
com.strncpy( GameInfo->sp_entity, "info_player_start", MAX_STRING );
|
||||
com.strncpy( GameInfo->dm_entity, "info_player_deathmatch", MAX_STRING );
|
||||
com.strncpy( GameInfo->ctf_entity, "info_player_ctf", MAX_STRING );
|
||||
com.strncpy( GameInfo->coop_entity, "info_player_coop", MAX_STRING );
|
||||
com.strncpy( GameInfo->team_entity, "info_player_team", MAX_STRING );
|
||||
com.strncpy( GameInfo->startmap, "newmap", MAX_STRING );
|
||||
|
||||
|
@ -1441,6 +1443,10 @@ static bool FS_ParseGameInfo( const char *filename, gameinfo_t *GameInfo )
|
|||
{
|
||||
PS_GetString( script, false, GameInfo->ctf_entity, sizeof( GameInfo->ctf_entity ));
|
||||
}
|
||||
else if( !com.stricmp( token.string, "coop_spawn" ))
|
||||
{
|
||||
PS_GetString( script, false, GameInfo->coop_entity, sizeof( GameInfo->coop_entity ));
|
||||
}
|
||||
else if( !com.stricmp( token.string, "team_spawn" ))
|
||||
{
|
||||
PS_GetString( script, false, GameInfo->team_entity, sizeof( GameInfo->team_entity ));
|
||||
|
@ -1456,7 +1462,7 @@ static bool FS_ParseGameInfo( const char *filename, gameinfo_t *GameInfo )
|
|||
else if( !com.stricmp( token.string, "max_edicts" ))
|
||||
{
|
||||
PS_GetInteger( script, false, &GameInfo->max_edicts );
|
||||
GameInfo->max_edicts = bound( 600, GameInfo->max_edicts, 32768 );
|
||||
GameInfo->max_edicts = bound( 600, GameInfo->max_edicts, 32000 ); // reserve some edicts for tempents
|
||||
}
|
||||
else if( !com.stricmp( token.string, "viewmode" ))
|
||||
{
|
||||
|
|
|
@ -181,7 +181,7 @@ bool REG_SetValue( HKEY hKey, const char *SubKey, const char *Value, char *pBuff
|
|||
//
|
||||
void NET_Init( void );
|
||||
void NET_Shutdown( void );
|
||||
void NET_Sleep( float time );
|
||||
void NET_Sleep( int msec );
|
||||
void NET_Config( bool net_enable );
|
||||
bool NET_IsLocalAddress( netadr_t adr );
|
||||
char *NET_AdrToString( const netadr_t a );
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<html>
|
||||
<body>
|
||||
<pre>
|
||||
<h1>Build Log</h1>
|
||||
<h3>
|
||||
--------------------Configuration: launch - Win32 Debug--------------------
|
||||
</h3>
|
||||
<h3>Command Lines</h3>
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP13EA.tmp" with contents
|
||||
[
|
||||
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "imagelib" /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\launch\!debug/" /Fo"..\temp\launch\!debug/" /Fd"..\temp\launch\!debug/" /FD /GZ /c
|
||||
"D:\Xash3D\src_main\launch\system.c"
|
||||
]
|
||||
Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP13EA.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP13EB.tmp" with contents
|
||||
[
|
||||
zlib.lib png.lib jpg.lib user32.lib gdi32.lib shell32.lib advapi32.lib winmm.lib /nologo /dll /incremental:yes /pdb:"..\temp\launch\!debug/launch.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /out:"..\temp\launch\!debug/launch.dll" /implib:"..\temp\launch\!debug/launch.lib" /pdbtype:sept /libpath:"./imagelib"
|
||||
"\Xash3D\src_main\temp\launch\!debug\cmd.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\console.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\cpuinfo.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\crclib.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\cvar.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\export.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\filesystem.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_bmp.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_dds.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_jpg.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_main.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_pcx.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_png.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_tga.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_utils.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_vtf.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\img_wad.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\memlib.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\network.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\parselib.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\patch.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\stdlib.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\system.obj"
|
||||
"\Xash3D\src_main\temp\launch\!debug\utils.obj"
|
||||
]
|
||||
Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP13EB.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP13EC.bat" with contents
|
||||
[
|
||||
@echo off
|
||||
copy \Xash3D\src_main\temp\launch\!debug\launch.dll "D:\Xash3D\bin\launch.dll"
|
||||
]
|
||||
Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP13EC.bat"
|
||||
Compiling...
|
||||
system.c
|
||||
Linking...
|
||||
<h3>Output Window</h3>
|
||||
Performing Custom Build Step on \Xash3D\src_main\temp\launch\!debug\launch.dll
|
||||
‘Ş®Ż¨ŕ®˘ ® ä ©«®˘: 1.
|
||||
|
||||
|
||||
|
||||
<h3>Results</h3>
|
||||
launch.dll - 0 error(s), 0 warning(s)
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -602,17 +602,14 @@ void NET_Config( bool multiplayer )
|
|||
}
|
||||
|
||||
// sleeps msec or until net socket is ready
|
||||
void NET_Sleep( float time )
|
||||
void NET_Sleep( int msec )
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set fdset;
|
||||
int i = 0;
|
||||
long sec = (int)time;
|
||||
long usec = (time - sec) * 1000;
|
||||
|
||||
if( Sys.app_name == HOST_NORMAL )
|
||||
return; // we're not a dedicated server, just run full speed
|
||||
if( !sec && !usec ) return; // smaller than timer resoultion
|
||||
return; // we're not a server, just run full speed
|
||||
|
||||
FD_ZERO( &fdset );
|
||||
|
||||
|
@ -622,8 +619,8 @@ void NET_Sleep( float time )
|
|||
i = ip_sockets[NS_SERVER];
|
||||
}
|
||||
|
||||
timeout.tv_sec = sec;
|
||||
timeout.tv_usec = usec;
|
||||
timeout.tv_sec = msec / 1000;
|
||||
timeout.tv_usec = (msec % 1000) * 1000;
|
||||
pSelect( i+1, &fdset, NULL, NULL, &timeout );
|
||||
}
|
||||
|
||||
|
|
|
@ -843,6 +843,7 @@ void Sys_Error(const char *error, ...)
|
|||
Con_ShowConsole( true );
|
||||
if( Sys.developer >= D_ERROR ) Sys_Print( text ); // print error message
|
||||
else Sys_Print( "Internal engine error\n" ); // don't confuse non-developers with technique stuff
|
||||
Sys.Free(); // kill video
|
||||
|
||||
Sys_WaitForQuit();
|
||||
Sys_Exit();
|
||||
|
@ -861,6 +862,8 @@ void Sys_Break(const char *error, ...)
|
|||
Sys.app_state = SYS_ERROR;
|
||||
Con_ShowConsole( true );
|
||||
Sys_Print( text );
|
||||
Sys.Free(); // kill video
|
||||
|
||||
Sys_WaitForQuit();
|
||||
Sys_Exit();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<body>
|
||||
<pre>
|
||||
<h1>Build Log</h1>
|
||||
<h3>
|
||||
--------------------Configuration: physic - Win32 Debug--------------------
|
||||
</h3>
|
||||
<h3>Command Lines</h3>
|
||||
|
||||
|
||||
|
||||
<h3>Results</h3>
|
||||
physic.dll - 0 error(s), 0 warning(s)
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -10,16 +10,15 @@
|
|||
//
|
||||
// engine constant limits, touching networking protocol modify with precaution
|
||||
//
|
||||
#define MAX_DLIGHTS 32 // dynamic lights (per one frame)
|
||||
#define MAX_DLIGHTS 32 // dynamic lights (rendered per one frame)
|
||||
#define MAX_LIGHTSTYLES 256 // can't be blindly increased
|
||||
#define MAX_DECALS 256 // server decal indexes
|
||||
#define MAX_DECALS 256 // server decal indexes (different decalnames, not a render limit)
|
||||
#define MAX_USER_MESSAGES 200 // another 56 messages reserved for engine routines
|
||||
#define MAX_CLASSNAMES 512 // maxcount of various edicts classnames
|
||||
#define MAX_SOUNDS 512 // openal software limit
|
||||
#define MAX_MODELS 4096 // total count of brush & studio various models per one map
|
||||
#define MAX_PARTICLES 32768 // pre one frame
|
||||
#define MAX_EDICTS 65535 // absolute limit that never be reached, (do not edit!)
|
||||
#define MAX_VERTS_ON_POLY 10 // decal vertices
|
||||
#define MAX_EDICTS 32768 // absolute limit that never be reached, (do not edit!)
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
|
|
@ -237,14 +237,14 @@ typedef struct gameinfo_s
|
|||
|
||||
string sp_entity; // e.g. info_player_start
|
||||
string dm_entity; // e.g. info_player_deathmatch
|
||||
string coop_entity; // e.g. info_player_coop
|
||||
string ctf_entity; // e.g. info_player_ctf
|
||||
string team_entity; // e.g. info_player_team
|
||||
|
||||
vec3_t client_mins[2]; // 0 - normal, 1 - ducked
|
||||
vec3_t client_maxs[2]; // 0 - normal, 1 - ducked
|
||||
|
||||
int max_edicts; // min edicts is 600, max edicts is 32768
|
||||
string imglib_mode; // image formats to using (optional)
|
||||
int max_edicts; // min edicts is 600, max edicts is 32000
|
||||
} gameinfo_t;
|
||||
|
||||
typedef struct sysinfo_s
|
||||
|
@ -460,7 +460,7 @@ typedef struct stdilib_api_s
|
|||
// network.c funcs
|
||||
void (*NET_Init)( void );
|
||||
void (*NET_Shutdown)( void );
|
||||
void (*NET_Sleep)( float time );
|
||||
void (*NET_Sleep)( int msec );
|
||||
void (*NET_Config)( bool net_enable );
|
||||
char *(*NET_AdrToString)( netadr_t a );
|
||||
bool (*NET_IsLocalAddress)( netadr_t adr );
|
||||
|
|
|
@ -308,14 +308,19 @@ void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t d
|
|||
int *gridBounds;
|
||||
mgridlight_t **lightarray;
|
||||
|
||||
VectorSet( ambientLocal, 0, 0, 0 );
|
||||
VectorSet( diffuseLocal, 0, 0, 0 );
|
||||
|
||||
if( !r_worldmodel || !r_worldbrushmodel->lightgrid || !r_worldbrushmodel->numlightgridelems )
|
||||
{
|
||||
// get fullbright
|
||||
VectorSet( ambientLocal, 255, 255, 255 );
|
||||
VectorSet( diffuseLocal, 255, 255, 255 );
|
||||
VectorSet( dir, 0.5f, 0.2f, -1.0f );
|
||||
goto dynamic;
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSet( ambientLocal, 0, 0, 0 );
|
||||
VectorSet( diffuseLocal, 0, 0, 0 );
|
||||
}
|
||||
|
||||
lightarray = r_worldbrushmodel->lightarray;
|
||||
gridSize = r_worldbrushmodel->gridSize;
|
||||
|
|
|
@ -44,7 +44,7 @@ extern byte *r_temppool;
|
|||
#define Host_Error com.error
|
||||
|
||||
typedef unsigned int elem_t;
|
||||
typedef enum { RT_MODEL, RT_SPRITE, RT_PORTALSURFACE, NUM_RTYPES } refEntityType_t;
|
||||
typedef enum { RT_NONE, RT_MODEL, RT_SPRITE, RT_PORTALSURFACE, NUM_RTYPES } refEntityType_t;
|
||||
|
||||
/*
|
||||
skins will be outline flood filled and mip mapped
|
||||
|
@ -129,7 +129,7 @@ enum
|
|||
#define SHADOW_PLANAR 1
|
||||
#define SHADOW_MAPPING 2
|
||||
|
||||
#define MAX_ENTITIES 2048
|
||||
#define MAX_ENTITIES 2048 // per one frame
|
||||
#define MAX_POLY_VERTS 3000
|
||||
#define MAX_POLYS 2048
|
||||
|
||||
|
|
|
@ -40,10 +40,10 @@ refinst_t RI, prevRI;
|
|||
ref_params_t r_lastRefdef;
|
||||
|
||||
static int r_numnullentities;
|
||||
static ref_entity_t *r_nullentities[MAX_EDICTS];
|
||||
static ref_entity_t *r_nullentities[MAX_ENTITIES];
|
||||
ref_model_t *cl_models[MAX_MODELS]; // client replacement modeltable
|
||||
static int r_numbmodelentities;
|
||||
static ref_entity_t *r_bmodelentities[MAX_EDICTS];
|
||||
static ref_entity_t *r_bmodelentities[MAX_MODELS];
|
||||
|
||||
static byte r_entVisBits[MAX_EDICTS/8];
|
||||
|
||||
|
@ -61,17 +61,14 @@ msurface_t *r_debug_surface;
|
|||
|
||||
char r_speeds_msg[MAX_RSPEEDSMSGSIZE];
|
||||
|
||||
//
|
||||
// screen size info
|
||||
//
|
||||
unsigned int r_numEntities;
|
||||
uint r_numEntities;
|
||||
ref_entity_t r_entities[MAX_ENTITIES];
|
||||
ref_entity_t *r_worldent = &r_entities[0];
|
||||
|
||||
unsigned int r_numDlights;
|
||||
uint r_numDlights;
|
||||
dlight_t r_dlights[MAX_DLIGHTS];
|
||||
|
||||
unsigned int r_numPolys;
|
||||
uint r_numPolys;
|
||||
poly_t r_polys[MAX_POLYS];
|
||||
|
||||
lightstyle_t r_lightStyles[MAX_LIGHTSTYLES];
|
||||
|
@ -1352,8 +1349,8 @@ static void R_CullEntities( void )
|
|||
case RT_SPRITE:
|
||||
culled = ( e->radius <= 0 ) || ( e->spriteshader == NULL );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case RT_NONE:
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( !culled ) r_entVisBits[i>>3] |= ( 1<<( i&7 ));
|
||||
|
@ -1457,8 +1454,8 @@ add:
|
|||
if( !shadowmap )
|
||||
R_AddSpritePolyToList( e );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case RT_NONE:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1787,7 +1784,7 @@ R_ClearScene
|
|||
*/
|
||||
void R_ClearScene( void )
|
||||
{
|
||||
r_numEntities = 1;
|
||||
r_numEntities = 2; // world and viewmodel
|
||||
r_numDlights = 0;
|
||||
r_numPolys = 0;
|
||||
RI.previousentity = NULL;
|
||||
|
@ -2238,13 +2235,22 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type )
|
|||
ref_entity_t *refent;
|
||||
bool result = false;
|
||||
|
||||
if( !pRefEntity || !pRefEntity->v.modelindex )
|
||||
return false; // if set to invisible, skip
|
||||
if( r_numEntities >= MAX_ENTITIES ) return false;
|
||||
// NULL or overflow
|
||||
if( !pRefEntity || (r_numEntities >= MAX_ENTITIES))
|
||||
return false;
|
||||
|
||||
refent = &r_entities[r_numEntities];
|
||||
if( pRefEntity->serialnumber == VMODEL_ENTINDEX )
|
||||
{
|
||||
// viewmodel always uses this slot for properly store
|
||||
// and playing client-side animation
|
||||
refent = &r_entities[1];
|
||||
|
||||
if( pRefEntity->v.effects & EF_NODRAW )
|
||||
// client lost weapon or change weapon
|
||||
if( !pRefEntity->v.modelindex ) refent->rtype = RT_NONE; // completely ignore to draw
|
||||
}
|
||||
else refent = &r_entities[r_numEntities];
|
||||
|
||||
if( !pRefEntity->v.modelindex || pRefEntity->v.effects & EF_NODRAW )
|
||||
return true; // done
|
||||
|
||||
// filter ents
|
||||
|
@ -2288,6 +2294,9 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type )
|
|||
result = R_AddGenericEntity( pRefEntity, refent );
|
||||
break;
|
||||
}
|
||||
|
||||
// viewmodel already reserve slot
|
||||
if( pRefEntity->serialnumber != VMODEL_ENTINDEX )
|
||||
r_numEntities++;
|
||||
|
||||
// never adding child entity without parent
|
||||
|
|
|
@ -149,7 +149,7 @@ byte *Mod_ClusterPVS( int cluster, ref_model_t *model )
|
|||
{
|
||||
mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;
|
||||
|
||||
if( cluster == -1 || !bmodel->vis )
|
||||
if( !model || !bmodel || !bmodel->vis || cluster < 0 || cluster >= bmodel->vis->numclusters )
|
||||
return mod_novis;
|
||||
return ( (byte *)bmodel->vis->data + cluster*bmodel->vis->rowsize );
|
||||
}
|
||||
|
@ -2021,16 +2021,16 @@ void R_BeginRegistration( const char *mapname, const dvis_t *visData )
|
|||
if( com.strcmp( r_models[0].name, fullname ))
|
||||
{
|
||||
Mod_FreeModel( &r_models[0] );
|
||||
R_NewMap ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// update progress bar
|
||||
Cvar_SetValue( "scr_loading", 50.0f );
|
||||
if( ri.UpdateScreen ) ri.UpdateScreen();
|
||||
R_StudioFreeAllExtradata (); // load game issues
|
||||
}
|
||||
|
||||
R_NewMap ();
|
||||
|
||||
if( r_lighting_packlightmaps->integer )
|
||||
{
|
||||
string lightmapsPath;
|
||||
|
|
|
@ -335,9 +335,10 @@ float R_GetSpriteFrameInterpolant( ref_entity_t *ent, mspriteframe_t **oldframe,
|
|||
{
|
||||
if( m_fDoInterp )
|
||||
{
|
||||
if( psprite->frames[ent->prev.sequence].type != FRAME_SINGLE )
|
||||
if( ent->prev.sequence >= psprite->numframes || psprite->frames[ent->prev.sequence].type != FRAME_SINGLE )
|
||||
{
|
||||
// this can be happens when rendering switched between single and angled frames
|
||||
// or change model on replace delta-entity
|
||||
ent->prev.sequence = ent->sequence = frame;
|
||||
ent->animtime = RI.refdef.time;
|
||||
lerpFrac = 1.0f;
|
||||
|
@ -367,6 +368,14 @@ float R_GetSpriteFrameInterpolant( ref_entity_t *ent, mspriteframe_t **oldframe,
|
|||
lerpFrac = 1.0f;
|
||||
}
|
||||
|
||||
if( ent->prev.sequence >= psprite->numframes )
|
||||
{
|
||||
// reset interpolation on change model
|
||||
ent->prev.sequence = ent->sequence = frame;
|
||||
ent->animtime = RI.refdef.time;
|
||||
lerpFrac = 0.0f;
|
||||
}
|
||||
|
||||
// get the interpolated frames
|
||||
if( oldframe ) *oldframe = psprite->frames[ent->prev.sequence].frameptr;
|
||||
if( curframe ) *curframe = psprite->frames[frame].frameptr;
|
||||
|
@ -412,9 +421,10 @@ float R_GetSpriteFrameInterpolant( ref_entity_t *ent, mspriteframe_t **oldframe,
|
|||
|
||||
if( m_fDoInterp )
|
||||
{
|
||||
if( psprite->frames[ent->prev.sequence].type != FRAME_ANGLED )
|
||||
if( ent->prev.sequence >= psprite->numframes || psprite->frames[ent->prev.sequence].type != FRAME_ANGLED )
|
||||
{
|
||||
// this can be happens when rendering switched between single and angled frames
|
||||
// or change model on replace delta-entity
|
||||
ent->prev.sequence = ent->sequence = frame;
|
||||
ent->animtime = RI.refdef.time;
|
||||
lerpFrac = 1.0f;
|
||||
|
@ -504,7 +514,7 @@ bool R_DrawSpriteModel( const meshbuffer_t *mb )
|
|||
lerp = bound( 0, lerp, 1 );
|
||||
ilerp = 1.0f - lerp;
|
||||
|
||||
if( ilerp != 0 && oldframe->shader > 0 && oldframe->shader < MAX_SHADERS ) // FIXME
|
||||
if( ilerp != 0 )
|
||||
{
|
||||
e->renderamt = renderamt * ilerp; // merge prevframe alpha
|
||||
rb->shaderkey = r_shaders[oldframe->shader].sortkey;
|
||||
|
|
|
@ -130,6 +130,7 @@ void R_StudioAllocExtradata( edict_t *in, ref_entity_t *e )
|
|||
}
|
||||
else
|
||||
{
|
||||
if( !studio->m_fSequenceFinished )
|
||||
R_StudioFrameAdvance( e, 0 );
|
||||
|
||||
if( studio->m_fSequenceFinished )
|
||||
|
@ -1928,7 +1929,7 @@ void R_StudioDrawDebug( void )
|
|||
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA );
|
||||
pglDepthRange( 0, 0 );
|
||||
|
||||
for( i = 0; i < r_numEntities; i++ )
|
||||
for( i = 1; i < r_numEntities; i++ )
|
||||
{
|
||||
RI.previousentity = RI.currententity;
|
||||
RI.currententity = &r_entities[i];
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<html>
|
||||
<body>
|
||||
<pre>
|
||||
<h1>Build Log</h1>
|
||||
<h3>
|
||||
--------------------Configuration: render - Win32 Debug--------------------
|
||||
</h3>
|
||||
<h3>Command Lines</h3>
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1778.tmp" with contents
|
||||
[
|
||||
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\render\!debug/" /Fo"..\temp\render\!debug/" /Fd"..\temp\render\!debug/" /FD /c
|
||||
"D:\Xash3D\src_main\render\r_shader.c"
|
||||
]
|
||||
Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1778.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1779.tmp" with contents
|
||||
[
|
||||
msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\render\!debug/render.pdb" /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\temp\render\!debug/render.dll" /implib:"..\temp\render\!debug/render.lib" /pdbtype:sept
|
||||
"\Xash3D\src_main\temp\render\!debug\cin.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_aliasq.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_backend.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_bloom.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_cin.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_cull.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_draw.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_image.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_light.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_main.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_math.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_mesh.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_model.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_opengl.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_poly.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_program.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_register.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_shader.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_shadow.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_sky.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_sprite.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_studio.obj"
|
||||
"\Xash3D\src_main\temp\render\!debug\r_surf.obj"
|
||||
]
|
||||
Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1779.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP177A.bat" with contents
|
||||
[
|
||||
@echo off
|
||||
copy \Xash3D\src_main\temp\render\!debug\render.dll "D:\Xash3D\bin\render.dll"
|
||||
]
|
||||
Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP177A.bat"
|
||||
Compiling...
|
||||
r_shader.c
|
||||
Linking...
|
||||
Creating library ..\temp\render\!debug/render.lib and object ..\temp\render\!debug/render.exp
|
||||
<h3>Output Window</h3>
|
||||
Performing Custom Build Step on \Xash3D\src_main\temp\render\!debug\render.dll
|
||||
‘ª®¯¨à®¢ ® ä ©«®¢: 1.
|
||||
|
||||
|
||||
|
||||
<h3>Results</h3>
|
||||
render.dll - 0 error(s), 0 warning(s)
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -880,6 +880,7 @@ int CBasePlayerWeapon :: SetAnimation( Activity activity, float fps )
|
|||
void CBasePlayerWeapon :: SendWeaponAnim( int sequence, float fps )
|
||||
{
|
||||
float framerate = 1.0f; // fps multiplier
|
||||
m_iSequence = sequence; // member current sequence
|
||||
|
||||
if( fps )
|
||||
{
|
||||
|
@ -888,7 +889,7 @@ void CBasePlayerWeapon :: SendWeaponAnim( int sequence, float fps )
|
|||
{
|
||||
dstudioseqdesc_t *pseqdesc;
|
||||
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
|
||||
pseqdesc = (dstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + m_iSequence;
|
||||
framerate = fps / pseqdesc->fps;
|
||||
}
|
||||
}
|
||||
|
@ -897,12 +898,11 @@ void CBasePlayerWeapon :: SendWeaponAnim( int sequence, float fps )
|
|||
pev->body = (pev->body % NUM_HANDS) + NUM_HANDS * m_iBody;
|
||||
|
||||
MESSAGE_BEGIN( MSG_ONE, gmsg.WeaponAnim, NULL, m_pPlayer->pev );
|
||||
WRITE_BYTE( sequence );
|
||||
WRITE_BYTE( m_iSequence );
|
||||
WRITE_BYTE( pev->body );
|
||||
WRITE_BYTE( framerate * 16 );
|
||||
MESSAGE_END();
|
||||
|
||||
m_pPlayer->pev->weaponanim = sequence;
|
||||
SetNextIdle( SequenceDuration( ));
|
||||
}
|
||||
|
||||
|
@ -1320,7 +1320,7 @@ void CBasePlayerWeapon :: PlayAttackSound( int firemode )
|
|||
if(sfxcnt())
|
||||
{
|
||||
int sfxsound = RANDOM_LONG(0, sfxcnt() - 1);
|
||||
EMIT_SOUND(ENT(pev), CHAN_BODY, STRING(SfxSound(sfxsound)), 1.0, ATTN_NORM);
|
||||
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, STRING(SfxSound(sfxsound)), 1.0, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
else //play normal random fire sound
|
||||
|
@ -1328,7 +1328,7 @@ void CBasePlayerWeapon :: PlayAttackSound( int firemode )
|
|||
if(sndcnt())
|
||||
{
|
||||
int firesound = RANDOM_LONG(0, sndcnt() - 1);
|
||||
EMIT_SOUND(ENT(pev), CHAN_BODY, STRING(FireSound(firesound)), 1.0, ATTN_NORM);
|
||||
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, STRING(FireSound(firesound)), 1.0, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1983,7 +1983,8 @@ BOOL CBasePlayerWeapon :: AddPrimaryAmmo( int iCount, char *szName, int iMaxClip
|
|||
if (iIdAmmo > 0)
|
||||
{
|
||||
m_iPrimaryAmmoType = iIdAmmo;
|
||||
if (m_pPlayer->HasPlayerItem( this )) EMIT_SOUND(ENT(pev), CHAN_ITEM, "weapons/glock/clip_in.wav", 1, ATTN_NORM);
|
||||
if( m_pPlayer->HasPlayerItem( this ))
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/glock/clip_in.wav", 1, ATTN_NORM );
|
||||
}
|
||||
return iIdAmmo > 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
@ -1997,7 +1998,7 @@ BOOL CBasePlayerWeapon :: AddSecondaryAmmo( int iCount, char *szName, int iMax )
|
|||
if (iIdAmmo > 0)
|
||||
{
|
||||
m_iSecondaryAmmoType = iIdAmmo;
|
||||
EMIT_SOUND(ENT(pev), CHAN_ITEM, "weapons/glock/clip_in.wav", 1, ATTN_NORM);
|
||||
EMIT_SOUND( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/glock/clip_in.wav", 1, ATTN_NORM );
|
||||
}
|
||||
return iIdAmmo > 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class CLaserSpot;
|
|||
#define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon
|
||||
#define ITEM_FLAG_NODUPLICATE 32 // player can't give this weapon again
|
||||
#define ITEM_FLAG_USEAUTOAIM 64 // weapon uses autoaim
|
||||
#define ITEM_FLAG_HIDEAMMO 128 // weapon uses autoaim
|
||||
#define ITEM_FLAG_HIDEAMMO 128 // hide ammo in round
|
||||
|
||||
// suit definitions
|
||||
#define BARNEY_SUIT 0 // just in case
|
||||
|
@ -32,7 +32,7 @@ class CLaserSpot;
|
|||
|
||||
#define PLAYER_HAS_SUIT (m_pPlayer->pev->weapons & ITEM_SUIT)
|
||||
#define PLAYER_DRAW_SUIT (pev->body & GORDON_SUIT)
|
||||
#define MAX_SHOOTSOUNDS 3 // max of four random shoot sounds
|
||||
#define MAX_SHOOTSOUNDS 3 // max of random shoot sounds
|
||||
|
||||
enum {
|
||||
NONE = 0,
|
||||
|
@ -154,13 +154,13 @@ public:
|
|||
void SendWeaponAnim( int sequence, float fps = 0 );
|
||||
float SetNextAttack( float delay ) { return m_pPlayer->m_flNextAttack = gpGlobals->time + delay; }
|
||||
float SetNextIdle( float delay ) { return m_flTimeWeaponIdle = gpGlobals->time + delay; }
|
||||
float SequenceDuration( void ) { return CBaseAnimating :: SequenceDuration( m_pPlayer->pev->weaponanim ); }
|
||||
float SequenceDuration( void ) { return CBaseAnimating :: SequenceDuration( m_iSequence ); }
|
||||
int GetNumBodies( void )
|
||||
{
|
||||
dstudiohdr_t *pstudiohdr = (dstudiohdr_t *)(GET_MODEL_PTR( ENT( pev )));
|
||||
if( pstudiohdr )
|
||||
{
|
||||
dstudiobodyparts_t *pbodypart = (dstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + 2;
|
||||
dstudiobodyparts_t *pbodypart = (dstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + NUM_HANDS;
|
||||
return pbodypart->nummodels;
|
||||
}
|
||||
return 0;
|
||||
|
@ -176,7 +176,7 @@ public:
|
|||
|
||||
CBasePlayer *m_pPlayer;
|
||||
CBasePlayerWeapon *m_pNext;
|
||||
int m_iId; //Weapon unical Id (0 - MAX_WEAPONS) // WEAPON_???
|
||||
int m_iId; // Weapon unique Id (0 - MAX_WEAPONS)
|
||||
|
||||
//don't save this
|
||||
CLaserSpot *m_pSpot; // LTD spot
|
||||
|
@ -346,6 +346,7 @@ public:
|
|||
int m_cActiveRocket; // how many rockets is now active ?
|
||||
int m_iOnControl; // controllable rocket is on control now
|
||||
int m_iStepReload; // reload state
|
||||
int m_iSequence; // current weaponmodel sequence
|
||||
int m_iClip; // current clip state
|
||||
int m_iBody; // viewmodel body
|
||||
int m_iSkin; // viewmodel skin
|
||||
|
|
|
@ -752,17 +752,21 @@ int AddTransitionToList( LEVELLIST *pLevelList, int listCount, const char *pMapN
|
|||
{
|
||||
int i;
|
||||
|
||||
if ( !pLevelList || !pMapName || !pLandmarkName || !pentLandmark ) return 0;
|
||||
if( !pLevelList || !pMapName ) return 0;
|
||||
|
||||
for( i = 0; i < listCount; i++ )
|
||||
{
|
||||
if( pLevelList[i].pentLandmark == pentLandmark && !strcmp( pLevelList[i].mapName, pMapName ))
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy( pLevelList[listCount].mapName, pMapName );
|
||||
strcpy( pLevelList[listCount].landmarkName, pLandmarkName );
|
||||
pLevelList[listCount].pentLandmark = pentLandmark;
|
||||
pLevelList[listCount].vecLandmarkOrigin = VARS(pentLandmark)->origin;
|
||||
|
||||
if ( FNullEnt( pentLandmark ))
|
||||
pLevelList[listCount].vecLandmarkOrigin = Vector( 0, 0, 0 );
|
||||
else pLevelList[listCount].vecLandmarkOrigin = VARS( pentLandmark )->origin;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -774,23 +778,33 @@ int BuildChangeList( LEVELLIST *pLevelList, int maxList )
|
|||
|
||||
count = 0;
|
||||
|
||||
// Find all of the possible level changes on this BSP
|
||||
// find all of the possible level changes on this BSP
|
||||
CBaseEntity *pChangelevel = UTIL_FindEntityByClassname( NULL, "trigger_changelevel" );
|
||||
|
||||
if ( !pChangelevel ) return NULL;
|
||||
if( !pChangelevel ) return 0;
|
||||
|
||||
while ( pChangelevel )
|
||||
{
|
||||
// Find the corresponding landmark
|
||||
// find the corresponding landmark
|
||||
pentLandmark = UTIL_FindLandmark( pChangelevel->pev->message );
|
||||
if( pentLandmark )
|
||||
{
|
||||
// Build a list of unique transitions
|
||||
DevMsg("Map name %s, landmark name %s\n", STRING(pChangelevel->pev->netname), STRING(pChangelevel->pev->message));
|
||||
if ( AddTransitionToList( pLevelList, count, (char *)STRING(pChangelevel->pev->netname), (char *)STRING(pChangelevel->pev->message), pentLandmark ))
|
||||
// build a list of unique transitions
|
||||
ALERT( at_aiconsole, "Map name %s, landmark name %s\n", STRING( pChangelevel->pev->netname ), STRING( pChangelevel->pev->message ));
|
||||
if( AddTransitionToList( pLevelList, count, STRING( pChangelevel->pev->netname ), STRING( pChangelevel->pev->message ), pentLandmark ))
|
||||
{
|
||||
count++;
|
||||
if ( count >= maxList )break;//List is FULL!!!
|
||||
if( count >= maxList ) break; // list is FULL!!!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// build a list of unique transitions (direct mode, when landmark not used)
|
||||
ALERT( at_aiconsole, "Map name %s\n", STRING( pChangelevel->pev->netname ));
|
||||
if( AddTransitionToList( pLevelList, count, STRING( pChangelevel->pev->netname ), "", NULL ))
|
||||
{
|
||||
count++;
|
||||
if( count >= maxList ) break; // list is FULL!!!
|
||||
}
|
||||
}
|
||||
pChangelevel = UTIL_FindEntityByClassname( pChangelevel, "trigger_changelevel" );
|
||||
|
@ -802,13 +816,20 @@ int BuildChangeList( LEVELLIST *pLevelList, int maxList )
|
|||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
int j, entityCount = 0;
|
||||
int entityCount = 0;
|
||||
CBaseEntity *pEntList[MAX_TRANSITION_ENTITY];
|
||||
int entityFlags[MAX_TRANSITION_ENTITY];
|
||||
|
||||
// Follow the linked list of entities in the PVS of the transition landmark
|
||||
edict_t *pent = UTIL_EntitiesInPVS( pLevelList[i].pentLandmark );
|
||||
|
||||
if( FNullEnt( pent ))
|
||||
{
|
||||
// landmark is absent so use Classic Changelel:
|
||||
// transfer client and him attached items
|
||||
pent = UTIL_FindClientTransitions( INDEXENT( 1 ));
|
||||
}
|
||||
|
||||
// Build a list of valid entities in this linked list (we're going to use pent->v.chain again)
|
||||
while ( !FNullEnt( pent ))
|
||||
{
|
||||
|
@ -816,11 +837,11 @@ int BuildChangeList( LEVELLIST *pLevelList, int maxList )
|
|||
if( pEntity )
|
||||
{
|
||||
int caps = pEntity->ObjectCaps();
|
||||
|
||||
if(!( caps & FCAP_DONT_SAVE ))
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
// If this entity can be moved or is global, mark it
|
||||
if( caps & FCAP_ACROSS_TRANSITION ) flags |= FENTTABLE_MOVEABLE;
|
||||
if( pEntity->pev->globalname && !pEntity->IsDormant() ) flags |= FENTTABLE_GLOBAL;
|
||||
if( flags )
|
||||
|
@ -828,14 +849,18 @@ int BuildChangeList( LEVELLIST *pLevelList, int maxList )
|
|||
pEntList[entityCount] = pEntity;
|
||||
entityFlags[entityCount] = flags;
|
||||
entityCount++;
|
||||
if ( entityCount > MAX_TRANSITION_ENTITY ) Msg("ERROR: Too many entities across a transition!" );
|
||||
if( entityCount >= MAX_TRANSITION_ENTITY )
|
||||
{
|
||||
ALERT( at_error, "Too many entities across a transition!" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pent = pent->v.chain;
|
||||
}
|
||||
|
||||
for ( j = 0; j < entityCount; j++ )
|
||||
for ( int j = 0; j < entityCount; j++ )
|
||||
{
|
||||
// Check to make sure the entity isn't screened out by a trigger_transition
|
||||
if( entityFlags[j] && UTIL_FindTransition( pEntList[j], pLevelList[i].landmarkName ))
|
||||
|
@ -966,7 +991,7 @@ int ServerClassifyEdict( edict_t *pentToClassify )
|
|||
// first pass: determine type by explicit parms
|
||||
if( pClass->pev->solid == SOLID_TRIGGER )
|
||||
{
|
||||
if( !stricmp( classname, "trigger_teleport" ))
|
||||
if( !stricmp( classname, "trigger_teleport" )) // FIXME
|
||||
return ED_AMBIENT;
|
||||
else if( pClass->pev->movetype == MOVETYPE_TOSS )
|
||||
return ED_NORMAL; // it's item or weapon
|
||||
|
|
|
@ -481,7 +481,6 @@ void CSave :: WriteVector( const char *pname, const float *value, int count )
|
|||
|
||||
void CSave :: WritePositionVector( const char *pname, const Vector &value )
|
||||
{
|
||||
|
||||
if( m_pdata && m_pdata->fUseLandmark )
|
||||
{
|
||||
Vector tmp = value - m_pdata->vecLandmarkOffset;
|
||||
|
@ -584,12 +583,6 @@ int CSave :: WriteFields( const char *cname, const char *pname, void *pBaseData,
|
|||
|
||||
#if 0
|
||||
ALERT( at_console, "CSave::WriteFields( %s [%i fields])\n", pname, fieldCount );
|
||||
|
||||
if( !strcmp( pname, "Save Header" ) || !strcmp( pname, "ADJACENCY" ) || !strcmp( pname, "Game Header" ))
|
||||
{
|
||||
for( i = 0; i < fieldCount; i++ )
|
||||
ALERT( at_console, "FIELD: %s [%s][0x%x]\n", pFields[i].fieldName, gNames[pFields[i].fieldType], pFields[i].flags );
|
||||
}
|
||||
#endif
|
||||
// precalculate the number of empty fields
|
||||
emptyCount = 0;
|
||||
|
@ -849,7 +842,8 @@ int CRestore::ReadField( void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCou
|
|||
else
|
||||
{
|
||||
*((CBaseEntity **)pOutputData) = NULL;
|
||||
if (entityIndex != -1) ALERT(at_console, "## Restore: invalid entitynum %d\n", entityIndex);
|
||||
if( entityIndex != -1 )
|
||||
ALERT( at_console, "## Restore: invalid entitynum %d\n", entityIndex );
|
||||
}
|
||||
break;
|
||||
case FIELD_EDICT:
|
||||
|
|
|
@ -578,6 +578,9 @@ edict_t *UTIL_FindLandmark( const char *pLandmarkName )
|
|||
{
|
||||
CBaseEntity *pLandmark;
|
||||
|
||||
if( FStringNull( pLandmarkName ) || FStrEq( pLandmarkName, "" ))
|
||||
return NULL; // landmark not specified
|
||||
|
||||
pLandmark = UTIL_FindEntityByTargetname( NULL, pLandmarkName );
|
||||
while( pLandmark )
|
||||
{
|
||||
|
@ -586,22 +589,23 @@ edict_t *UTIL_FindLandmark( const char *pLandmarkName )
|
|||
return ENT( pLandmark->pev );
|
||||
else pLandmark = UTIL_FindEntityByTargetname( pLandmark, pLandmarkName );
|
||||
}
|
||||
|
||||
Msg( "ERROR: Can't find landmark %s\n", pLandmarkName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int UTIL_FindTransition( CBaseEntity *pEntity, string_t iVolumeName )
|
||||
{
|
||||
return UTIL_FindTransition( pEntity, (char *)STRING( iVolumeName ));
|
||||
return UTIL_FindTransition( pEntity, STRING( iVolumeName ));
|
||||
}
|
||||
|
||||
int UTIL_FindTransition( CBaseEntity *pEntity, char *pVolumeName )
|
||||
int UTIL_FindTransition( CBaseEntity *pEntity, const char *pVolumeName )
|
||||
{
|
||||
CBaseEntity *pVolume;
|
||||
|
||||
if( pEntity->ObjectCaps() & FCAP_FORCE_TRANSITION ) return 1;
|
||||
|
||||
// If you're following another entity, follow it through the transition (weapons follow the player)
|
||||
// if you're following another entity, follow it through the transition (weapons follow the player)
|
||||
if( pEntity->pev->movetype == MOVETYPE_FOLLOW && pEntity->pev->aiment != NULL )
|
||||
{
|
||||
pEntity = CBaseEntity::Instance( pEntity->pev->aiment );
|
||||
|
@ -614,15 +618,46 @@ int UTIL_FindTransition( CBaseEntity *pEntity, char *pVolumeName )
|
|||
{
|
||||
if( FClassnameIs( pVolume->pev, "trigger_transition" ))
|
||||
{
|
||||
if ( pVolume->Intersects( pEntity ) ) // It touches one, it's in the volume
|
||||
if( pVolume->Intersects( pEntity )) // it touches one, it's in the volume
|
||||
return 1;
|
||||
else inVolume = 0; // Found a trigger_transition, but I don't intersect it
|
||||
else inVolume = 0; // found a trigger_transition, but I don't intersect it
|
||||
}
|
||||
pVolume = UTIL_FindEntityByTargetname( pVolume, pVolumeName );
|
||||
}
|
||||
return inVolume;
|
||||
}
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
UTIL_FindClientTransitions - returns list of client attached entites
|
||||
e.g. weapons, items and other followed entities
|
||||
========================================================================
|
||||
*/
|
||||
edict_t *UTIL_FindClientTransitions( edict_t *pClient )
|
||||
{
|
||||
edict_t *pEdict, *chain;
|
||||
int i;
|
||||
|
||||
chain = NULL;
|
||||
pClient->v.chain = chain; // client is always add to tail of chain
|
||||
chain = pClient;
|
||||
|
||||
if( !pClient || pClient->free )
|
||||
return chain;
|
||||
|
||||
for( i = 0; i < gpGlobals->numEntities; i++ )
|
||||
{
|
||||
pEdict = INDEXENT( i );
|
||||
if( pEdict->free ) continue;
|
||||
if( pEdict->v.movetype == MOVETYPE_FOLLOW && pEdict->v.aiment == pClient )
|
||||
{
|
||||
pEdict->v.chain = chain;
|
||||
chain = pEdict;
|
||||
}
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
// UTIL_ClearPTR - clear all pointers before changelevel
|
||||
//========================================================================
|
||||
|
@ -630,7 +665,7 @@ void UTIL_ClearPTR( void )
|
|||
{
|
||||
CBaseEntity *pEntity = NULL;
|
||||
|
||||
for ( int i = 1; i <= gpGlobals->maxEntities; i++ )
|
||||
for( int i = 1; i < gpGlobals->numEntities; i++ )
|
||||
{
|
||||
edict_t *pEntityEdict = INDEXENT( i );
|
||||
if( pEntityEdict && !pEntityEdict->free && !FStringNull( pEntityEdict->v.globalname ))
|
||||
|
@ -647,29 +682,29 @@ void UTIL_ClearPTR( void )
|
|||
//========================================================================
|
||||
void UTIL_ChangeLevel( string_t mapname, string_t spotname )
|
||||
{
|
||||
UTIL_ChangeLevel((char *)STRING( mapname ), (char *)STRING( spotname ));
|
||||
UTIL_ChangeLevel( STRING( mapname ), STRING( spotname ));
|
||||
}
|
||||
|
||||
void UTIL_ChangeLevel( const char *szNextMap, const char *szNextSpot )
|
||||
{
|
||||
edict_t *pentLandmark;
|
||||
LEVELLIST levels[16];
|
||||
|
||||
ASSERT( !FStrEq( szNextMap, "" ));
|
||||
|
||||
// Don't work in deathmatch
|
||||
// don't work in deathmatch
|
||||
if( IsMultiplayer()) return;
|
||||
// Some people are firing these multiple times in a frame, disable
|
||||
|
||||
// some people are firing these multiple times in a frame, disable
|
||||
if( NewLevel ) return;
|
||||
|
||||
CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 );
|
||||
if (!UTIL_FindTransition( pPlayer, (char *)szNextSpot ))
|
||||
if( !UTIL_FindTransition( pPlayer, szNextSpot ))
|
||||
{
|
||||
DevMsg( "Player isn't in the transition volume %s, aborting\n", szNextSpot );
|
||||
return;
|
||||
}
|
||||
|
||||
// This object will get removed in the call to CHANGE_LEVEL, copy the params into "safe" memory
|
||||
// this object will get removed in the call to CHANGE_LEVEL, copy the params into "safe" memory
|
||||
strcpy( st_szNextMap, szNextMap );
|
||||
st_szNextSpot[0] = 0; // Init landmark to NULL
|
||||
|
||||
|
@ -681,19 +716,15 @@ void UTIL_ChangeLevel( const char *szNextMap, const char *szNextSpot )
|
|||
gpGlobals->spotOffset = VARS( pentLandmark )->origin;
|
||||
}
|
||||
|
||||
//try to found bsp file before loading nextlevel
|
||||
char path[128];
|
||||
|
||||
sprintf(path, "maps/%s.bsp", st_szNextMap);
|
||||
|
||||
if( FILE_EXISTS( path ))
|
||||
// map must exist and contain info_player_start
|
||||
if( IS_MAP_VALID( st_szNextMap ))
|
||||
{
|
||||
UTIL_ClearPTR();
|
||||
DevMsg( "CHANGE LEVEL: %s %s\n", st_szNextMap, st_szNextSpot );
|
||||
ALERT( at_aiconsole, "CHANGE LEVEL: %s %s\n", st_szNextMap, st_szNextSpot );
|
||||
CHANGE_LEVEL( st_szNextMap, st_szNextSpot );
|
||||
}
|
||||
else Msg("Warning! Map %s not found!\n", st_szNextMap );
|
||||
NewLevel = TRUE;//bit who indiactes new level
|
||||
else ALERT( at_warning, "map %s not found!\n", st_szNextMap );
|
||||
NewLevel = TRUE; // UTIL_ChangeLevel is called
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
|
|
|
@ -328,6 +328,7 @@ extern CBaseEntity *UTIL_FindEntityByTarget(CBaseEntity *pStartEntity, const cha
|
|||
extern CBaseEntity *UTIL_FindEntityGeneric(const char *szName, Vector &vecSrc, float flRadius );
|
||||
extern CBaseEntity *UTIL_FindGlobalEntity( string_t classname, string_t globalname );
|
||||
extern CBaseEntity *UTIL_FindPlayerInSphere( const Vector &vecCenter, float flRadius );
|
||||
extern edict_t *UTIL_FindClientTransitions( edict_t *pClient );
|
||||
extern CBasePlayer *UTIL_FindPlayerInPVS( edict_t *pent );
|
||||
|
||||
// returns a CBaseEntity pointer to a player by index. Only returns if the player is spawned and connected
|
||||
|
@ -335,6 +336,7 @@ extern CBasePlayer *UTIL_FindPlayerInPVS( edict_t *pent );
|
|||
// Index is 1 based
|
||||
extern CBaseEntity *UTIL_PlayerByIndex( int playerIndex );
|
||||
|
||||
|
||||
#define UTIL_EntitiesInPVS( pent ) (*g_engfuncs.pfnEntitiesInPVS)(pent)
|
||||
extern void UTIL_MakeVectors( const Vector &vecAngles );
|
||||
|
||||
|
@ -787,7 +789,7 @@ void UTIL_WatchTarget( CBaseEntity *pWatcher, CBaseEntity *pTarget);
|
|||
void UTIL_FindBreakable( CBaseEntity *Brush );
|
||||
edict_t *UTIL_FindLandmark( string_t iLandmarkName );
|
||||
edict_t *UTIL_FindLandmark( const char *pLandmarkName );
|
||||
int UTIL_FindTransition( CBaseEntity *pEntity, char *pVolumeName );
|
||||
int UTIL_FindTransition( CBaseEntity *pEntity, const char *pVolumeName );
|
||||
int UTIL_FindTransition( CBaseEntity *pEntity, string_t iVolumeName );
|
||||
void UTIL_FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value = 0);
|
||||
void UTIL_FireTargets( int targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value = 0);
|
||||
|
|
|
@ -3427,8 +3427,9 @@ int CBasePlayer::Restore( CRestore &restore )
|
|||
// default to normal spawn
|
||||
edict_t* pentSpawnSpot = EntSelectSpawnPoint( this );
|
||||
pev->origin = VARS( pentSpawnSpot )->origin + Vector( 0, 0, 1 );
|
||||
pev->angles = VARS(pentSpawnSpot)->angles;
|
||||
pev->viewangles = pev->angles = VARS( pentSpawnSpot )->angles;
|
||||
}
|
||||
|
||||
pev->viewangles.z = 0; // clear out roll
|
||||
pev->angles = pev->viewangles;
|
||||
pev->fixangle = TRUE; // turn this way immediately
|
||||
|
|
|
@ -3,9 +3,94 @@
|
|||
<pre>
|
||||
<h1>Build Log</h1>
|
||||
<h3>
|
||||
--------------------Configuration: server - Win32 Release--------------------
|
||||
--------------------Configuration: server - Win32 Debug--------------------
|
||||
</h3>
|
||||
<h3>Command Lines</h3>
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1780.tmp" with contents
|
||||
[
|
||||
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "ents" /I "game" /I "global" /I "monsters" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\server\!debug/" /Fo"..\temp\server\!debug/" /Fd"..\temp\server\!debug/" /FD /c
|
||||
"D:\Xash3D\src_main\server\global\dll_int.cpp"
|
||||
]
|
||||
Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1780.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1781.tmp" with contents
|
||||
[
|
||||
msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\server\!debug/server.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /def:".\server.def" /out:"..\temp\server\!debug/server.dll" /implib:"..\temp\server\!debug/server.lib" /pdbtype:sept
|
||||
"\Xash3D\src_main\temp\server\!debug\ai_sound.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\animating.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\animation.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\apache.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\barnacle.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\barney.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basebrush.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseentity.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basefunc.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basefx.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseinfo.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseitem.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baselogic.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basemonster.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basemover.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseother.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basepath.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basephys.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baserockets.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basetank.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\basetrigger.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseutil.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseweapon.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\baseworld.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\client.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\combat.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\decals.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\defaultai.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\dll_int.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\flyingmonster.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\game.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\gamerules.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\generic.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\globals.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\gman.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\hassassin.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\headcrab.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\hgrunt.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\leech.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\legacy.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\lights.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\multiplay_gamerules.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\nodes.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\osprey.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\parent.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\player.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\rat.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\roach.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\saverestore.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\scientist.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\scripted.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\sfx.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\singleplay_gamerules.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\sound.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\spectator.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\squadmonster.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\talkmonster.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\teamplay_gamerules.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\turret.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\utils.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\weapon_generic.obj"
|
||||
"\Xash3D\src_main\temp\server\!debug\zombie.obj"
|
||||
]
|
||||
Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1781.tmp"
|
||||
Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1782.bat" with contents
|
||||
[
|
||||
@echo off
|
||||
copy \Xash3D\src_main\temp\server\!debug\server.dll "D:\Xash3D\bin\server.dll"
|
||||
]
|
||||
Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSP1782.bat"
|
||||
Compiling...
|
||||
dll_int.cpp
|
||||
Linking...
|
||||
<h3>Output Window</h3>
|
||||
Performing Custom Build Step on \Xash3D\src_main\temp\server\!debug\server.dll
|
||||
‘ª®¯¨à®¢ ® ä ©«®¢: 1.
|
||||
|
||||
|
||||
|
||||
|
|
6
todo.log
6
todo.log
|
@ -151,4 +151,8 @@ Beta 13.12.09
|
|||
124. fixup studio events on client-side OK
|
||||
125. sort & implement engfuncs on server.dll
|
||||
126. implement trace from Quake3
|
||||
127. debug sv.edicts and cl.edicts management
|
||||
127. debug sv.edicts and cl.edicts management OK
|
||||
128. fixup sprites lerping OK
|
||||
129. fixup sound orientation OK
|
||||
130. don't show console on changelevel OK
|
||||
131. support for doom3-style parsing
|
||||
|
|
Reference in New Issue