29 Sep 2009

This commit is contained in:
g-cont 2009-09-29 00:00:00 +04:00 committed by Alibek Omarov
parent 587d7f70f0
commit d87d09b959
63 changed files with 1583 additions and 881 deletions

View File

@ -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>

View File

@ -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;
int i;
float m_fLerp;
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

View File

@ -550,16 +550,17 @@ void DrawImageBar( float percent, const char *szSpriteName, int x, int y )
//
void V_RenderPlaque( void )
{
const char *levelshot;
if( gHUD.m_iDrawPlaque )
{
const char *levelshot;
levelshot = CVAR_GET_STRING( "cl_levelshot_name" );
// logo that shows up while upload next level
DrawImageRectangle( SPR_Load( levelshot ));
DrawImageBar( CVAR_GET_FLOAT( "scr_loading" ), "m_loading" );
// 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 );
}

View File

@ -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( ); \

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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,23 +84,21 @@ 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 )
{
// write it out
len = LittleLong (buf.cursize);
len = LittleLong( buf.cursize );
FS_Write( cls.demofile, &len, 4 );
FS_Write( cls.demofile, buf.data, buf.cursize );
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 );

View File

@ -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,18 +238,18 @@ 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" );
idx = MSG_ReadByte( msg );
clent = EDICT_NUM( idx ); // get client
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 );
Host_Error( "CL_ParseFrame: invalid playernum (%d should be %d)\n", idx-1, cl.playernum );
// now we can reading delta player state
if( cl.oldframe ) cl.frame.ps = MSG_ParseDeltaPlayer( &cl.oldframe->ps, &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;
edict_t *ent;
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 );
}
}

View File

@ -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;

View File

@ -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

View File

@ -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 ();

View File

@ -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;

View File

@ -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,8 +101,8 @@ apply pre-calculated values
*/
void V_AddViewModel( void )
{
if( cl.viewent.v.modelindex && !cl.refdef.nextView )
re->AddRefEntity( &cl.viewent, ED_VIEWMODEL );
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_ClearScene ();
CL_AddEntities ();
V_SetupRefDef ();
V_CalcRefDef ();
}

View File

@ -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;

View File

@ -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 );

View File

@ -245,11 +245,11 @@ void Con_Init( void )
// register our commands
con_notifytime = Cvar_Get( "con_notifytime", "3", 0, "notify time to live" );
con_speed = Cvar_Get( "con_speed", "3", 0, "console moving speed" );
con_font = Cvar_Get( "con_font", "default", CVAR_ARCHIVE, "path to console charset" );
con_font = Cvar_Get( "con_font", "default", CVAR_ARCHIVE, "path to console charset" );
Field_Clear( &g_consoleField );
g_consoleField.widthInChars = g_console_field_width;
for ( i = 0 ; i < COMMAND_HISTORY ; i++ )
for( i = 0; i < COMMAND_HISTORY; i++ )
{
Field_Clear( &historyEditLines[i] );
historyEditLines[i].widthInChars = g_console_field_width;
@ -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;
}
@ -554,24 +555,22 @@ Con_DrawConsole
*/
void Con_DrawConsole( void )
{
if(!host.developer) return;
if( !host.developer ) return;
// 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,10 +578,18 @@ 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 );
else if ( cls.state == ca_active ) Con_DrawNotify(); // draw notify lines
else if( cls.state == ca_active ) Con_DrawNotify(); // draw notify lines
break;
}
}

View File

@ -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
};

View File

@ -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;
Mem_Set( to, 0, sizeof( *to ));
to->number = MAX_EDICTS - 1; // entity was removed
return;
}
for( i = 0, field = ent_fields; field->name; i++, field++ )

View File

@ -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

View File

@ -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.

View File

@ -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 );

View File

@ -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;
//===========================================================
@ -316,10 +323,12 @@ 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 );
int SV_FindIndex (const char *name, int start, int end, bool create);
void SV_InitGame( void );
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 );
//============================================================
//

View File

