From d1536f0baba0ba43df8d8ca3efc02370ed8693e3 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 30 Oct 2016 12:28:40 +0200 Subject: [PATCH] Fix some crashes, fix skipping CoopApplyData sometimes, game pausing --- dlls/cbase.cpp | 15 ++++ dlls/client.cpp | 12 +-- dlls/doors.cpp | 2 + dlls/game.h | 1 + dlls/gamerules.cpp | 22 +++-- dlls/multiplay_gamerules.cpp | 10 ++- dlls/plats.cpp | 1 + dlls/player.cpp | 2 +- dlls/triggers.cpp | 157 +++++++++++++++++++++++++++-------- 9 files changed, 173 insertions(+), 49 deletions(-) diff --git a/dlls/cbase.cpp b/dlls/cbase.cpp index 62b4eaa1..e9200681 100644 --- a/dlls/cbase.cpp +++ b/dlls/cbase.cpp @@ -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 ); diff --git a/dlls/client.cpp b/dlls/client.cpp index 178b6b91..b67f2ab3 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -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 ) diff --git a/dlls/doors.cpp b/dlls/doors.cpp index 23d96517..341d139a 100644 --- a/dlls/doors.cpp +++ b/dlls/doors.cpp @@ -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 ) diff --git a/dlls/game.h b/dlls/game.h index 80459a60..18b07deb 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -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; diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index d0fc4130..aeb652f8 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -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; + } } diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index 2aa198a2..e3ccd6a9 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -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; } diff --git a/dlls/plats.cpp b/dlls/plats.cpp index 8b1d6588..606aac8c 100644 --- a/dlls/plats.cpp +++ b/dlls/plats.cpp @@ -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 { diff --git a/dlls/player.cpp b/dlls/player.cpp index 2a508511..bffc3647 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -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 diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index f58072a0..1ad049ab 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -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 ) ) - { - ALERT( at_console, "Player isn't in the transition volume %s, aborting\n", m_szLandmarkName ); - return; - }*/ + CBaseEntity *pPlayer = NULL; + if( pActivator && pActivator->IsPlayer() ) + pPlayer = pActivator; - // Create an entity to fire the changetarget - if( m_changeTarget && pPlayer ) + if( !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; + int count = 0; + for( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBaseEntity *plr = UTIL_PlayerByIndex( i ); - // Call spawn - DispatchSpawn( pFireAndDie->edict() ); + 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; + + }*/ + // 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 ) );