Fix some crashes, fix skipping CoopApplyData sometimes, game pausing

This commit is contained in:
mittorn 2016-10-30 12:28:40 +02:00
parent ab9523769a
commit d1536f0bab
9 changed files with 173 additions and 49 deletions

View File

@ -207,6 +207,9 @@ BOOL gTouchDisabled = FALSE;
void DispatchTouch( edict_t *pentTouched, edict_t *pentOther )
{
if( g_fPause )
return;
if( gTouchDisabled )
return;
@ -219,6 +222,9 @@ void DispatchTouch( edict_t *pentTouched, edict_t *pentOther )
void DispatchUse( edict_t *pentUsed, edict_t *pentOther )
{
if( g_fPause )
return;
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE( pentUsed );
CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE( pentOther );
@ -228,6 +234,12 @@ void DispatchUse( edict_t *pentUsed, edict_t *pentOther )
void DispatchThink( edict_t *pent )
{
if( g_fPause )
{
pent->v.nextthink = gpGlobals->time;
return;
}
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE( pent );
if( pEntity )
{
@ -240,6 +252,9 @@ void DispatchThink( edict_t *pent )
void DispatchBlocked( edict_t *pentBlocked, edict_t *pentOther )
{
if( g_fPause )
return;
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE( pentBlocked );
CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE( pentOther );

View File

@ -652,6 +652,10 @@ void ServerDeactivate( void )
//
}
void CoopClearData( void );
void CoopApplyData( void );
void CoopClearWeaponList( void );
void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
{
int i;
@ -688,6 +692,7 @@ void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
LinkUserMessages();
if( mp_coop.value )
{
CoopApplyData();
for( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer *plr = (CBasePlayer*)UTIL_PlayerByIndex( i );
@ -744,9 +749,6 @@ void PlayerPostThink( edict_t *pEntity )
pPlayer->PostThink( );
}
void CoopClearData( void );
void CoopApplyData( void );
void CoopClearWeaponList( void );
void ParmsNewLevel( void )
{
// retrieve the pointer to the save data
@ -755,7 +757,7 @@ void ParmsNewLevel( void )
if ( pSaveData )
{
pSaveData->connectionCount = BuildChangeList( pSaveData->levelList, MAX_LEVEL_CONNECTIONS );
CoopApplyData();
//CoopApplyData();
}
else
if( mp_coop_changelevel.value )
@ -775,7 +777,7 @@ void ParmsChangeLevel( void )
if ( pSaveData )
{
pSaveData->connectionCount = BuildChangeList( pSaveData->levelList, MAX_LEVEL_CONNECTIONS );
CoopApplyData();
//CoopApplyData();
}
else
if( mp_coop_changelevel.value )

View File

@ -103,6 +103,8 @@ TYPEDESCRIPTION CBaseDoor::m_SaveData[] =
DEFINE_FIELD( CBaseDoor, m_bLockedSentence, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_bUnlockedSound, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_bUnlockedSentence, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_fActivated, FIELD_CHARACTER ),
DEFINE_FIELD( CBaseDoor, m_savedtarget, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CBaseDoor, CBaseToggle )

View File

@ -56,6 +56,7 @@ extern cvar_t mp_unduck;
extern cvar_t mp_semclip;
extern cvar_t mp_coop_reconnect_hack;
extern bool g_fSavedDuck;
extern bool g_fPause;
// Engine Cvars
extern cvar_t *g_psv_gravity;

View File

@ -87,8 +87,13 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer )
if( pPlayer->m_state == STATE_POINT_SELECT )
{
pPlayer->m_state = STATE_SPAWNED;
if(pPlayer->pev->origin.Length() > 8192)
pPlayer->pev->origin = g_vecZero;
pPlayer->pev->effects &= ~EF_NODRAW;
pPlayer->pev->takedamage = DAMAGE_YES;
pPlayer->pev->flags &= ~FL_SPECTATOR;
pPlayer->pev->movetype = MOVETYPE_WALK;
CLIENT_COMMAND( pPlayer->edict(), "touch_show _coopm*\n" );
return NULL;
}
@ -105,20 +110,25 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer )
if( mp_coop_changelevel.value && !CoopRestorePlayerCoords( pPlayer, &pPlayer->pev->origin, &pPlayer->pev->angles ))
if( !CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles ) )
{
if( pPlayer->m_state == STATE_SPAWNED && !g_pLastSpawn )
if( !g_pLastSpawn )
{
hudtextparms_t params = {};
params.fadeinTime = 0.5;
params.fadeoutTime = .5;
params.holdTime = 10;
params.channel = 1;
params.y = 100;
params.channel = 0;
params.y = 0;
params.r2 = params.g2 = params.b2 = params.a2 = params.r1 = params.g1 = params.b1 = params.a1 = 255;
UTIL_HudMessage( pPlayer, params, "Server cannot select a spawnpoint, please fly to it manually and press attack button\n" );
UTIL_HudMessage( pPlayer, params, "Server cannot select a spawnpoint, please fly to it manually and press attack button" );
// select spawn point
pPlayer->m_state = STATE_POINT_SELECT;
pPlayer->m_afButtonPressed = 0;
if(pPlayer->pev->origin.Length() > 8192)
pPlayer->pev->origin = g_vecZero;
}
}

View File

@ -752,7 +752,7 @@ void CHalfLifeMultiplay::PlayerThink( CBasePlayer *pPlayer )
if( pPlayer->m_state == STATE_POINT_SELECT )
{
if( pPlayer->m_afButtonPressed & ( IN_DUCK | IN_ATTACK | IN_ATTACK2 | IN_USE | IN_JUMP ) )
SpawnPlayer( pPlayer );
pPlayer->Spawn();
}
if( g_fGameOver )
@ -789,13 +789,15 @@ void CHalfLifeMultiplay::PlayerSpawn( CBasePlayer *pPlayer )
return;
}
if( pPlayer->m_state == STATE_POINT_SELECT )
if( pPlayer->m_state == STATE_POINT_SELECT && !(pPlayer->pev->flags & FL_SPECTATOR) )
{
pPlayer->RemoveAllItems( TRUE );
BecomeSpectator( pPlayer );
return;
}
g_fPause = false;
pPlayer->pev->weapons |= ( 1 << WEAPON_SUIT );
addDefault = TRUE;
@ -1355,10 +1357,12 @@ int CHalfLifeMultiplay::DeadPlayerAmmo( CBasePlayer *pPlayer )
edict_t *CHalfLifeMultiplay::GetPlayerSpawnSpot( CBasePlayer *pPlayer )
{
edict_t *pentSpawnSpot = CGameRules::GetPlayerSpawnSpot( pPlayer );
if( IsMultiplayer() && pentSpawnSpot->v.target )
if( IsMultiplayer() && pentSpawnSpot && pentSpawnSpot->v.target )
{
FireTargets( STRING( pentSpawnSpot->v.target ), pPlayer, pPlayer, USE_TOGGLE, 0 );
}
if( !pentSpawnSpot )
ALERT( at_console, "GetPlayerSpawnSpot: pentSpawnSpot is NULL\n" );
return pentSpawnSpot;
}

View File

@ -760,6 +760,7 @@ void CFuncTrain::Next( void )
SetBits(pev->effects, EF_NOINTERP);
UTIL_SetOrigin(pev, pTarg->pev->origin - (pev->mins + pev->maxs)* 0.5);
Wait(); // Get on with doing the next path corner.
pev->iuser1++; // Invalidate state for coop
}
else
{

View File

@ -1544,7 +1544,7 @@ void FixPlayerCrouchStuck( edict_t *pPlayer )
// Move up as many as 18 pixels if the player is stuck.
for( int i = 0; i < 18; i++ )
{
UTIL_TraceHull( pPlayer->v.origin, pPlayer->v.origin, missile, head_hull, pPlayer, &trace );
UTIL_TraceHull( pPlayer->v.origin, pPlayer->v.origin, ignore_monsters, head_hull, pPlayer, &trace );
if( trace.fStartSolid )
pPlayer->v.origin.z++;
else

View File

@ -1297,18 +1297,21 @@ LINK_ENTITY_TO_CLASS( fireanddie, CFireAndDie )
void CFireAndDie::Spawn( void )
{
ALERT( at_console, "fireanddie: spawn!\n");
pev->classname = MAKE_STRING( "fireanddie" );
// Don't call Precache() - it should be called on restore
}
void CFireAndDie::Precache( void )
{
ALERT( at_console, "fireanddie: precache!\n");
// This gets called on restore
pev->nextthink = gpGlobals->time + m_flDelay;
}
void CFireAndDie::Think( void )
{
ALERT( at_console, "fireanddie: firing!\n");
SUB_UseTargets( this, USE_TOGGLE, 0 );
UTIL_Remove( this );
}
@ -1495,6 +1498,8 @@ struct SavedCoords
bool trainsaved;
Vector trainoffset;
char trainglobal[256];
int trainuser1;
bool fUsed;
} g_SavedCoords, s_SavedCoords;
@ -1506,13 +1511,16 @@ void CoopClearData( void )
g_SavedCoords = l_SavedCoords;
}
bool g_fPause;
void CoopApplyData( void )
{
if( s_SavedCoords.valid )
{
g_SavedCoords = s_SavedCoords;
s_SavedCoords = {};
g_fPause = false;
}
ALERT( at_console, "^2CoopApplyData()\n" );
}
int g_iMenu;
@ -1787,10 +1795,11 @@ bool CoopGetSpawnPoint( Vector *origin, Vector *angles)
{
CBaseEntity *train = UTIL_FindEntityByString( NULL, "globalname", g_SavedCoords.trainglobal );
if( !train ) train = UTIL_FindEntityByString( NULL, "classname", g_SavedCoords.trainglobal );
if( train )
if( train && ( !g_SavedCoords.trainuser1 || train->pev->iuser1 == g_SavedCoords.trainuser1 ) )
{
*angles = g_SavedCoords.triggerangles;
*origin = VecBModelOrigin(train->pev) + g_SavedCoords.trainoffset;
g_SavedCoords.trainuser1 = train->pev->iuser1;
return true;
}
ALERT( at_console, "Failed to get train %s (map design error?)\n", g_SavedCoords.trainglobal );
@ -1806,22 +1815,24 @@ bool CoopGetSpawnPoint( Vector *origin, Vector *angles)
point = point + g_SavedCoords.offset;
//UTIL_TraceHull( point, point, ignore_monsters, human_hull, NULL, &tr );
if( mp_unduck.value )
if( mp_unduck.value && g_fSavedDuck && !g_SavedCoords.fUsed )
UTIL_TraceHull( point, point + angle * 100, missile, head_hull, NULL, &tr );
else
UTIL_TraceHull( point, point + angle * 100, missile, human_hull, NULL, &tr );
if( !tr.fStartSolid && !tr.fAllSolid )
{
g_SavedCoords.triggerorigin = tr.vecEndPos;
g_SavedCoords.validspawnpoint = true;
//g_SavedCoords.triggerorigin = tr.vecEndPos;
//g_SavedCoords.validspawnpoint = true;
if( tr.pHit && FClassnameIs( tr.pHit, "func_door" ) )
tr.pHit->v.solid = SOLID_NOT;
ALERT( at_console, "CoopGetSpawnPoint: ^2offset set\n");
}
else
{
g_SavedCoords.valid = false;
ALERT( at_console, "CoopGetSpawnPoint: trace failed\n");
//g_SavedCoords.valid = false;
ALERT( at_console, "CoopGetSpawnPoint: ^2trace failed\n");
return false;
}
}
@ -1832,11 +1843,24 @@ bool CoopGetSpawnPoint( Vector *origin, Vector *angles)
CBaseEntity *CoopGetPlayerTrain( CBaseEntity *pPlayer)
{
CBaseEntity *train = NULL;
if( !pPlayer)
return NULL;
if( FNullEnt(pPlayer->pev->groundentity))
return NULL;
CBaseEntity *train = CBaseEntity::Instance(pPlayer->pev->groundentity);
if( !pPlayer->IsPlayer() )
{
// activated by path track
train = pPlayer;
}
else
{
if( FNullEnt(pPlayer->pev->groundentity))
return NULL;
train = CBaseEntity::Instance(pPlayer->pev->groundentity);
}
if( !train )
return NULL;
if( !train->pev->globalname ||!STRING(train->pev->globalname) || !STRING(train->pev->globalname)[0] )
@ -1859,7 +1883,24 @@ void CoopSaveTrain( CBaseEntity *pPlayer, SavedCoords *coords)
ALERT( at_console, "^1NO TRAIN!\n");
return;
}
ALERT( at_console, "^1TRAIN IS %s", STRING( train->pev->classname ) );
ALERT( at_console, "^1TRAIN IS %s\n", STRING( train->pev->classname ) );
if( !pPlayer->IsPlayer() )
{
// it is trainnitself, try find player on it
CBaseEntity *pList;
Vector mins = pPlayer->pev->absmin;
Vector maxs = pPlayer->pev->absmax;
maxs.z += 72;
int count = UTIL_EntitiesInBox( &pList, 1, mins, maxs, FL_ONGROUND );
if( count && pList && pList->IsPlayer() )
pPlayer = pList;
else
{
ALERT( at_console, "Train without players\n" );
return;
}
}
strcpy( coords->trainglobal, STRING(train->pev->globalname) );
coords->trainoffset = pPlayer->pev->origin - VecBModelOrigin(train->pev);
@ -1875,6 +1916,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
params.fadeoutTime = .5;
params.holdTime = 10;
params.r2 = params.g2 = params.b2 = params.a2 = params.r1 = params.g1 = params.b1 = params.a1 = 255;
bool valid = false;
ASSERT( !FStrEq( m_szMapName, "" ) );
@ -1957,7 +1999,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
i = 1;
if( i )
UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map, next is %s %s, %d to go\n",
UTIL_HudMessageAll( params, UTIL_VarArgs( "%s touched end of map, next is %s %s, %d to go",
( pActivator->pev->netname && STRING( pActivator->pev->netname )[0] != 0 ) ? STRING( pActivator->pev->netname ) : "unconnected",
st_szNextMap, st_szNextSpot, i ) );
if( count2 )
@ -1974,8 +2016,8 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
if( count1 > 1 && count1 < count2 / 3 )
return;
if( count1 <= 1 && count2 == 2 )
return;
//if( count1 <= 1 && count2 == 2 )
// return;
if( m_fIsBack )
{
@ -1998,7 +2040,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
{
l_SavedCoords.triggerangles = m_vecSpawnAngles;
l_SavedCoords.triggerorigin = m_vecSpawnOrigin;
l_SavedCoords.valid = true;
valid = true;
}
ALERT( at_console, "^2CHANGELEVEL:^7 %d %d %d\n", count2, count1, (int)m_fIsBack);
}
@ -2010,7 +2052,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
{
l_SavedCoords.triggerangles = pActivator->pev->angles;
l_SavedCoords.triggerorigin = pActivator->pev->origin;
l_SavedCoords.valid = true;
valid = true;
g_fSavedDuck = !!(pActivator->pev->flags & FL_DUCKING);
}
@ -2033,28 +2075,47 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
pev->dmgtime = gpGlobals->time;
CBaseEntity *pPlayer = CBaseEntity::Instance( g_engfuncs.pfnPEntityOfEntIndex( 1 ) );
/*if( !InTransitionVolume( pPlayer, m_szLandmarkName ) )
CBaseEntity *pPlayer = NULL;
if( pActivator && pActivator->IsPlayer() )
pPlayer = pActivator;
if( !pPlayer )
{
int count = 0;
for( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if( plr && plr->IsPlayer() )
{
if( InTransitionVolume( plr, m_szLandmarkName ))
{
count++;
}
}
}
if( !count )
{
ALERT( at_console, "There are no players in transition volume %s, aborting\n", m_szLandmarkName );
return;
}
ALERT( at_console, "There are %d players in transition volume %s\n", count, m_szLandmarkName );
}
else if( !InTransitionVolume( pPlayer, m_szLandmarkName ) )
{
ALERT( at_console, "Player isn't in the transition volume %s, aborting\n", m_szLandmarkName );
return;
}
//else
/* if !pPlayer
{
ALERT( at_console, ", aborting\n" );
return;
}*/
// Create an entity to fire the changetarget
if( m_changeTarget && pPlayer )
{
CFireAndDie *pFireAndDie = GetClassPtr( (CFireAndDie *)NULL );
if( pFireAndDie )
{
// Set target and delay
pFireAndDie->pev->target = m_changeTarget;
pFireAndDie->m_flDelay = m_changeTargetDelay;
pFireAndDie->pev->origin = pPlayer->pev->origin;
// Call spawn
DispatchSpawn( pFireAndDie->edict() );
}
}
// shedule remove ke^w on first info_player_start
/*edict_t *playerstart = FIND_ENTITY_BY_CLASSNAME( NULL, "info_player_start" );
@ -2077,6 +2138,25 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
s_SavedCoords.offset = gpGlobals->vecLandmarkOffset = VARS( pentLandmark )->origin;
}
// Create an entity to fire the changetarget
if( m_changeTarget )
{
CFireAndDie *pFireAndDie = GetClassPtr( (CFireAndDie *)NULL );
if( pFireAndDie )
{
// Set target and delay
pFireAndDie->pev->target = m_changeTarget;
pFireAndDie->m_flDelay = m_changeTargetDelay + 1;
if( pPlayer )
pFireAndDie->pev->origin = pPlayer->pev->origin;
else if( !FNullEnt( pentLandmark ) )
pFireAndDie->pev->origin = VARS( pentLandmark )->origin; // always in landmark's PVS
// Call spawn
DispatchSpawn( pFireAndDie->edict() );
}
}
//ALERT( at_console, "Level touches %d levels\n", ChangeList( levels, 16 ) );
ALERT( at_console, "CHANGE LEVEL: %s %s\n", st_szNextMap, st_szNextSpot );
g_iMenu = 0;
@ -2105,6 +2185,9 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator )
//SERVER_EXECUTE();
}
}
g_fPause = true;
s_SavedCoords.fUsed = m_bUsed;
s_SavedCoords.valid = valid;
if( mp_coop_reconnect_hack.value )
SERVER_COMMAND( UTIL_VarArgs( "wait;wait;wait;wait;wait;changelevel %s %s\n", st_szNextMap, st_szNextSpot ) );
else
@ -2166,6 +2249,9 @@ int CChangeLevel::InTransitionVolume( CBaseEntity *pEntity, char *pVolumeName )
pEntity = CBaseEntity::Instance( pEntity->pev->aiment );
}
if( !pEntity )
return 0;
int inVolume = 1; // Unless we find a trigger_transition, everything is in the volume
pentVolume = FIND_ENTITY_BY_TARGETNAME( NULL, pVolumeName );
@ -2262,8 +2348,11 @@ int CChangeLevel::ChangeList( LEVELLIST *pLevelList, int maxList )
pEntList[entityCount] = pEntity;
entityFlags[entityCount] = flags;
entityCount++;
if( entityCount > MAX_ENTITY )
ALERT( at_error, "Too many entities across a transition!" );
if( entityCount >= MAX_ENTITY )
{
ALERT( at_error, "Too many entities across a transition!\n" );
break;
}
}
//else
// ALERT( at_console, "Failed %s\n", STRING( pEntity->pev->classname ) );