@ -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 )
@ -632,7 +636,7 @@ void SV_New_f( sv_client_t *cl )
// begin fetching configstrings
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, va("cmd configstrings %i %i\n", svs.spawncount, 0 ));
MSG_WriteString( &cl->netchan.message, va( "cmd configstrings %i %i\n", svs.spawncount, 0 ));
}
}
@ -1066,7 +1070,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
Cmd_TokenizeString( s );
c = Cmd_Argv( 0 );
MsgDev( D_INFO, "SV_ConnectionlessPacket: %s : %s\n", NET_AdrToString(from), c);
MsgDev( D_INFO, "SV_ConnectionlessPacket: %s : %s\n", NET_AdrToString( from ), c );
if( !com.strcmp( c, "ping" )) SV_Ping( from );
else if( !com.strcmp( c, "ack" )) SV_Ack( from );

View File

@ -193,6 +193,7 @@ For development work
void SV_Map_f( void )
{
string filename;
char *spawn_entity;
if( Cmd_Argc() != 2 )
{
@ -200,29 +201,41 @@ 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
Cbuf_ExecuteText(EXEC_APPEND, va("map %s\n", GI->startmap ));
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 );
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();
}
/*
@ -265,10 +280,10 @@ void SV_Save_f( void )
{
if( Cmd_Argc() != 2 )
{
Msg ("Usage: save <name>\n");
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;
}
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 );
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_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 )

View File

@ -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++ )
{

View File

@ -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;
f = FS_Open( va( "maps/%s.bsp", filename ), "rb" );
char *spawn_entity;
if( f )
{
string dm_entity;
// 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;
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,37 +3285,42 @@ 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
for( i = 0; i < svgame.globals->maxClients; i++ )
if( !sv.loadgame && !sv.changelevel )
{
// setup all clients
ent = EDICT_NUM( i + 1 );
SV_InitEdict( ent );
ent->pvServerData->client = svs.clients + i;
ent->pvServerData->client->edict = ent;
svgame.globals->numClients++;
for( i = 0; i < svgame.globals->maxClients; i++ )
{
// setup all clients
ent = EDICT_NUM( i + 1 );
SV_InitEdict( ent );
ent->pvServerData->client = svs.clients + i;
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();
svgame.dllFuncs.pfnGameShutdown ();
Sys_FreeNameFuncGlobals();
Sys_FreeNameFuncGlobals ();
Com_FreeLibrary( svgame.hInstance );
Mem_FreePool( &svgame.mempool );
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++ )

View File

@ -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;
}
sv.time = 1000;
com.strncpy( sv.name, server, MAX_STRING );
FS_FileBase(server, sv.configstrings[CS_NAME]);
// 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;
com.sprintf( sv.configstrings[CS_MODELS+1], "maps/%s", server );
Cvar_SetValue( "skill", (float)current_skill );
sv.time = 1000;
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.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
}
/*

View File

@ -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 ));

View File

@ -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

View File

@ -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,15 +246,39 @@ 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 )
{
svgame.dllFuncs.pfnSave( pent, pSaveData );
if( pTable->classname && pTable->size )
pTable->id = pent->serialnumber;
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 )
pTable->id = pent->serialnumber;
else pTable->flags |= FENTTABLE_REMOVED;
}
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;
}
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];
@ -303,7 +348,7 @@ void SV_WriteSaveFile( const char *name, bool autosave )
if( !savfile )
{
MsgDev(D_ERROR, "SV_WriteSaveFile: failed to open %s\n", path );
MsgDev( D_ERROR, "SV_WriteSaveFile: failed to open %s\n", path );
return;
}
@ -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 ));
svs.spawncount = ghdr.mapCount; // restore spawncount
Mem_Copy( svs.comment, ghdr.comment, MAX_STRING );
com.strncpy( svs.mapname, ghdr.mapName, MAX_STRING );
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 ));
SV_ConfigString( CS_MAXCLIENTS, va( "%i", sv_maxclients->integer ));
com.strncpy( sv.name, shdr.mapName, MAX_STRING );
svgame.globals->mapname = MAKE_STRING( sv.name );
svgame.globals->time = shdr.time;
sv.time = svgame.globals->time * 1000;
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;
}
// 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( pTable->flags & FENTTABLE_REMOVED ) SV_FreeEdict( pent );
else pent = SV_AllocPrivateData( pent, pTable->classname );
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;
// check for client or global entity
if( pTable->flags & (FENTTABLE_PLAYER|FENTTABLE_GLOBAL))
bAlloc = true;
if( pTable->id != pent->serialnumber )
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,15 +639,34 @@ void SV_ReadEntities( wfile_t *l )
edict_t *pent = EDICT_NUM( i );
pTable = &pSaveData->pTable[i];
// ignore removed edicts
if( !pent->free && pTable->classname )
if( sv.loadgame )
{
svgame.dllFuncs.pfnRestore( pent, pSaveData, false );
SV_RestoreEdict( pent );
// 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++;
}
// do cleanup operations
Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA ));
svgame.globals->pSaveData = NULL;
@ -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 );
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
if( sv.loadgame && !sv.changelevel )
{
SV_ReadCvars( savfile );
SV_InitGame(); // start a new game fresh with new cvars
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;
@ -610,4 +821,39 @@ bool SV_GetComment( char *comment, int savenum )
WAD_Close( savfile );
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;
}

View File

@ -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" ))
{
@ -2694,11 +2700,11 @@ FS_FileTime
return time of creation file in seconds
==================
*/
fs_offset_t FS_FileTime (const char *filename)
fs_offset_t FS_FileTime( const char *filename )
{
struct stat buf;
if( stat( filename, &buf) == -1 )
if( stat( filename, &buf ) == -1 )
return -1;
return buf.st_mtime;

View File

@ -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 );

