diff --git a/dlls/client.cpp b/dlls/client.cpp index 4a4974cb..bc71e6cb 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -818,23 +818,7 @@ void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) // Link user messages here to make sure first client can get them... LinkUserMessages(); - if( mp_coop.value ) - { - COOP_ApplyData(); - for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *plr = (CBasePlayer*)UTIL_PlayerByIndex( i ); - - // reset all players state - if( plr ) - { - plr->gravgunmod_data.m_state = STATE_UNINITIALIZED; - plr->RemoveAllItems( TRUE ); - UTIL_BecomeSpectator( plr ); - //plr->Spawn(); - } - } - } + GGM_ServerActivate(); } diff --git a/dlls/coop.cpp b/dlls/coop.cpp index 49d03992..502745cd 100644 --- a/dlls/coop.cpp +++ b/dlls/coop.cpp @@ -753,7 +753,6 @@ bool COOP_ClientCommand( edict_t *pEntity ) else { pPlayer->RemoveAllItems( TRUE ); - pPlayer->gravgunmod_data.m_state = STATE_SPAWNED; UTIL_SpawnPlayer( pPlayer ); } return true; diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index bb833f62..2234fbec 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -88,7 +88,7 @@ edict_t *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) pPlayer->pev->angles = VARS( pentSpawnSpot )->angles; pPlayer->pev->punchangle = g_vecZero; if( !(pPlayer->pev->flags & FL_SPECTATOR ) ) - if( mp_coop_changelevel.value && !UTIL_CoopRestorePlayerCoords( pPlayer, &pPlayer->pev->origin, &pPlayer->pev->angles )) + if( mp_coop_changelevel.value ) if( !UTIL_CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles ) ) { if( !g_pLastSpawn ) diff --git a/dlls/gravgunmod.cpp b/dlls/gravgunmod.cpp index b6f461c1..6c611516 100644 --- a/dlls/gravgunmod.cpp +++ b/dlls/gravgunmod.cpp @@ -854,6 +854,100 @@ struct GGMPlayerState *GGM_GetState( const char *uid, const char *name ) return anonymous_list = pState; } + +GGMMapOffset *g_pMapOffsets; +GGMLandmarkTransition g_landmarkTransition; +edict_t *COOP_FindLandmark( const char *pLandmarkName ); +bool COOP_ProcessTransition( void ) +{ + bool fAddCurrent = true; + edict_t *landmark; + + if( !mp_coop.value ) + return false; + + if( !g_landmarkTransition.landmarkName[0] ) + return false; + + if( strcmp( g_landmarkTransition.targetMap, STRING(gpGlobals->mapname) ) ) + return false; + landmark = COOP_FindLandmark( g_landmarkTransition.landmarkName ); + if( !landmark ) + return false; + Vector &lm = landmark->v.origin; + + for( GGMMapOffset *pOffset = g_pMapOffsets; pOffset; pOffset = pOffset->pNext ) + { + if( !strcmp( pOffset->mapName, STRING(gpGlobals->mapname) ) ) + { + pOffset->vecOffset = Vector( 0, 0, 0 ); + fAddCurrent = false; + continue; + } + pOffset->vecOffset = pOffset->vecOffset - g_landmarkTransition.vecLandmark + lm; + } + + if( fAddCurrent ) + { + GGMMapOffset *pNewOffset = (GGMMapOffset *)calloc(1, sizeof( struct GGMMapOffset ) ); + + pNewOffset->pNext = g_pMapOffsets; + pNewOffset->vecOffset = Vector(0, 0, 0); + strncpy(pNewOffset->mapName, STRING(gpGlobals->mapname), 31); + g_pMapOffsets = pNewOffset; + } + return true; +} + +void COOP_SetupLandmarkTransition( const char *szNextMap, const char *szNextSpot, Vector vecLandmarkOffset ) +{ + strncpy(g_landmarkTransition.sourceMap, STRING(gpGlobals->mapname), 31 ); + strncpy(g_landmarkTransition.targetMap, szNextMap, 31 ); + strncpy(g_landmarkTransition.landmarkName, szNextSpot, 31 ); + g_landmarkTransition.vecLandmark = vecLandmarkOffset; +} +void GGM_ServerActivate( void ) +{ + if( !COOP_ProcessTransition() ) + { + ALERT( at_console, "Transition failed, new game started\n"); + while( g_pMapOffsets ) + { + GGMMapOffset *pOffset = g_pMapOffsets; + g_pMapOffsets = pOffset->pNext; + free( pOffset ); + } + GGMMapOffset *pNewOffset = (GGMMapOffset *)calloc(1, sizeof( struct GGMMapOffset ) ); + + pNewOffset->pNext = g_pMapOffsets; + pNewOffset->vecOffset = Vector(0, 0, 0); + strncpy(pNewOffset->mapName, STRING(gpGlobals->mapname), 31); + g_pMapOffsets = pNewOffset; + if( mp_coop.value ) + COOP_ClearData(); + } + else if( mp_coop.value ) COOP_ApplyData(); + + + if( mp_coop.value ) + { + for( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *plr = (CBasePlayer*)UTIL_PlayerByIndex( i ); + + // reset all players state + if( plr ) + { + plr->gravgunmod_data.m_state = STATE_UNINITIALIZED; + plr->RemoveAllItems( TRUE ); + UTIL_BecomeSpectator( plr ); + //plr->Spawn(); + } + } + } + g_landmarkTransition.landmarkName[0] = false; +} + void GGM_SaveState( CBasePlayer *pPlayer ) { if( !pPlayer ) @@ -877,6 +971,19 @@ void GGM_SaveState( CBasePlayer *pPlayer ) pState->t.pos.vecAngles = pPlayer->pev->angles; pState->t.pos.fDuck = !!(pPlayer->pev->flags & FL_DUCKING); strncpy( pState->t.pos.mapName, STRING(gpGlobals->mapname), 31 ); + CBaseEntity *pTrain = UTIL_CoopGetPlayerTrain(pPlayer); + if( pTrain ) + { + strcpy( pState->t.pos.trainGlobal, STRING( pTrain->pev->globalname ) ); + if( pTrain->pev->angles == g_vecZero ) + pState->t.pos.vecTrainOffset = pPlayer->pev->origin - VecBModelOrigin(pTrain->pev); + else + pState->t.pos.vecTrainOffset = pPlayer->pev->origin - pTrain->pev->origin; + + pState->t.pos.vecTrainAngles = pTrain->pev->angles; + } + else pState->t.pos.trainGlobal[0] = 0; + pState->t.flHealth = pPlayer->pev->health; pState->t.flBattery = pPlayer->pev->armorvalue; @@ -903,11 +1010,11 @@ void GGM_SaveState( CBasePlayer *pPlayer ) if( pState->fNeedWrite ) GGM_WritePersist( pState ); } - bool GGM_RestoreState(CBasePlayer *pPlayer) { GGMPlayerState *pState = pPlayer->gravgunmod_data.pState; int i; + bool fOriginSet = false; if( !pState ) return false; @@ -920,7 +1027,51 @@ bool GGM_RestoreState(CBasePlayer *pPlayer) return false; pPlayer->pev->armorvalue = pState->t.flBattery; pPlayer->pev->health = pState->t.flHealth; - pPlayer->pev->origin = pState->t.pos.vecOrigin; + + //pPlayer->pev->origin = pState->t.pos.vecOrigin; + for( GGMMapOffset *offset = g_pMapOffsets; offset; offset = offset->pNext ) + { + if( !strcmp( offset->mapName, pState->t.pos.mapName ) ) + { + pPlayer->pev->origin = pState->t.pos.vecOrigin + offset->vecOffset; + fOriginSet = true; + break; + } + } + + if( pState->t.pos.trainGlobal[0] ) + { + CBaseEntity *pTrain = UTIL_FindEntityByString( NULL, "globalname", pState->t.pos.trainGlobal ); + if( pTrain ) + { + Vector vecTrainOrigin; + if( pState->t.pos.vecTrainAngles == g_vecZero ) + vecTrainOrigin = VecBModelOrigin( pTrain->pev ); + else + vecTrainOrigin = pTrain->pev->origin; + + Vector angleDiff = pTrain->pev->angles - pState->t.pos.vecAngles; + if( angleDiff != g_vecZero ) + { + float length = pState->t.pos.vecTrainOffset.Length(); + Vector newAngles = UTIL_VecToAngles( pState->t.pos.vecTrainOffset) + angleDiff; + //newAngles[0] = -newAngles[0]; + Vector newOffset; + UTIL_MakeVectorsPrivate( newAngles, newOffset, NULL, NULL ); + pPlayer->pev->origin = vecTrainOrigin - newOffset * length; + } + else + pPlayer->pev->origin = vecTrainOrigin + pState->t.pos.vecTrainOffset; + fOriginSet = true; + } + } + if( mp_coop.value && !fOriginSet ) + { + g_pGameRules->GetPlayerSpawnSpot( pPlayer ); + if( pPlayer->gravgunmod_data.m_state = STATE_POINT_SELECT ) + return false; + } + if( pState->t.pos.fDuck ) { pPlayer->pev->view_ofs.z = 12; @@ -987,7 +1138,45 @@ bool GGM_PlayerSpawn( CBasePlayer *pPlayer ) if( pPlayer->pev->flags & FL_SPECTATOR ) return true; - if( !mp_coop_changelevel.value ) + if( mp_coop_changelevel.value ) + { + if( pPlayer->gravgunmod_data.m_state != STATE_SPAWNED ) + { + pPlayer->gravgunmod_data.m_state = STATE_SPAWNED; + g_fPause = false; + if( GGM_RestoreState( pPlayer ) ) + { + pPlayer->pev->weapons |= (1 << WEAPON_SUIT); + return true; + } + else + { + /*edict_t *pentSpawnSpot = EntSelectSpawnPoint( pPlayer ); + pPlayer->pev->origin = VARS( pentSpawnSpot )->origin + Vector( 0, 0, 1 ); + pPlayer->pev->v_angle = g_vecZero; + pPlayer->pev->velocity = g_vecZero; + pPlayer->pev->angles = VARS( pentSpawnSpot )->angles; + pPlayer->pev->punchangle = g_vecZero; + pPlayer->pev->fixangle = TRUE; + if( !(pPlayer->pev->flags & FL_SPECTATOR ) ) + if( !UTIL_CoopGetSpawnPoint( &pPlayer->pev->origin, &pPlayer->pev->angles ) ) + { + ClientPrint( pPlayer->pev, HUD_PRINTCENTER, "Server cannot select a spawnpoint\nplease fly to it manually\nand press attack button"); + pPlayer->m_afButtonPressed = 0; + if(pPlayer->pev->origin.Length() > 8192) + pPlayer->pev->origin = g_vecZero; + pPlayer->gravgunmod_data.m_state = STATE_POINT_SELECT; + pPlayer->m_afButtonPressed = 0; + }*/ + } + } + else + { + + } + g_pGameRules->GetPlayerSpawnSpot( pPlayer ); + } + else { if( pPlayer->gravgunmod_data.m_state != STATE_SPAWNED ) { diff --git a/dlls/gravgunmod.h b/dlls/gravgunmod.h index 7f66ad22..1bbe1ff0 100644 --- a/dlls/gravgunmod.h +++ b/dlls/gravgunmod.h @@ -116,6 +116,7 @@ struct GGMLandmarkTransition { char sourceMap[32]; char targetMap[32]; + char landmarkName[32]; Vector vecLandmark; }; @@ -198,5 +199,7 @@ bool GGM_RestoreState( CBasePlayer *pPlayer ); void GGM_SaveState( CBasePlayer *pPlayer ); bool GGM_PlayerSpawn( CBasePlayer *pPlayer ); const char *GGM_GetAuthID( CBasePlayer *pPlayer ); +void GGM_ServerActivate( void ); +void COOP_SetupLandmarkTransition( const char *szNextMap, const char *szNextSpot, Vector vecLandmarkOffset ); #endif // GRAVGUNMOD_H diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index b90d0d6c..63a8acfd 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -1164,7 +1164,7 @@ int CHalfLifeMultiplay::DeadPlayerAmmo( CBasePlayer *pPlayer ) edict_t *CHalfLifeMultiplay::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) { - edict_t *pentSpawnSpot = CGameRules::GetPlayerSpawnSpot( pPlayer ); + edict_t *pentSpawnSpot = CGameRules::GetPlayerSpawnSpot( pPlayer ); if( IsMultiplayer() && pentSpawnSpot && pentSpawnSpot->v.target ) { FireTargets( STRING( pentSpawnSpot->v.target ), pPlayer, pPlayer, USE_TOGGLE, 0 ); diff --git a/dlls/plats.cpp b/dlls/plats.cpp index f30a1a68..25b8f215 100644 --- a/dlls/plats.cpp +++ b/dlls/plats.cpp @@ -1150,7 +1150,7 @@ void CFuncTrackTrain::Next( void ) int count = UTIL_EntitiesInBox( &pList, 1, mins, maxs, FL_ONGROUND ); if( !count || !pList->IsPlayer() ) { - pev->velocity = g_vecZero; + pev->velocity = pev->avelocity = g_vecZero; NextThink( pev->ltime + time, TRUE ); return; } diff --git a/dlls/player.cpp b/dlls/player.cpp index 310c5800..0f1c6b26 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -2945,7 +2945,7 @@ void CBasePlayer::Spawn( void ) m_flFallVelocity = 0; g_pGameRules->SetDefaultPlayerTeam( this ); - g_pGameRules->GetPlayerSpawnSpot( this ); + if( !mp_coop.value )g_pGameRules->GetPlayerSpawnSpot( this ); SET_MODEL( ENT( pev ), "models/player.mdl" ); g_ulModelIndexPlayer = pev->modelindex; diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index 573cc0a0..de3b3171 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -1791,6 +1791,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) // reset all players state to make it spawn again after restart if( plr ) { + GGM_SaveState( plr ); plr->gravgunmod_data.m_state = STATE_UNINITIALIZED; plr->RemoveAllItems( TRUE ); UTIL_BecomeSpectator( plr ); @@ -1803,6 +1804,7 @@ void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) } s_SavedCoords.fUsed = m_bUsed; s_SavedCoords.valid = valid; + COOP_SetupLandmarkTransition( st_szNextMap, st_szNextSpot, gpGlobals->vecLandmarkOffset ); // wait 5 frames to make sure all players are in reconnected state if( mp_coop_reconnect_hack.value )