From 4e4019395ae4fb9d44d899f57edb2ac83612fd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ABBielBdeLuna=C2=BB?= <«7318.tk@gmail.com»> Date: Fri, 21 Jun 2024 16:14:18 +0200 Subject: [PATCH 1/3] 3 types of portal skies --- game/Game_local.cpp | 103 +++++++++++++++++++++++++++++++++++++++ game/Game_local.h | 23 +++++++++ game/Game_network.cpp | 24 +++++++++ game/Item.cpp | 36 ++++++++++++++ game/Misc.cpp | 89 +++++++++++++++++++++++++++++++++ game/Misc.h | 19 ++++++++ game/Player.cpp | 8 +++ game/PlayerView.cpp | 75 ++++++++++++++++++++++++++++ game/Pvs.cpp | 48 ++++++++++++++++++ game/Pvs.h | 2 + game/gamesys/SysCvar.cpp | 2 + game/gamesys/SysCvar.h | 2 + 12 files changed, 431 insertions(+) diff --git a/game/Game_local.cpp b/game/Game_local.cpp index a2cefa6a..5fcb1b61 100644 --- a/game/Game_local.cpp +++ b/game/Game_local.cpp @@ -254,6 +254,11 @@ void idGameLocal::Clear( void ) { savedEventQueue.Init(); memset( lagometer, 0, sizeof( lagometer ) ); + + portalSkyEnt = NULL; + portalSkyActive = false; + playerOldEyePos.Zero(); + globalPortalSky = false; } /* @@ -547,6 +552,14 @@ void idGameLocal::SaveGame( idFile *f ) { savegame.WriteBool( isNewFrame ); savegame.WriteFloat( clientSmoothing ); + portalSkyEnt.Save( &savegame ); + savegame.WriteBool( portalSkyActive ); + savegame.WriteBool( globalPortalSky ); + savegame.WriteInt( currentPortalSkyType ); + savegame.WriteVec3( playerOldEyePos ); + savegame.WriteVec3( portalSkyGlobalOrigin ); + savegame.WriteVec3( portalSkyOrigin ); + savegame.WriteBool( mapCycleLoaded ); savegame.WriteInt( spawnCount ); @@ -917,6 +930,11 @@ void idGameLocal::LoadMap( const char *mapName, int randseed ) { sessionCommand = ""; nextGibTime = 0; + portalSkyEnt = NULL; + portalSkyActive = false; + playerOldEyePos.Zero(); + globalPortalSky = false; + vacuumAreaNum = -1; // if an info_vacuum is spawned, it will set this if ( !editEntities ) { @@ -1394,6 +1412,14 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo savegame.ReadBool( isNewFrame ); savegame.ReadFloat( clientSmoothing ); + portalSkyEnt.Restore( &savegame ); + savegame.ReadBool( portalSkyActive ); + savegame.ReadBool( globalPortalSky ); + savegame.ReadInt( currentPortalSkyType ); + savegame.ReadVec3( playerOldEyePos ); + savegame.ReadVec3( portalSkyGlobalOrigin ); + savegame.ReadVec3( portalSkyOrigin ); + savegame.ReadBool( mapCycleLoaded ); savegame.ReadInt( spawnCount ); @@ -2040,6 +2066,23 @@ void idGameLocal::SetupPlayerPVS( void ) { pvs.FreeCurrentPVS( otherPVS ); playerConnectedAreas = newPVS; } + + // if portalSky is preset, then merge into pvs so we get rotating brushes, etc + if ( portalSkyEnt.GetEntity() ) { + idEntity *skyEnt = portalSkyEnt.GetEntity(); + + otherPVS = pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() ); + newPVS = pvs.MergeCurrentPVS( playerPVS, otherPVS ); + pvs.FreeCurrentPVS( playerPVS ); + pvs.FreeCurrentPVS( otherPVS ); + playerPVS = newPVS; + + otherPVS = pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() ); + newPVS = pvs.MergeCurrentPVS( playerConnectedAreas, otherPVS ); + pvs.FreeCurrentPVS( playerConnectedAreas ); + pvs.FreeCurrentPVS( otherPVS ); + playerConnectedAreas = newPVS; + } } } @@ -4316,6 +4359,66 @@ void idGameLocal::ThrottleUserInfo( void ) { mpGame.ThrottleUserInfo(); } +/* +================= +idGameLocal::SetPortalSkyEnt +================= +*/ +void idGameLocal::SetPortalSkyEnt( idEntity *ent ) { + portalSkyEnt = ent; +} + +/* +================= +idGameLocal::IsPortalSkyActive +================= +*/ +bool idGameLocal::IsPortalSkyActive() { + return portalSkyActive; +} + +/* +================= +idGameLocal::CheckGlobalPortalSky +================= +*/ +bool idGameLocal::CheckGlobalPortalSky() { + return globalPortalSky; +} + +/* +================= +idGameLocal::SetGlobalPortalSky +================= +*/ +void idGameLocal::SetGlobalPortalSky( const char *name ) { + + if ( CheckGlobalPortalSky() ) { + Error( "idGameLocal::SetGlobalPortalSky : more than one global portalSky:\ndelete them until you have just one.\nportalSky '%s' causes it.", name ); + } + else { + globalPortalSky = true; + } +} + +/* +================= +idGameLocal::SetCurrentPortalSkyType +================= +*/ +void idGameLocal::SetCurrentPortalSkyType( int type ) { + currentPortalSkyType = type; +} + +/* +================= +idGameLocal::GetCurrentPortalSkyType +================= +*/ +int idGameLocal::GetCurrentPortalSkyType() { + return currentPortalSkyType; +} + /* =========== idGameLocal::SelectTimeGroup diff --git a/game/Game_local.h b/game/Game_local.h index df7456d1..1cbcb26c 100644 --- a/game/Game_local.h +++ b/game/Game_local.h @@ -163,6 +163,12 @@ typedef struct { int dist; } spawnSpot_t; +enum { + PORTALSKY_STANDARD = 0, // standard D3XP portalsky + PORTALSKY_GLOBAL = 1, // always following portal sky since the start of the level + PORTALSKY_LOCAL = 2, // when triggered start follwing always from the spawn position +}; + //============================================================================ class idEventQueue { @@ -294,6 +300,21 @@ class idGameLocal : public idGame { idEntityPtr lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f int lastGUI; // last GUI on the lastGUIEnt + idEntityPtr portalSkyEnt; + bool portalSkyActive; + bool globalPortalSky; + int portalSkyScale; + int currentPortalSkyType; //0 = classic, 1 = global, 2 = local + idVec3 portalSkyOrigin; + idVec3 portalSkyGlobalOrigin; + idVec3 playerOldEyePos; + void SetPortalSkyEnt( idEntity *ent ); + bool IsPortalSkyActive(); + bool CheckGlobalPortalSky(); + void SetGlobalPortalSky(const char *name); + void SetCurrentPortalSkyType(int type); // 0 = classic, 1 = global, 2 = local + int GetCurrentPortalSkyType(); //0 = classic, 1 = global, 2 = local + // ---------------------- Public idGame Interface ------------------- idGameLocal(); @@ -386,6 +407,8 @@ class idGameLocal : public idGame { bool InPlayerPVS( idEntity *ent ) const; bool InPlayerConnectedArea( idEntity *ent ) const; + + pvsHandle_t GetPlayerPVS() { return playerPVS; }; void SetCamera( idCamera *cam ); idCamera * GetCamera( void ) const; diff --git a/game/Game_network.cpp b/game/Game_network.cpp index 5e24df70..cb2b83a4 100644 --- a/game/Game_network.cpp +++ b/game/Game_network.cpp @@ -589,6 +589,18 @@ void idGameLocal::ServerWriteSnapshot( int clientNum, int sequence, idBitMsg &ms numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS ); pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL ); + // Add portalSky areas to PVS + if ( portalSkyEnt.GetEntity() ) { + pvsHandle_t otherPVS, newPVS; + idEntity *skyEnt = portalSkyEnt.GetEntity(); + + otherPVS = gameLocal.pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() ); + newPVS = gameLocal.pvs.MergeCurrentPVS( pvsHandle, otherPVS ); + pvs.FreeCurrentPVS( pvsHandle ); + pvs.FreeCurrentPVS( otherPVS ); + pvsHandle = newPVS; + } + #if ASYNC_WRITE_TAGS idRandom tagRandom; tagRandom.SetSeed( random.RandomInt() ); @@ -1120,6 +1132,18 @@ void idGameLocal::ClientReadSnapshot( int clientNum, int sequence, const int gam numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS ); pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL ); + // Add portalSky areas to PVS + if ( portalSkyEnt.GetEntity() ) { + pvsHandle_t otherPVS, newPVS; + idEntity *skyEnt = portalSkyEnt.GetEntity(); + + otherPVS = gameLocal.pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() ); + newPVS = gameLocal.pvs.MergeCurrentPVS( pvsHandle, otherPVS ); + pvs.FreeCurrentPVS( pvsHandle ); + pvs.FreeCurrentPVS( otherPVS ); + pvsHandle = newPVS; + } + // read the PVS from the snapshot #if ASYNC_WRITE_PVS int serverPVS[idEntity::MAX_PVS_AREAS]; diff --git a/game/Item.cpp b/game/Item.cpp index 97ae9523..6450d31d 100644 --- a/game/Item.cpp +++ b/game/Item.cpp @@ -712,6 +712,42 @@ void idObjective::Event_CamShot( ) { renderView_t fullView = *view; fullView.width = SCREEN_WIDTH; fullView.height = SCREEN_HEIGHT; + + // HACK : always draw sky-portal view if there is one in the map, this isn't real-time + if ( gameLocal.portalSkyEnt.GetEntity() && g_enablePortalSky.GetBool() ) { + renderView_t portalView = fullView; + portalView.vieworg = gameLocal.portalSkyEnt.GetEntity()->GetPhysics()->GetOrigin(); + + // setup global fixup projection vars + if ( 1 ) { + int vidWidth, vidHeight; + idVec2 shiftScale; + + renderSystem->GetGLSettings( vidWidth, vidHeight ); + + float pot; + int temp; + + int w = vidWidth; + for (temp = 1 ; temp < w ; temp<<=1) { + } + pot = (float)temp; + shiftScale.x = (float)w / pot; + + int h = vidHeight; + for (temp = 1 ; temp < h ; temp<<=1) { + } + pot = (float)temp; + shiftScale.y = (float)h / pot; + + fullView.shaderParms[4] = shiftScale.x; + fullView.shaderParms[5] = shiftScale.y; + } + + gameRenderWorld->RenderScene( &portalView ); + renderSystem->CaptureRenderToImage( "_currentRender" ); + } + // draw a view to a texture renderSystem->CropRenderSize( 256, 256, true ); gameRenderWorld->RenderScene( &fullView ); diff --git a/game/Misc.cpp b/game/Misc.cpp index bfde7193..df186830 100644 --- a/game/Misc.cpp +++ b/game/Misc.cpp @@ -3156,3 +3156,92 @@ void idPhantomObjects::Think( void ) { BecomeInactive( TH_THINK ); } } + +/* +=============================================================================== + +idPortalSky + +=============================================================================== +*/ + +CLASS_DECLARATION( idEntity, idPortalSky ) + EVENT( EV_PostSpawn, idPortalSky::Event_PostSpawn ) + EVENT( EV_Activate, idPortalSky::Event_Activate ) +END_CLASS + +/* +=============== +idPortalSky::idPortalSky +=============== +*/ +idPortalSky::idPortalSky( void ) { + +} + +/* +=============== +idPortalSky::~idPortalSky +=============== +*/ +idPortalSky::~idPortalSky( void ) { + +} + +/* +=============== +idPortalSky::Spawn +=============== +*/ +void idPortalSky::Spawn( void ) { + + if ( spawnArgs.GetInt( "type" ) == PORTALSKY_GLOBAL ) { + gameLocal.SetGlobalPortalSky( spawnArgs.GetString( "name" ) ); + gameLocal.portalSkyGlobalOrigin = GetPhysics()->GetOrigin(); + } + + + if ( !spawnArgs.GetBool( "triggered" ) ) { + if ( spawnArgs.GetInt( "type" ) != PORTALSKY_STANDARD ) { + gameLocal.portalSkyScale = spawnArgs.GetInt( "scale", "16" ); + } + PostEventMS( &EV_PostSpawn, 1 ); + } + + +} + +/* +================ +idPortalSky::Event_PostSpawn +================ +*/ +void idPortalSky::Event_PostSpawn() { + + gameLocal.SetCurrentPortalSkyType( spawnArgs.GetInt( "type", "0" ) ); + + if ( gameLocal.GetCurrentPortalSkyType() != PORTALSKY_GLOBAL ) { + gameLocal.portalSkyOrigin = GetPhysics()->GetOrigin(); + // both standard and local portalSky share the origin, it's in the execution that things change. + } + + gameLocal.SetPortalSkyEnt( this ); +} + +/* +================ +idPortalSky::Event_Activate +================ +*/ +void idPortalSky::Event_Activate( idEntity *activator ) { + + gameLocal.SetCurrentPortalSkyType( spawnArgs.GetInt( "type", "0" ) ); + + if ( gameLocal.GetCurrentPortalSkyType() != PORTALSKY_GLOBAL ) { + gameLocal.portalSkyOrigin = GetPhysics()->GetOrigin(); + // both standard and local portalSky share the origin, it's in the execution that things change. + } + + gameLocal.portalSkyScale = spawnArgs.GetInt( "scale", "16" ); + gameLocal.SetPortalSkyEnt( this ); +} diff --git a/game/Misc.h b/game/Misc.h index 89a4235e..4c35feeb 100644 --- a/game/Misc.h +++ b/game/Misc.h @@ -765,4 +765,23 @@ class idPhantomObjects : public idEntity { idList lastTargetPos; }; +/* +=============================================================================== + +idPortalSky + +=============================================================================== +*/ +class idPortalSky : public idEntity { +public: + CLASS_PROTOTYPE( idPortalSky ); + + idPortalSky(); + ~idPortalSky(); + + void Spawn( void ); + void Event_PostSpawn(); + void Event_Activate( idEntity *activator ); +}; + #endif /* !__GAME_MISC_H__ */ diff --git a/game/Player.cpp b/game/Player.cpp index 8308c961..56543588 100644 --- a/game/Player.cpp +++ b/game/Player.cpp @@ -6406,6 +6406,9 @@ void idPlayer::Think( void ) { } gameLocal.Printf( "%d: enemies\n", num ); } + + // determine if portal sky is in pvs + gameLocal.portalSkyActive = gameLocal.pvs.CheckAreasForPortalSky( gameLocal.GetPlayerPVS(), GetPhysics()->GetOrigin() ); } /* @@ -7935,6 +7938,11 @@ void idPlayer::ClientPredictionThink( void ) { if ( gameLocal.isNewFrame && entityNumber == gameLocal.localClientNum ) { playerView.CalculateShake(); } + + // determine if portal sky is in pvs + pvsHandle_t clientPVS = gameLocal.pvs.SetupCurrentPVS( GetPVSAreas(), GetNumPVSAreas() ); + gameLocal.portalSkyActive = gameLocal.pvs.CheckAreasForPortalSky( clientPVS, GetPhysics()->GetOrigin() ); + gameLocal.pvs.FreeCurrentPVS( clientPVS ); } /* diff --git a/game/PlayerView.cpp b/game/PlayerView.cpp index 149b8292..5c6b861d 100644 --- a/game/PlayerView.cpp +++ b/game/PlayerView.cpp @@ -36,6 +36,13 @@ If you have questions concerning this license or the applicable additional terms #include "PlayerView.h" +static int MakePowerOfTwo( int num ) { + int pot; + for (pot = 1 ; pot < num ; pot<<=1) { + } + return pot; +} + const int IMPULSE_DELAY = 150; /* ============== @@ -452,6 +459,74 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) renderView_t hackedView = *view; hackedView.viewaxis = hackedView.viewaxis * ShakeAxis(); + idVec3 diff, currentEyePos, PSOrigin, Zero; + + Zero.Zero(); + if ( ( gameLocal.CheckGlobalPortalSky() ) || ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) ) { + // in a case of a moving portalSky + + currentEyePos = hackedView.vieworg; + + if ( gameLocal.playerOldEyePos == Zero ) { + gameLocal.playerOldEyePos = currentEyePos; + //initialize playerOldEyePos, this will only happen in one tick. + } + + diff = ( currentEyePos - gameLocal.playerOldEyePos) / gameLocal.portalSkyScale; + gameLocal.portalSkyGlobalOrigin += diff; // this is for the global portalSky. + // It should keep going even when not active. + } + + if ( gameLocal.portalSkyEnt.GetEntity() && gameLocal.IsPortalSkyActive() && g_enablePortalSky.GetBool() ) { + if ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_STANDARD ) { + PSOrigin = gameLocal.portalSkyOrigin; + } + + if ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_GLOBAL ) { + PSOrigin = gameLocal.portalSkyGlobalOrigin; + } + + if ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) { + gameLocal.portalSkyOrigin += diff; + PSOrigin = gameLocal.portalSkyOrigin; + } + + gameLocal.playerOldEyePos = currentEyePos; + + renderView_t portalView = hackedView; + portalView.vieworg = PSOrigin; + + // setup global fixup projection vars + if ( 1 ) { + int vidWidth, vidHeight; + idVec2 shiftScale; + + renderSystem->GetGLSettings( vidWidth, vidHeight ); + + float pot; + int w = vidWidth; + pot = MakePowerOfTwo( w ); + shiftScale.x = (float)w / pot; + + int h = vidHeight; + pot = MakePowerOfTwo( h ); + shiftScale.y = (float)h / pot; + + hackedView.shaderParms[4] = shiftScale.x; + hackedView.shaderParms[5] = shiftScale.y; + } + + gameRenderWorld->RenderScene( &portalView ); + renderSystem->CaptureRenderToImage( "_currentRender" ); + + hackedView.forceUpdate = true; // FIX: for smoke particles not drawing when portalSky present + + } else { + gameLocal.playerOldEyePos = currentEyePos; + // so if g_enablePortalSky is disabled GlobalPortalSkies don't broke + // when g_enablePortalSky gets re-enabled GlobalPortalSkies keep working + } + gameRenderWorld->RenderScene( &hackedView ); if ( player->spectating ) { diff --git a/game/Pvs.cpp b/game/Pvs.cpp index 4536710e..745f4b55 100644 --- a/game/Pvs.cpp +++ b/game/Pvs.cpp @@ -1421,3 +1421,51 @@ void idPVS::ReadPVS( const pvsHandle_t handle, const idBitMsg &msg ) { } #endif + +/* +================ +idPVS::CheckAreasForPortalSky +================ +*/ +bool idPVS::CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &origin ) { + int j, sourceArea; + + if ( handle.i < 0 || handle.i >= MAX_CURRENT_PVS || handle.h != currentPVS[handle.i].handle.h ) { + return false; + } + + sourceArea = gameRenderWorld->PointInArea( origin ); + + if ( sourceArea == -1 ) { + // this is the case where the player is not in any AAS area; + // this is, he is in noclip mode out of the map. let's do a global/local PS check! + + if ( gameLocal.CheckGlobalPortalSky() || ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) ) { + //this is... if the current PS is local, or there exist a global PS in the map, even if it's not current... + return true; // in any one of those cases keep callculating for the global or the local portalSky + } + return false; + } + + for ( j = 0; j < numAreas; j++ ) { + + if ( !( currentPVS[handle.i].pvs[j>>3] & (1 << (j&7)) ) ) { + continue; + } + + if ( gameRenderWorld->CheckAreaForPortalSky( j ) ) { + return true; + } + } + + // here if the player is in an unreachable AAS like inisde a sealed room, where he teleports in, + // the function will return false. so let's repeat the global/local PS check! + + + if ( gameLocal.CheckGlobalPortalSky() || ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) ) { + //this is... if the current PS is local, or there exist a global PS in the map, even if it's not current... + return true; // in any one of those cases keep callculating for the global or the local portalSky + } + + return false; +} diff --git a/game/Pvs.h b/game/Pvs.h index 963b1786..ae904f2e 100644 --- a/game/Pvs.h +++ b/game/Pvs.h @@ -97,6 +97,8 @@ class idPVS { void ReadPVS( const pvsHandle_t handle, const idBitMsg &msg ); #endif + bool CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &origin ); + private: int numAreas; int numPortals; diff --git a/game/gamesys/SysCvar.cpp b/game/gamesys/SysCvar.cpp index e2d64e7c..7d75934f 100644 --- a/game/gamesys/SysCvar.cpp +++ b/game/gamesys/SysCvar.cpp @@ -335,3 +335,5 @@ idCVar mod_validSkins( "mod_validSkins", "skins/characters/player/marine_mp idCVar net_serverDownload( "net_serverDownload", "0", CVAR_GAME | CVAR_INTEGER | CVAR_ARCHIVE, "enable server download redirects. 0: off 1: redirect to si_serverURL 2: use builtin download. see net_serverDl cvars for configuration" ); idCVar net_serverDlBaseURL( "net_serverDlBaseURL", "", CVAR_GAME | CVAR_ARCHIVE, "base URL for the download redirection" ); idCVar net_serverDlTable( "net_serverDlTable", "", CVAR_GAME | CVAR_ARCHIVE, "pak names for which download is provided, separated by ;" ); + +idCVar g_enablePortalSky( "g_enablePortalSky", "1", CVAR_GAME | CVAR_BOOL, "enables the portal sky" ); diff --git a/game/gamesys/SysCvar.h b/game/gamesys/SysCvar.h index da8e26ee..1296d5fc 100644 --- a/game/gamesys/SysCvar.h +++ b/game/gamesys/SysCvar.h @@ -254,4 +254,6 @@ extern const char *si_gameTypeArgs[]; extern const char *ui_skinArgs[]; +extern idCVar g_enablePortalSky; + #endif /* !__SYS_CVAR_H__ */ From 8d8a09c9a4f2a6577e419296b75aac9f7452cf90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ABBielBdeLuna=C2=BB?= <«7318.tk@gmail.com»> Date: Fri, 21 Jun 2024 17:37:33 +0200 Subject: [PATCH 2/3] added the infrestructure in a pk4 file --- base/portalsky_00.pk4 | Bin 0 -> 6617 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 base/portalsky_00.pk4 diff --git a/base/portalsky_00.pk4 b/base/portalsky_00.pk4 new file mode 100644 index 0000000000000000000000000000000000000000..a84fb2e38dc3b904bc17a4bc88c9190d189f29cd GIT binary patch literal 6617 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 literal 0 HcmV?d00001 From 6f459b3b5859d872e1bd4078b9b67d217dcdf807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ABBielBdeLuna=C2=BB?= <«7318.tk@gmail.com»> Date: Tue, 25 Jun 2024 12:59:38 +0200 Subject: [PATCH 3/3] d3xp now also can use the new portalskies --- d3xp/Game_local.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++-- d3xp/Game_local.h | 20 +++++++++++++- d3xp/Misc.cpp | 23 ++++++++++++++++ d3xp/PlayerView.cpp | 44 ++++++++++++++++++++++++++++--- d3xp/Pvs.cpp | 14 ++++++++++ game/PlayerView.cpp | 1 + 6 files changed, 160 insertions(+), 6 deletions(-) diff --git a/d3xp/Game_local.cpp b/d3xp/Game_local.cpp index 0b1252eb..1684a5ed 100644 --- a/d3xp/Game_local.cpp +++ b/d3xp/Game_local.cpp @@ -296,6 +296,9 @@ void idGameLocal::Clear( void ) { portalSkyEnt = NULL; portalSkyActive = false; + playerOldEyePos.Zero(); + globalPortalSky = false; + ResetSlowTimeVars(); #endif } @@ -630,6 +633,12 @@ void idGameLocal::SaveGame( idFile *f ) { #ifdef _D3XP portalSkyEnt.Save( &savegame ); savegame.WriteBool( portalSkyActive ); + + savegame.WriteBool( globalPortalSky ); + savegame.WriteInt( currentPortalSkyType ); + savegame.WriteVec3( playerOldEyePos ); + savegame.WriteVec3( portalSkyGlobalOrigin ); + savegame.WriteVec3( portalSkyOrigin ); fast.Save( &savegame ); slow.Save( &savegame ); @@ -1018,6 +1027,9 @@ void idGameLocal::LoadMap( const char *mapName, int randseed ) { #ifdef _D3XP portalSkyEnt = NULL; portalSkyActive = false; + + playerOldEyePos.Zero(); + globalPortalSky = false; ResetSlowTimeVars(); #endif @@ -1539,6 +1551,12 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo #ifdef _D3XP portalSkyEnt.Restore( &savegame ); savegame.ReadBool( portalSkyActive ); + + savegame.ReadBool( globalPortalSky ); + savegame.ReadInt( currentPortalSkyType ); + savegame.ReadVec3( playerOldEyePos ); + savegame.ReadVec3( portalSkyGlobalOrigin ); + savegame.ReadVec3( portalSkyOrigin ); fast.Restore( &savegame ); slow.Restore( &savegame ); @@ -4796,13 +4814,55 @@ void idGameLocal::SetPortalSkyEnt( idEntity *ent ) { /* ================= -idPlayer::IsPortalSkyAcive +idPlayer::IsPortalSkyActive ================= */ -bool idGameLocal::IsPortalSkyAcive() { +bool idGameLocal::IsPortalSkyActive() { return portalSkyActive; } +/* +================= +idGameLocal::CheckGlobalPortalSky +================= +*/ +bool idGameLocal::CheckGlobalPortalSky() { + return globalPortalSky; +} + +/* +================= +idGameLocal::SetGlobalPortalSky +================= +*/ +void idGameLocal::SetGlobalPortalSky( const char *name ) { + + if ( CheckGlobalPortalSky() ) { + Error( "idGameLocal::SetGlobalPortalSky : more than one global portalSky:\ndelete them until you have just one.\nportalSky '%s' causes it.", name ); + } + else { + globalPortalSky = true; + } +} + +/* +================= +idGameLocal::SetCurrentPortalSkyType +================= +*/ +void idGameLocal::SetCurrentPortalSkyType( int type ) { + currentPortalSkyType = type; +} + +/* +================= +idGameLocal::GetCurrentPortalSkyType +================= +*/ +int idGameLocal::GetCurrentPortalSkyType() { + return currentPortalSkyType; +} + /* =========== idGameLocal::SelectTimeGroup diff --git a/d3xp/Game_local.h b/d3xp/Game_local.h index acd4fff0..688bd8f1 100644 --- a/d3xp/Game_local.h +++ b/d3xp/Game_local.h @@ -166,6 +166,12 @@ typedef struct { #endif } spawnSpot_t; +enum { + PORTALSKY_STANDARD = 0, // classic portalsky + PORTALSKY_GLOBAL = 1, // always following portal sky + PORTALSKY_LOCAL = 2, // following portal sky from a spot +}; + //============================================================================ class idEventQueue { @@ -324,8 +330,20 @@ class idGameLocal : public idGame { idEntityPtr portalSkyEnt; bool portalSkyActive; + bool globalPortalSky; + int portalSkyScale; + int currentPortalSkyType; // 0 = classic, 1 = global, 2 = local + idVec3 portalSkyOrigin; + idVec3 portalSkyGlobalOrigin; + idVec3 playerOldEyePos; + void SetPortalSkyEnt( idEntity *ent ); - bool IsPortalSkyAcive(); + bool IsPortalSkyActive(); + + bool CheckGlobalPortalSky(); + void SetGlobalPortalSky(const char *name); + void SetCurrentPortalSkyType(int type); // 0 = classic, 1 = global, 2 = local + int GetCurrentPortalSkyType(); // 0 = classic, 1 = global, 2 = local timeState_t fast; timeState_t slow; diff --git a/d3xp/Misc.cpp b/d3xp/Misc.cpp index f87342d5..592e7e71 100644 --- a/d3xp/Misc.cpp +++ b/d3xp/Misc.cpp @@ -3737,7 +3737,15 @@ idPortalSky::Spawn =============== */ void idPortalSky::Spawn( void ) { + if ( spawnArgs.GetInt( "type" ) == PORTALSKY_GLOBAL ) { + gameLocal.SetGlobalPortalSky( spawnArgs.GetString( "name" ) ); + gameLocal.portalSkyGlobalOrigin = GetPhysics()->GetOrigin(); + } + if ( !spawnArgs.GetBool( "triggered" ) ) { + if ( spawnArgs.GetInt( "type" ) != PORTALSKY_STANDARD ) { + gameLocal.portalSkyScale = spawnArgs.GetInt( "scale", "16" ); + } PostEventMS( &EV_PostSpawn, 1 ); } } @@ -3748,6 +3756,13 @@ idPortalSky::Event_PostSpawn ================ */ void idPortalSky::Event_PostSpawn() { + gameLocal.SetCurrentPortalSkyType( spawnArgs.GetInt( "type", "0" ) ); + + if ( gameLocal.GetCurrentPortalSkyType() != PORTALSKY_GLOBAL ) { + gameLocal.portalSkyOrigin = GetPhysics()->GetOrigin(); + // both standard and local portalSky share the origin, it's in the execution that things change. + } + gameLocal.SetPortalSkyEnt( this ); } @@ -3757,6 +3772,14 @@ idPortalSky::Event_Activate ================ */ void idPortalSky::Event_Activate( idEntity *activator ) { + gameLocal.SetCurrentPortalSkyType( spawnArgs.GetInt( "type", "0" ) ); + + if ( gameLocal.GetCurrentPortalSkyType() != PORTALSKY_GLOBAL ) { + gameLocal.portalSkyOrigin = GetPhysics()->GetOrigin(); + // both standard and local portalSky share the origin, it's in the execution that things change. + } + + gameLocal.portalSkyScale = spawnArgs.GetInt( "scale", "16" ); gameLocal.SetPortalSkyEnt( this ); } #endif /* _D3XP */ diff --git a/d3xp/PlayerView.cpp b/d3xp/PlayerView.cpp index 00a5d21c..547d3762 100644 --- a/d3xp/PlayerView.cpp +++ b/d3xp/PlayerView.cpp @@ -484,9 +484,42 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) hackedView.viewaxis = hackedView.viewaxis * ShakeAxis(); #ifdef _D3XP - if ( gameLocal.portalSkyEnt.GetEntity() && gameLocal.IsPortalSkyAcive() && g_enablePortalSky.GetBool() ) { + idVec3 diff, currentEyePos, PSOrigin, Zero; + + Zero.Zero(); + + if ( ( gameLocal.CheckGlobalPortalSky() ) || ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) ) { + // in a case of a moving portalSky + currentEyePos = hackedView.vieworg; + + if ( gameLocal.playerOldEyePos == Zero ) { + gameLocal.playerOldEyePos = currentEyePos; + //initialize playerOldEyePos, this will only happen in one tick. + } + + diff = ( currentEyePos - gameLocal.playerOldEyePos) / gameLocal.portalSkyScale; + gameLocal.portalSkyGlobalOrigin += diff; // this is for the global portalSky. + // It should keep going even when not active. + } + + if ( gameLocal.portalSkyEnt.GetEntity() && gameLocal.IsPortalSkyActive() && g_enablePortalSky.GetBool() ) { + if ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_STANDARD ) { + PSOrigin = gameLocal.portalSkyOrigin; + } + + if ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_GLOBAL ) { + PSOrigin = gameLocal.portalSkyGlobalOrigin; + } + + if ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) { + gameLocal.portalSkyOrigin += diff; + PSOrigin = gameLocal.portalSkyOrigin; + } + + gameLocal.playerOldEyePos = currentEyePos; + renderView_t portalView = hackedView; - portalView.vieworg = gameLocal.portalSkyEnt.GetEntity()->GetPhysics()->GetOrigin(); + portalView.vieworg = PSOrigin; // setup global fixup projection vars if ( 1 ) { @@ -512,10 +545,15 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) renderSystem->CaptureRenderToImage( "_currentRender" ); hackedView.forceUpdate = true; // FIX: for smoke particles not drawing when portalSky present + } else { + gameLocal.playerOldEyePos = currentEyePos; + // so if g_enablePortalSky is disabled GlobalPortalSkies don't broke + // when g_enablePortalSky gets re-enabled GlPS keep working } // process the frame - fxManager->Process( &hackedView ); + gameRenderWorld->RenderScene( &hackedView ); + #endif if ( player->spectating ) { diff --git a/d3xp/Pvs.cpp b/d3xp/Pvs.cpp index 4894eb1a..96698f50 100644 --- a/d3xp/Pvs.cpp +++ b/d3xp/Pvs.cpp @@ -1439,6 +1439,13 @@ bool idPVS::CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &orig sourceArea = gameRenderWorld->PointInArea( origin ); if ( sourceArea == -1 ) { + // this is the case where the player is not in any AAS area; + // this is, he is in noclip mode out of the map. let's do a global/local PS check! + + if ( gameLocal.CheckGlobalPortalSky() || ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) ) { + //this is... if the current PS is local, or there exist a global PS in the map, even if it's not current... + return true; // in any one of those cases keep callculating for the global or the local portalSky + } return false; } @@ -1453,6 +1460,13 @@ bool idPVS::CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &orig } } + // here if the player is in an unreachable AAS like inisde a sealed room, where he teleports in, + // the function will return false. so let's repeat the global/local PS check! + + if ( gameLocal.CheckGlobalPortalSky() || ( gameLocal.GetCurrentPortalSkyType() == PORTALSKY_LOCAL ) ) { + //this is... if the current PS is local, or there exist a global PS in the map, even if it's not current... + return true; // in any one of those cases keep callculating for the global or the local portalSky + } return false; } #endif diff --git a/game/PlayerView.cpp b/game/PlayerView.cpp index 5c6b861d..b73bd4c0 100644 --- a/game/PlayerView.cpp +++ b/game/PlayerView.cpp @@ -527,6 +527,7 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) // when g_enablePortalSky gets re-enabled GlobalPortalSkies keep working } + // process the frame gameRenderWorld->RenderScene( &hackedView ); if ( player->spectating ) {