63
launch/launch.plg Normal file
View File

@ -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>

View File

@ -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 );
}

View File

@ -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();
}

View File

@ -344,7 +344,7 @@ const char *StringTable_GetString( int handle, string_t index )
string_t StringTable_SetString( int handle, const char *string )
{
int i, len, table_size, data_size;
int i, len, table_size, data_size;
if( !StringTable_CheckHandle( handle, false ))
return -1;

16
physic/physic.plg Normal file
View File

@ -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>

View File

@ -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!)
/*
==============================================================================

View File

@ -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 );

View File

@ -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;

View File

@ -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

View File

@ -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,20 +61,17 @@ msurface_t *r_debug_surface;
char r_speeds_msg[MAX_RSPEEDSMSGSIZE];
//
// screen size info
//
unsigned int r_numEntities;
ref_entity_t r_entities[MAX_ENTITIES];
ref_entity_t *r_worldent = &r_entities[0];
uint r_numEntities;
ref_entity_t r_entities[MAX_ENTITIES];
ref_entity_t *r_worldent = &r_entities[0];
unsigned int r_numDlights;
dlight_t r_dlights[MAX_DLIGHTS];
uint r_numDlights;
dlight_t r_dlights[MAX_DLIGHTS];
unsigned int r_numPolys;
poly_t r_polys[MAX_POLYS];
uint r_numPolys;
poly_t r_polys[MAX_POLYS];
lightstyle_t r_lightStyles[MAX_LIGHTSTYLES];
lightstyle_t r_lightStyles[MAX_LIGHTSTYLES];
int r_viewcluster, r_oldviewcluster;
@ -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,7 +2294,10 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type )
result = R_AddGenericEntity( pRefEntity, refent );
break;
}
r_numEntities++;
// viewmodel already reserve slot
if( pRefEntity->serialnumber != VMODEL_ENTINDEX )
r_numEntities++;
// never adding child entity without parent
// only studio models can have attached childrens

View File

@ -1031,7 +1031,7 @@ static bool R_DrawPortalSurface( void )
}
}
if( ( i == r_numEntities ) && !captureTexture )
if(( i == r_numEntities ) && !captureTexture )
return false;
setup_and_render:

View File

@ -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,15 +2021,15 @@ 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 )
{

View File

@ -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;

View File

@ -130,7 +130,8 @@ void R_StudioAllocExtradata( edict_t *in, ref_entity_t *e )
}
else
{
R_StudioFrameAdvance( e, 0 );
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];

63
render/render.plg Normal file
View File

@ -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>

View File

@ -701,10 +701,10 @@ void CFuncTeleport :: Touch( CBaseEntity *pOther )
return;
if( IsLockedByMaster( pOther )) return;
pTarget = UTIL_FindEntityByTargetname( pTarget, STRING(pev->target) );
if ( !pTarget ) return;
pTarget = UTIL_FindEntityByTargetname( pTarget, STRING( pev->target ));
if( !pTarget ) return;
CBaseEntity *pLandmark = UTIL_FindEntityByTargetname( NULL, STRING(pev->message) );
CBaseEntity *pLandmark = UTIL_FindEntityByTargetname( NULL, STRING( pev->message ));
if ( pLandmark )
{
Vector vecOriginOffs = pTarget->pev->origin - pLandmark->pev->origin;

View File

@ -737,7 +737,7 @@ int CBasePlayerWeapon :: PlaySequence( Activity activity, float fps )
if(!m_pPlayer->pev->viewmodel) return -1;
UTIL_SetModel( ENT(pev), STRING( m_pPlayer->pev->viewmodel ));
int iSequence = LookupActivity( activity );
if(iSequence != -1) SendWeaponAnim(iSequence, fps);
if( iSequence != -1 ) SendWeaponAnim( iSequence, fps );
else DevMsg("Warning: %s not found\n", activity_map[activity - 1].name);
return iSequence;
@ -866,7 +866,7 @@ int CBasePlayerWeapon :: SetAnimation( Activity activity, float fps )
iSequence = LookupSequence( pAnimsList[i] );
if( iSequence != -1 )
{
SendWeaponAnim (iSequence, fps ); // names method
SendWeaponAnim( iSequence, fps ); // names method
return iSequence;
}
}
@ -879,7 +879,8 @@ int CBasePlayerWeapon :: SetAnimation( Activity activity, float fps )
//=========================================================
void CBasePlayerWeapon :: SendWeaponAnim( int sequence, float fps )
{
float framerate = 1.0f; // fps multiplier
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;
}

View File

@ -16,14 +16,14 @@
class CLaserSpot;
// weapon flags
#define ITEM_FLAG_SELECTONEMPTY 1 //this weapon can choose without ammo
#define ITEM_FLAG_NOAUTORELOAD 2 //only manual reload
#define ITEM_FLAG_NOAUTOSWITCHEMPTY 4 //don't switch from this weapon
#define ITEM_FLAG_LIMITINWORLD 8 //limit in world
#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_SELECTONEMPTY 1 // this weapon can choose without ammo
#define ITEM_FLAG_NOAUTORELOAD 2 // only manual reload
#define ITEM_FLAG_NOAUTOSWITCHEMPTY 4 // don't switch from this weapon
#define ITEM_FLAG_LIMITINWORLD 8 // limit in world
#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 // hide ammo in round
// suit definitions
#define BARNEY_SUIT 0 // just in case
@ -32,17 +32,17 @@ 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,
AMMO1, //fire primary ammo
AMMO2, //fire seondary ammo
LASER_DOT, //enable laser dot
ZOOM, //enable zoom
FLASHLIGHT, //enable flashlight
SWITCHMODE, //play two beetwen anims and change body
SWING, //crowbar swing
AMMO1, // fire primary ammo
AMMO2, // fire seondary ammo
LASER_DOT, // enable laser dot
ZOOM, // enable zoom
FLASHLIGHT, // enable flashlight
SWITCHMODE, // play two beetwen anims and change body
SWING, // crowbar swing
};
#define BATTACK_FIREMODE0 0 //both attack firemode 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)
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,10 +176,10 @@ 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
CLaserSpot *m_pSpot; // LTD spot
//virtual methods for ItemInfo acess
int iItemPosition(void) { return ItemInfoArray[ m_iId ].iPosition; }
@ -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

View File

@ -739,9 +739,9 @@ void PlayerPostThink( edict_t *pEntity )
void BuildLevelList( void )
{
// retrieve the pointer to the save data
SAVERESTOREDATA *pSaveData = (SAVERESTOREDATA *)gpGlobals->pSaveData;
SAVERESTOREDATA *pSaveData = (SAVERESTOREDATA *)gpGlobals->pSaveData;
if ( pSaveData )
if( pSaveData )
pSaveData->connectionCount = BuildChangeList( pSaveData->levelList, MAX_LEVEL_CONNECTIONS );
}
@ -750,100 +750,125 @@ void BuildLevelList( void )
//=======================================================================
int AddTransitionToList( LEVELLIST *pLevelList, int listCount, const char *pMapName, const char *pLandmarkName, edict_t *pentLandmark )
{
int i;
int i;
if ( !pLevelList || !pMapName || !pLandmarkName || !pentLandmark ) return 0;
if( !pLevelList || !pMapName ) return 0;
for ( i = 0; i < listCount; i++ )
for( i = 0; i < listCount; i++ )
{
if ( pLevelList[i].pentLandmark == pentLandmark && !strcmp( pLevelList[i].mapName, pMapName ))
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;
}
int BuildChangeList( LEVELLIST *pLevelList, int maxList )
{
edict_t *pentLandmark;
int i, count;
edict_t *pentLandmark;
int i, count;
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 )
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" );
}
if ( gpGlobals->pSaveData && ((SAVERESTOREDATA *)gpGlobals->pSaveData)->pTable )
if( gpGlobals->pSaveData && ((SAVERESTOREDATA *)gpGlobals->pSaveData)->pTable )
{
CSave saveHelper( (SAVERESTOREDATA *)gpGlobals->pSaveData );
for ( i = 0; i < count; i++ )
{
int j, entityCount = 0;
CBaseEntity *pEntList[ MAX_TRANSITION_ENTITY ];
int entityFlags[ MAX_TRANSITION_ENTITY ];
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 );
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 ) )
while ( !FNullEnt( pent ))
{
CBaseEntity *pEntity = CBaseEntity::Instance(pent);
if ( pEntity )
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 )
if(!( caps & FCAP_DONT_SAVE ))
{
int flags = 0;
if( caps & FCAP_ACROSS_TRANSITION ) flags |= FENTTABLE_MOVEABLE;
if( pEntity->pev->globalname && !pEntity->IsDormant() ) flags |= FENTTABLE_GLOBAL;
if( flags )
{
pEntList[ entityCount ] = pEntity;
entityFlags[ entityCount ] = flags;
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 ) )
if( entityFlags[j] && UTIL_FindTransition( pEntList[j], pLevelList[i].landmarkName ))
{
// Mark entity table with 1<<i
int index = saveHelper.EntityIndex( pEntList[j] );
// Flag it with the level number
saveHelper.EntityFlagsSet( index, entityFlags[j] | (1<<i) );
saveHelper.EntityFlagsSet( index, entityFlags[j]|( 1<<i ));
}
}
}
@ -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

View File

@ -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:

View File

@ -571,38 +571,42 @@ void UTIL_FindHullIntersection( const Vector &vecSrc, TraceResult &tr, float *mi
edict_t *UTIL_FindLandmark( string_t iLandmarkName )
{
return UTIL_FindLandmark( STRING( iLandmarkName));
return UTIL_FindLandmark( STRING( iLandmarkName ));
}
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 )
while( pLandmark )
{
// Found the landmark
if ( FClassnameIs( pLandmark->pev, "info_landmark" ) )
return ENT(pLandmark->pev);
else pLandmark = UTIL_FindEntityByTargetname( pLandmark, pLandmarkName );
if( FClassnameIs( pLandmark->pev, "info_landmark" ))
return ENT( pLandmark->pev );
else pLandmark = UTIL_FindEntityByTargetname( pLandmark, pLandmarkName );
}
Msg("ERROR: Can't find landmark %s\n", 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( pEntity->ObjectCaps() & FCAP_FORCE_TRANSITION ) return 1;
// 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)
// 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 );
}
@ -610,19 +614,50 @@ int UTIL_FindTransition( CBaseEntity *pEntity, char *pVolumeName )
int inVolume = 1; // Unless we find a trigger_transition, everything is in the volume
pVolume = UTIL_FindEntityByTargetname( NULL, pVolumeName );
while ( pVolume )
while( pVolume )
{
if ( FClassnameIs( pVolume->pev, "trigger_transition" ) )
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,10 +665,10 @@ 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) )
if( pEntityEdict && !pEntityEdict->free && !FStringNull( pEntityEdict->v.globalname ))
{
pEntity = CBaseEntity::Instance( pEntityEdict );
}
@ -647,53 +682,49 @@ 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, ""));
ASSERT( !FStrEq( szNextMap, "" ));
// Don't work in deathmatch
if ( IsMultiplayer()) return;
// Some people are firing these multiple times in a frame, disable
if ( NewLevel ) return;
// don't work in deathmatch
if( IsMultiplayer()) return;
// 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
strcpy(st_szNextMap, szNextMap);
st_szNextSpot[0] = 0; // Init landmark to NULL
// 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
// look for a landmark entity
pentLandmark = UTIL_FindLandmark( szNextSpot );
if ( !FNullEnt( pentLandmark ) )
if( !FNullEnt( pentLandmark ))
{
strcpy(st_szNextSpot, szNextSpot);
gpGlobals->spotOffset = VARS(pentLandmark)->origin;
strcpy( st_szNextSpot, 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
}
//========================================================================
@ -1893,7 +1924,7 @@ CBaseEntity *UTIL_FindEntityGeneric( const char *szWhatever, Vector &vecSrc, flo
// returns a CBaseEntity pointer to a player by index. Only returns if the player is spawned and connected
// otherwise returns NULL
// Index is 1 based
CBaseEntity *UTIL_PlayerByIndex( int playerIndex )
CBaseEntity *UTIL_PlayerByIndex( int playerIndex )
{
CBaseEntity *pPlayer = NULL;

View File

@ -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,8 +336,9 @@ 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);
#define UTIL_EntitiesInPVS( pent ) (*g_engfuncs.pfnEntitiesInPVS)(pent)
extern void UTIL_MakeVectors( const Vector &vecAngles );
// Pass in an array of pointers and an array size, it fills the array and returns the number inserted
extern int UTIL_MonstersInSphere( CBaseEntity **pList, int listMax, const Vector &center, float radius );
@ -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);

View File

@ -3426,15 +3426,16 @@ 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->origin = VARS( pentSpawnSpot )->origin + Vector( 0, 0, 1 );
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
// Copied from spawn() for now
m_bloodColor = BLOOD_COLOR_RED;
m_bloodColor = BLOOD_COLOR_RED;
g_ulModelIndexPlayer = pev->modelindex;
@ -3442,11 +3443,11 @@ int CBasePlayer::Restore( CRestore &restore )
{
// Use the crouch HACK
FixPlayerCrouchStuck( edict() );
UTIL_SetSize(pev, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX);
UTIL_SetSize( pev, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX );
}
else
{
UTIL_SetSize(pev, VEC_HULL_MIN, VEC_HULL_MAX);
UTIL_SetSize( pev, VEC_HULL_MIN, VEC_HULL_MAX );
}
RenewItems();

View File

@ -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.

View File

@ -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

View File

@ -583,8 +583,8 @@ void S_Update( int clientnum, const vec3_t position, const vec3_t velocity, cons
al_state.clientnum = clientnum;
// set up listener
VectorSet( s_listener.position, position[1], position[2], -position[0]);
VectorSet( s_listener.velocity, velocity[1], velocity[2], -velocity[0]);
VectorSet( s_listener.position, position[1], position[2], -position[0] );
VectorSet( s_listener.velocity, velocity[1], velocity[2], -velocity[0] );
// set listener orientation matrix
s_listener.orientation[0] = at[1];