diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 936763f0..136750d6 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -4279,9 +4279,6 @@ void HandleExplosionQueue( void ) } } -// Flugente: riot shields -extern void ShowRiotShield( SOLDIERTYPE* pSoldier ); - // Flugente: show warnings around armed timebombs both in map and inventories void HandleExplosionWarningAnimations( ) { @@ -4359,26 +4356,6 @@ void HandleExplosionWarningAnimations( ) } } } - - // show riot shields - for ( UINT32 cnt = 0; cnt < TOTAL_SOLDIERS; ++cnt ) - { - SOLDIERTYPE* pSoldier = MercPtrs[cnt]; - - if ( pSoldier && pSoldier->bActive && pSoldier->bInSector ) - { - if ( (pSoldier->ubDirection == EAST || - pSoldier->ubDirection == SOUTHEAST || - pSoldier->ubDirection == SOUTH || - pSoldier->ubDirection == SOUTHWEST || - pSoldier->ubDirection == NORTHEAST) - && pSoldier->bVisible != -1 - && pSoldier->IsRiotShieldEquipped( ) ) - { - ShowRiotShield( pSoldier ); - } - } - } } void DecayBombTimers( void ) diff --git a/TileEngine/renderworld.cpp b/TileEngine/renderworld.cpp index d603e2f2..9458003f 100644 --- a/TileEngine/renderworld.cpp +++ b/TileEngine/renderworld.cpp @@ -582,7 +582,7 @@ void RenderHighlight( INT16 sMouseX_M, INT16 sMouseY_M, INT16 sStartPointX_M, IN BOOLEAN CheckRenderCenter( INT16 sNewCenterX, INT16 sNewCenterY ); // Flugente: display a riot shield -void ShowRiotShield( SOLDIERTYPE* pSoldier ) +void ShowRiotShield( SOLDIERTYPE* pSoldier, UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue ) { if (pSoldier) { @@ -598,6 +598,17 @@ void ShowRiotShield( SOLDIERTYPE* pSoldier ) fShieldGraphicInit = TRUE; } + + HVOBJECT hSrcVObject; + if ( !GetVideoObject( &hSrcVObject, guiShieldGraphic ) ) + return; + + OBJECTTYPE* pObj = pSoldier->GetEquippedRiotShield(); + + if ( !pObj ) + return; + + UINT16 offset = Item[pObj->usItem].usRiotShieldGraphic; // Get screen pos of gridno...... INT16 sScreenX, sScreenY; @@ -607,24 +618,6 @@ void ShowRiotShield( SOLDIERTYPE* pSoldier ) if ( pSoldier->pathing.bLevel == 1 ) sScreenY -= 50; - // redraw background to stop weird graphic remnants remaining - // but don*t do so while scrolling, because that looks weird - if ( !gfScrollPending && !gfScrollInertia) - { - INT32 iBack = RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sScreenX - 50, sScreenY - 60, sScreenX + 50, sScreenY + 35 ); - - if (iBack != -1) - { - SetBackgroundRectFilled(iBack); - } - } - - UINT16 offset = 0; - OBJECTTYPE* pObj = pSoldier->GetEquippedRiotShield(); - - if (pObj) - offset = Item[pObj->usItem].usRiotShieldGraphic; - // try to keep the shield 'moving' alongside the soldier. This won't work perfectly, but it's better than nothing INT16 base_x = 0; INT16 base_y = 0; @@ -636,7 +629,29 @@ void ShowRiotShield( SOLDIERTYPE* pSoldier ) INT16 offset_x = (dx - dy); INT16 offset_y = (dx + dy); - BltVideoObjectFromIndex( FRAME_BUFFER, guiShieldGraphic, offset * 8 + pSoldier->ubDirection, sScreenX - 20 + offset_x, sScreenY - 60 + offset_y, VO_BLT_TRANSSHADOW, NULL ); + // redraw background to stop weird graphic remnants remaining + // but don't do so while scrolling, because that looks weird + if ( !gfScrollPending && !gfScrollInertia ) + { + // We can get graphical glitches here if we reserve too many background rectangles, as the entire array will be filled rapidly. + // To prevent this, each soldier can have their own reserved rectangle, which we free first + static INT32 soldierbackgroundrectangle[TOTAL_SOLDIERS] = { 0 }; + + if ( soldierbackgroundrectangle[pSoldier->ubID] != 0 && soldierbackgroundrectangle[pSoldier->ubID] != -1 ) + { + FreeBackgroundRect( soldierbackgroundrectangle[pSoldier->ubID] ); + soldierbackgroundrectangle[pSoldier->ubID] = 0; + } + + soldierbackgroundrectangle[pSoldier->ubID] = RegisterBackgroundRect( BGND_FLAG_ANIMATED, NULL, sScreenX - 50, sScreenY - 60, sScreenX + 50, sScreenY + 35 ); + + if ( soldierbackgroundrectangle[pSoldier->ubID] != -1 ) + { + SetBackgroundRectFilled( soldierbackgroundrectangle[pSoldier->ubID] ); + } + } + + Blt8BPPDataTo16BPPBufferTransZNB( pBuffer, uiDestPitchBYTES, pZBuffer, usZValue, hSrcVObject, sScreenX - 20 + offset_x, sScreenY - 60 + offset_y, offset * 8 + pSoldier->ubDirection ); } } @@ -957,7 +972,7 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT //#if 0 LEVELNODE *pNode; //, *pLand, *pStruct; //*pObject, *pTopmost, *pMerc; - SOLDIERTYPE *pSoldier, *pSelSoldier; + SOLDIERTYPE *pSoldier; HVOBJECT hVObject = NULL; ETRLEObject *pTrav; TILE_ELEMENT *TileElem = NULL; @@ -1870,17 +1885,6 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT usImageIndex = pSoldier->CryoAniFrame(); } - // Flugente: riot shields - if (pSoldier && - pSoldier->bVisible != -1 && - (pSoldier->ubDirection == NORTH || - pSoldier->ubDirection == NORTHWEST || - pSoldier->ubDirection == WEST) - && pSoldier->IsRiotShieldEquipped()) - { - ShowRiotShield(pSoldier); - } - uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED | BGND_FLAG_MERC; break; } @@ -2516,6 +2520,17 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } else if (fMerc) { + // Flugente: draw riot shield UNDER the soldier + if ( pSoldier && + pSoldier->bVisible != -1 && + ( pSoldier->ubDirection == NORTH || + pSoldier->ubDirection == NORTHWEST || + pSoldier->ubDirection == WEST ) + && pSoldier->IsRiotShieldEquipped() ) + { + ShowRiotShield( pSoldier, (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel ); + } + if (fZBlitter) { if (fZWrite) @@ -2639,6 +2654,19 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } } + + // Flugente: draw riot shield OVER the soldier + if ( pSoldier && + pSoldier->bVisible != -1 && + ( pSoldier->ubDirection == EAST || + pSoldier->ubDirection == SOUTHEAST || + pSoldier->ubDirection == SOUTH || + pSoldier->ubDirection == SOUTHWEST || + pSoldier->ubDirection == NORTHEAST ) + && pSoldier->IsRiotShieldEquipped() ) + { + ShowRiotShield( pSoldier, (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel ); + } } else if (fShadowBlitter) {