From 350e7cd849435825e17ec61a22fab90f9230d3f8 Mon Sep 17 00:00:00 2001 From: Flugente Date: Sun, 16 Oct 2016 14:32:37 +0000 Subject: [PATCH] If TIME_BOMB_WARNING is true, display a warning animation around any armed time bomb. GameDir >= r2345 is recommended. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=347349&#msg_347349 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8319 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 3 ++ GameSettings.h | 3 ++ Tactical/Interface Control.cpp | 88 ++++++++++++++++++++++++++++++-- Tactical/Interface Control.h | 4 ++ TileEngine/Explosion Control.cpp | 55 +++++++++++++++++++- TileEngine/Explosion Control.h | 3 ++ 6 files changed, 151 insertions(+), 5 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 07172c2b..41edc0ea 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1001,6 +1001,9 @@ void LoadGameExternalOptions() // WDS - Automatically flag mines gGameExternalOptions.automaticallyFlagMines = iniReader.ReadBoolean("Tactical Interface Settings","AUTOMATICALLY_FLAG_MINES_WHEN_SPOTTED", FALSE); + // Flugente: display an animation on any active timed bomb + gGameExternalOptions.fTimeBombWarnAnimations = iniReader.ReadBoolean( "Tactical Interface Settings", "TIME_BOMB_WARNING", FALSE ); + // silversurfer: don't play quote when mine spotted? gGameExternalOptions.fMineSpottedNoTalk = iniReader.ReadBoolean("Tactical Interface Settings","MINES_SPOTTED_NO_TALK", FALSE); diff --git a/GameSettings.h b/GameSettings.h index a1f610ed..3c4b79da 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -567,6 +567,9 @@ typedef struct // WDS - Automatically flag mines BOOLEAN automaticallyFlagMines; + // Flugente: display an animation on any active timed bomb + BOOLEAN fTimeBombWarnAnimations; + // WDS - Automatically try to save when an assertion failure occurs BOOLEAN autoSaveOnAssertionFailure; UINT32 autoSaveTime; diff --git a/Tactical/Interface Control.cpp b/Tactical/Interface Control.cpp index 4f2e8627..446460a1 100644 --- a/Tactical/Interface Control.cpp +++ b/Tactical/Interface Control.cpp @@ -46,6 +46,7 @@ #include "Map Screen Interface.h" #include "civ quotes.h" #include "GameSettings.h" + #include "Explosion Control.h" // added by Flugente #endif #include "connect.h" @@ -580,6 +581,83 @@ void RenderRubberBanding( ) UnLockVideoSurface( FRAME_BUFFER ); } +// Flugente: draw moving circles around a gridno. This is used to warn the playe of impending explosions +void DrawExplosionWarning( INT32 sGridno, INT8 usLevel, INT8 usDelay ) +{ + if ( usDelay <= 0 ) + return; + + UINT16 usLineColor = 0; + UINT32 uiDestPitchBYTES; + UINT8* pDestBuf; + INT32 iBack = -1; + INT16 periods = 120 / usDelay; + static INT32 uiTimeOfLastUpdate = 0; + static INT32 updatecounter = 0; + INT16 sScreenX, sScreenY; + + if ( TileIsOutOfBounds( sGridno ) || !GridNoOnScreen( sGridno ) ) + return; + + // Get screen pos of gridno...... + GetGridNoScreenXY( sGridno, &sScreenX, &sScreenY ); + + // ATE: If we are on a higher interface level, substract.... + if ( usLevel == 1 ) + sScreenY -= 50; + + if ( (GetJA2Clock( ) - uiTimeOfLastUpdate) > 30 ) + { + uiTimeOfLastUpdate = GetJA2Clock( ); + + if ( ++updatecounter >= 120 ) + updatecounter = 0; + } + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y ); + + INT16 numcircles = max( 1, 4 - usDelay); + + for ( int i = 0; i < numcircles; ++i ) + { + INT32 radiusvar = (updatecounter + i * periods / numcircles) % periods; + INT32 radius = min(8, max( 1, radiusvar / 8 ) ); + + INT16 radius_inner = max( 2, radiusvar ); + INT16 radius_outer = radius_inner + radius; + + INT32 xl = max( 0, sScreenX - radius_outer ); + INT32 xr = sScreenX + radius_outer; + INT32 yl = max( 0, sScreenY - radius_outer ); + INT32 yh = sScreenY + radius_outer; + + for ( INT32 x = xl; x <= xr; ++x ) + { + for ( INT32 y = yl; y <= yh; ++y ) + { + FLOAT diff = std::sqrt( (sScreenX - x) * (sScreenX - x) + 2 * (sScreenY - y) * (sScreenY - y) ); + + if ( radius_inner <= diff && diff <= radius_outer ) + { + usLineColor = Get16BPPColor( FROMRGB( min( 255, 50 + 2 * radiusvar ), 0, 0 ) ); + + PixelDraw( FALSE, x, y, usLineColor, pDestBuf ); + } + } + } + + iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, xl, yl, (INT16)(xr + 1), (INT16)(yh + 1) ); + + if ( iBack != -1 ) + { + SetBackgroundRectFilled( iBack ); + } + } + + UnLockVideoSurface( FRAME_BUFFER ); +} + void RenderTopmostTacticalInterface( ) { SOLDIERTYPE *pSoldier; @@ -704,10 +782,12 @@ void RenderTopmostTacticalInterface( ) // Syncronize for upcoming soldier counters SYNCTIMECOUNTER( ); - + // Setup system for video overlay ( text and blitting ) Sets clipping rects, etc StartViewportOverlays( ); + HandleExplosionWarningAnimations( ); + RenderTopmostFlashingItems( ); RenderTopmostMultiPurposeLocator( ); @@ -731,8 +811,8 @@ void RenderTopmostTacticalInterface( ) } DrawCounters( pSoldier ); - } - } + } + } if ( gusSelectedSoldier != NOBODY ) { @@ -761,7 +841,7 @@ void RenderTopmostTacticalInterface( ) RenderAimCubeUI( ); EndViewportOverlays( ); - + RenderRubberBanding( ); if ( !gfInItemPickupMenu && gpItemPointer == NULL ) diff --git a/Tactical/Interface Control.h b/Tactical/Interface Control.h index 7fb9967b..abf08fa7 100644 --- a/Tactical/Interface Control.h +++ b/Tactical/Interface Control.h @@ -65,4 +65,8 @@ void DrawCounters( SOLDIERTYPE *pSoldier ); // width is updated as X offset after printing void PrintCounter( INT16 x, INT16 y, INT16 data, UINT16 &width, UINT8 ubForegound, UINT8 scale = PRINT_SCALE_PLAIN_NUMBER ); void PrintSuppressionCounter( INT16 x, INT16 y, INT16 sX, INT16 sY, UINT8 data, UINT16 &widthDamage, UINT16 &widthSuppression, UINT8 ubForeground, UINT8 scale, UINT8 option); + +// Flugente: draw moving circles around a gridno. This is used to warn the playe of impending explosions +void DrawExplosionWarning( INT32 sGridno, INT8 usLevel, INT8 usDelay ); + #endif \ No newline at end of file diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index f1a20032..22263fc8 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -68,6 +68,7 @@ #include "campaign.h" // yet another one added #include "CampaignStats.h" // added by Flugente #include "Points.h" // added by Flugente +#include "Interface Control.h" // added by Flugente for DrawExplosionWarning(...) #endif #include "Soldier Macros.h" @@ -4235,7 +4236,59 @@ void HandleExplosionQueue( void ) gfExplosionQueueActive = FALSE; } +} +// Flugente: show warnings around armed timebombs both in map and inventories +void HandleExplosionWarningAnimations( ) +{ + if ( gGameExternalOptions.fTimeBombWarnAnimations ) + { + OBJECTTYPE * pObj; + + // Go through all the bombs in the world, and look for timed ones + for ( UINT32 uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; ++uiWorldBombIndex ) + { + if ( gWorldBombs[uiWorldBombIndex].fExists ) + { + pObj = &(gWorldItems[gWorldBombs[uiWorldBombIndex].iItemIndex].object); + + if ( (*pObj)[0]->data.misc.bDetonatorType == BOMB_TIMED && !((*pObj).fFlags & OBJECT_DISABLED_BOMB) && (*pObj)[0]->data.misc.bDelay ) + { + DrawExplosionWarning( gWorldItems[gWorldBombs[uiWorldBombIndex].iItemIndex].sGridNo, gsInterfaceLevel, ( *pObj )[0]->data.misc.bDelay ); + } + } + } + + // Flugente: we have to check every inventory for armed bombs and do the countdown for them, too + for ( UINT32 cnt = 0; cnt < guiNumMercSlots; ++cnt ) + { + SOLDIERTYPE* pSoldier = MercSlots[cnt]; + + if ( pSoldier != NULL ) + { + if ( pSoldier->bInSector && pSoldier->bActive && (pSoldier->sSectorX == gWorldSectorX) && (pSoldier->sSectorY == gWorldSectorY) && (pSoldier->bSectorZ == gbWorldSectorZ) ) + { + INT8 invsize = (INT8)pSoldier->inv.size( ); // remember inventorysize, so we don't call size() repeatedly + + for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) // ... for all items in our inventory ... + { + // ... if Item is a bomb ... + if ( pSoldier->inv[bLoop].exists( ) && (Item[pSoldier->inv[bLoop].usItem].usItemClass & (IC_BOMB | IC_GRENADE)) ) + { + OBJECTTYPE * pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ... + + if ( (*pObj)[0]->data.misc.bDetonatorType == BOMB_TIMED && (*pObj)[0]->data.misc.bDelay ) + { + DrawExplosionWarning( pSoldier->sGridNo, gsInterfaceLevel, ( *pObj )[0]->data.misc.bDelay ); + + break; + } + } + } + } + } + } + } } void DecayBombTimers( void ) @@ -4337,7 +4390,7 @@ void DecayBombTimers( void ) } } } - } + } } void SetOffBombsByFrequency( UINT8 ubID, INT8 bFrequency ) diff --git a/TileEngine/Explosion Control.h b/TileEngine/Explosion Control.h index 610c5a45..e2435220 100644 --- a/TileEngine/Explosion Control.h +++ b/TileEngine/Explosion Control.h @@ -106,6 +106,9 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 void GenerateExplosion( EXPLOSION_PARAMS *pExpParams ); +// Flugente: show warnings around armed timebombs both in map and inventories +void HandleExplosionWarningAnimations( ); + void DecayBombTimers( void ); void SetOffBombsByFrequency( UINT8 ubID, INT8 bFrequency ); BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8 bLevel );