diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index b7dc3d42..0de2b07c 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -878,6 +878,7 @@ static int l_SetSamSiteHackStatus( lua_State *L ); static int l_GetSamSiteHackStatus( lua_State *L ); static int l_SetMiniGameType( lua_State *L ); +static int l_DisplayPictureTactical( lua_State *L ); static int l_SoldierSpendMoney( lua_State *L ); static int l_SetAdditionalDialogue( lua_State *L ); @@ -1772,6 +1773,7 @@ void IniFunction(lua_State *L, BOOLEAN bQuests ) lua_register( L, "GetSamSiteHackStatus", l_GetSamSiteHackStatus ); lua_register( L, "SetMiniGameType", l_SetMiniGameType ); + lua_register( L, "DisplayPictureTactical", l_DisplayPictureTactical ); lua_register( L, "SoldierSpendMoney", l_SoldierSpendMoney ); lua_register( L, "SetAdditionalDialogue", l_SetAdditionalDialogue ); @@ -13247,6 +13249,27 @@ static int l_SetMiniGameType( lua_State *L ) return 0; } +static int l_DisplayPictureTactical( lua_State *L ) +{ + if ( lua_gettop( L ) >= 2 ) + { + size_t len = 0; + const char* str = lua_tolstring( L, 1, &len ); + bool stretch = lua_tointeger( L, 2 ); + + if ( guiCurrentScreen == GAME_SCREEN + && (std::strstr(str, ".png") != NULL || std::strstr( str, ".PNG" ) != NULL ) ) + { + SetInteractivePicture( str, stretch ); + + SetNextGame( PICTURE ); + SetPendingNewScreen( MINIGAME_SCREEN ); + } + } + + return 0; +} + static int l_SoldierSpendMoney( lua_State *L ) { if ( lua_gettop( L ) >= 2 ) diff --git a/Tactical/MiniGame.h b/Tactical/MiniGame.h index 3c42d721..a1f634ae 100644 --- a/Tactical/MiniGame.h +++ b/Tactical/MiniGame.h @@ -13,6 +13,7 @@ enum TETRIS = MINIGAME_FIRST, PONG, + PICTURE, MINIGAME_MAX, }; @@ -38,4 +39,8 @@ UINT32 MiniGame_Handle_Tetris(); void MiniGame_Init_Pong( ); UINT32 MiniGame_Handle_Pong( ); +void SetInteractivePicture( std::string aStr, bool aVal ); +void MiniGame_Init_Picture(); +UINT32 MiniGame_Handle_Picture(); + #endif //__MINIGAME_H \ No newline at end of file diff --git a/Tactical/Minigame.cpp b/Tactical/Minigame.cpp index e33febf7..b87b3b1a 100644 --- a/Tactical/Minigame.cpp +++ b/Tactical/Minigame.cpp @@ -81,6 +81,10 @@ void MiniGameDataInit() MiniGame_Init_Pong( ); break; + case PICTURE: + MiniGame_Init_Picture(); + break; + default: break; } @@ -130,6 +134,10 @@ UINT32 MiniGameScreenHandle( void ) return MiniGame_Handle_Pong( ); break; + case PICTURE: + return MiniGame_Handle_Picture(); + break; + default: break; } @@ -142,7 +150,7 @@ UINT32 MiniGameScreenShutdown( void ) return TRUE; } -void DisplayPNGImage( SGPRect aDstRect, std::string& arStrImage ) +void DisplayPNGImage( SGPRect aDstRect, std::string& arStrImage, bool aStretch ) { VSURFACE_DESC vs_desc = {}; HVSURFACE hVSurface; @@ -164,6 +172,24 @@ void DisplayPNGImage( SGPRect aDstRect, std::string& arStrImage ) SrcRect.iRight = hVSurface->usWidth; SrcRect.iBottom = hVSurface->usHeight; + // if we're not supposed to stretch it, alter aDstRect + INT32 width = SrcRect.iRight - SrcRect.iLeft; + INT32 height = SrcRect.iBottom - SrcRect.iTop; + + INT32 width_dest = aDstRect.iRight - aDstRect.iLeft; + INT32 height_dest = aDstRect.iBottom - aDstRect.iTop; + + if ( !aStretch || width > width_dest || height > height_dest ) + { + if ( width > 0 && height > 0 ) + { + aDstRect.iLeft = max(0, ( aDstRect.iRight + aDstRect.iLeft ) / 2 - width / 2 ); + aDstRect.iRight = min( aDstRect.iRight, aDstRect.iLeft + width); + aDstRect.iTop = max(0, ( aDstRect.iBottom + aDstRect.iTop ) / 2 - height / 2 ); + aDstRect.iBottom = min( aDstRect.iBottom, aDstRect.iTop + height ); + } + } + BltStretchVideoSurface( FRAME_BUFFER, uiLoadScreen, 0, 0, 0, &SrcRect, &aDstRect ); DeleteVideoSurfaceFromIndex( uiLoadScreen ); @@ -412,7 +438,7 @@ UINT32 MiniGame_Handle_Tetris() else if ( gMiniGameState == MINIGAME_GAMEOVER ) strImage = "Interface\\background_tetris_gameover.png"; - DisplayPNGImage( backgroundrect, strImage ); + DisplayPNGImage( backgroundrect, strImage, false ); gMiniGameRenewBackground = FALSE; } @@ -1417,7 +1443,7 @@ UINT32 MiniGame_Handle_Pong() else if ( gMiniGameState == MINIGAME_GAMEOVER ) strImage = "Interface\\background_tetris_gameover.png"; - DisplayPNGImage( backgroundrect, strImage ); + DisplayPNGImage( backgroundrect, strImage, false ); gMiniGameRenewBackground = FALSE; } @@ -2464,3 +2490,41 @@ UINT32 MiniGame_Handle_Pong() return MINIGAME_SCREEN; } ////////////////////////////////////////////// PONG ////////////////////////////////////////////// + +////////////////////////////////////////////// PICTURE ////////////////////////////////////////////// +// We display a picture. That's it. + +std::string gstrInteractivePictureDisplay = "Interface\\background_tetris_startscreen.png"; +bool gstrInteractivePictureStretch = false; + +void SetInteractivePicture( std::string aStr, bool aVal ) { gstrInteractivePictureDisplay = aStr; gstrInteractivePictureStretch = aVal; } + +void MiniGame_Init_Picture() +{ + gMiniGameRenewBackground = TRUE; +} + +UINT32 MiniGame_Handle_Picture() +{ + // coordinates for the background rectangle + if ( gMiniGameRenewBackground ) + { + SGPRect backgroundrect; + backgroundrect.iLeft = 0; + backgroundrect.iTop = 0; + backgroundrect.iRight = ( SCREEN_WIDTH - 0 ); + backgroundrect.iBottom = ( SCREEN_HEIGHT - 0 ); + + // background: display a png picture + DisplayPNGImage( backgroundrect, gstrInteractivePictureDisplay, gstrInteractivePictureStretch ); + + gMiniGameRenewBackground = FALSE; + } + + InvalidateScreen(); + + SetCurrentCursorFromDatabase( VIDEO_NO_CURSOR ); + + return MINIGAME_SCREEN; +} +////////////////////////////////////////////// PICTURE ////////////////////////////////////////////// diff --git a/Tactical/Structure Wrap.cpp b/Tactical/Structure Wrap.cpp index fde21cd5..cbf36b96 100644 --- a/Tactical/Structure Wrap.cpp +++ b/Tactical/Structure Wrap.cpp @@ -599,11 +599,49 @@ UINT16 InteractiveActionPossibleAtGridNo( INT32 sGridNo, UINT8 usLevel, UINT16& { arusStructIndex = 0; - STRUCTURE * pStruct = FindStructure( sGridNo, (STRUCTURE_GENERIC) ); + if ( TileIsOutOfBounds( sGridNo ) ) + return INTERACTIVE_STRUCTURE_NO_ACTION; + + INT32 tmpgridno = 0; + UINT16 structurenumber = 0; + INT32 structuregridno = NOWHERE; + UINT32 uiTileType = 0; + bool properdatafound( false ); + + STRUCTURE* pStruct = FindStructure( sGridNo, ( STRUCTURE_GENERIC ) ); + + // Wall decorations are on the gridno of the wall. This can be problematic if this gridno is 'behind' the wall, because then we might not find a path. + // Thus we need to check for decorations on these walls + if ( !pStruct ) + { + tmpgridno = NewGridNo( sGridNo, DirectionInc( NORTH ) ); + + pStruct = GetStructForLevelNodeOfTypeRange( tmpgridno, FIRSTDECORATIONS, FOURTHDECORATIONS ); + + // if struct is found but has wrong orientation, ignore it + if ( pStruct + && pStruct->ubWallOrientation != OUTSIDE_TOP_LEFT + && pStruct->ubWallOrientation != INSIDE_TOP_LEFT ) + pStruct = NULL; + } + + if ( !pStruct ) + { + tmpgridno = NewGridNo( sGridNo, DirectionInc( WEST ) ); + + pStruct = GetStructForLevelNodeOfTypeRange( tmpgridno, FIRSTDECORATIONS, FOURTHDECORATIONS ); + + // if struct is found but has wrong orientation, ignore it + if ( pStruct + && pStruct->ubWallOrientation != OUTSIDE_TOP_RIGHT + && pStruct->ubWallOrientation != INSIDE_TOP_RIGHT ) + pStruct = NULL; + } + if ( pStruct ) { // if this is a multi-tile structure, be sure to use the base gridno - if ( !(pStruct->fFlags & STRUCTURE_BASE_TILE) ) + if ( !( pStruct->fFlags & STRUCTURE_BASE_TILE ) ) { pStruct = FindBaseStructure( pStruct ); @@ -611,114 +649,141 @@ UINT16 InteractiveActionPossibleAtGridNo( INT32 sGridNo, UINT8 usLevel, UINT16& return INTERACTIVE_STRUCTURE_NO_ACTION; } + structuregridno = pStruct->sGridNo; + structurenumber = pStruct->pDBStructureRef->pDBStructure->usStructureNumber; + LEVELNODE* pNode = FindLevelNodeBasedOnStructure( pStruct->sGridNo, pStruct ); - - if ( pNode ) + + if ( pNode + && GetTileType( pNode->usIndex, &uiTileType ) ) { - UINT16 usIndex = pNode->usIndex; - UINT32 uiTileType = 0; - if ( GetTileType( usIndex, &uiTileType ) ) + properdatafound = true; + } + } + + // With Decals we don't have structuredata for the node. Thus we have to work around that by getting the data from the TileElem + if ( !properdatafound ) + { + tmpgridno = NewGridNo( sGridNo, DirectionInc( NORTH ) ); + + if ( GetTypeRegionIndexForLevelNodeOfTypeRange( tmpgridno, FIRSTWALLDECAL, FOURTHWALLDECAL, uiTileType, structurenumber ) + || GetTypeRegionIndexForLevelNodeOfTypeRange( tmpgridno, FIFTHWALLDECAL, EIGTHWALLDECAL, uiTileType, structurenumber ) ) + { + properdatafound = true; + } + } + + if ( !properdatafound ) + { + tmpgridno = NewGridNo( sGridNo, DirectionInc( WEST ) ); + + if ( GetTypeRegionIndexForLevelNodeOfTypeRange( tmpgridno, FIRSTWALLDECAL, FOURTHWALLDECAL, uiTileType, structurenumber ) + || GetTypeRegionIndexForLevelNodeOfTypeRange( tmpgridno, FIFTHWALLDECAL, EIGTHWALLDECAL, uiTileType, structurenumber ) ) + { + properdatafound = true; + } + } + + if ( properdatafound ) + { + // we loop over each action and determine whether it fits + // multiple actions can fit, we chose whatever fits best + // So, for example, we can set computers everywhere to be hackable with a generic result, and then define more precise results on specific computers + // Other example: With just oen entry, with neither sector nor location set, we can make all water taps drinkable + BOOLEAN foundmatch_precise = FALSE; + BOOLEAN foundmatch_sector = FALSE; + BOOLEAN foundmatch_any = FALSE; + + UINT8 sector = SECTOR( gWorldSectorX, gWorldSectorY ); + + int foundindex = 0; + if ( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[uiTileType][0] ) + { + for ( int i = 0; i < gMaxInteractiveStructureRead; ++i ) { - // we loop over each action and determine whether it fits - // multiple actions can fit, we chose whatever fits best - // So, for example, we can set computers everywhere to be hackable with a generci result, and then define more precise results on specific computers - // Other example: With just oen entry, with neither sector nor location set, we can make all water taps drinkable - BOOLEAN foundmatch_precise = FALSE; - BOOLEAN foundmatch_sector = FALSE; - BOOLEAN foundmatch_any = FALSE; - - UINT8 sector = SECTOR( gWorldSectorX, gWorldSectorY ); - - int foundindex = 0; - if ( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[uiTileType][0] ) + if ( !_strnicmp( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[uiTileType], gInteractiveStructure[i].szTileSetName, 11 ) ) { - for ( int i = 0; i < gMaxInteractiveStructureRead; ++i ) + std::vector tmpvec = gInteractiveStructure[i].tileindexvector; + + std::vector::iterator it = std::find( tmpvec.begin( ), tmpvec.end( ), structurenumber ); + + if ( it != tmpvec.end( ) ) { - if ( !_strnicmp( gTilesets[giCurrentTilesetID].TileSurfaceFilenames[uiTileType], gInteractiveStructure[i].szTileSetName, 11 ) ) + if ( gInteractiveStructure[i].sector == sector && gInteractiveStructure[i].sectorlevel == gbWorldSectorZ ) { - std::vector tmpvec = gInteractiveStructure[i].tileindexvector; + foundmatch_sector = TRUE; + foundindex = i; - std::vector::iterator it = std::find( tmpvec.begin( ), tmpvec.end( ), pStruct->pDBStructureRef->pDBStructure->usStructureNumber ); - - if ( it != tmpvec.end( ) ) + if ( gInteractiveStructure[i].sLevel == usLevel || gInteractiveStructure[i].sLevel == -1 ) { - if ( gInteractiveStructure[i].sector == sector && gInteractiveStructure[i].sectorlevel == gbWorldSectorZ ) + std::vector tmpgridnovec = gInteractiveStructure[i].gridnovector; + + std::vector::iterator it_gridno = std::find( tmpgridnovec.begin( ), tmpgridnovec.end( ), structuregridno ); + + if ( it_gridno != tmpgridnovec.end( ) ) { - foundmatch_sector = TRUE; - foundindex = i; - - if ( gInteractiveStructure[i].sLevel == usLevel || gInteractiveStructure[i].sLevel == -1 ) - { - std::vector tmpgridnovec = gInteractiveStructure[i].gridnovector; - - std::vector::iterator it_gridno = std::find( tmpgridnovec.begin( ), tmpgridnovec.end( ), pStruct->sGridNo ); - - if ( it_gridno != tmpgridnovec.end( ) ) - { - foundmatch_precise = TRUE; - break; - } - } - } - // some actions cen be defined everywhere - else if ( !foundmatch_sector && gInteractiveStructure[i].sector == -1 && gInteractiveStructure[i].sectorlevel == -1 ) - { - foundmatch_any = TRUE; - foundindex = i; + foundmatch_precise = TRUE; + break; } } } - } - } - // otherwise, check first tileset (GENERIC 1) - else if ( gTilesets[0].TileSurfaceFilenames[uiTileType][0] ) - { - for ( int i = 0; i < gMaxInteractiveStructureRead; ++i ) - { - if ( !_strnicmp( gTilesets[0].TileSurfaceFilenames[uiTileType], gInteractiveStructure[i].szTileSetName, 11 ) ) + // some actions cen be defined everywhere + else if ( !foundmatch_sector && gInteractiveStructure[i].sector == -1 && gInteractiveStructure[i].sectorlevel == -1 ) { - std::vector tmpvec = gInteractiveStructure[i].tileindexvector; - - std::vector::iterator it = std::find( tmpvec.begin( ), tmpvec.end( ), pStruct->pDBStructureRef->pDBStructure->usStructureNumber ); - - if ( it != tmpvec.end() ) - { - if ( gInteractiveStructure[i].sector == sector && gInteractiveStructure[i].sectorlevel == gbWorldSectorZ ) - { - foundmatch_sector = TRUE; - foundindex = i; - - if ( gInteractiveStructure[i].sLevel == usLevel || gInteractiveStructure[i].sLevel == -1 ) - { - std::vector tmpgridnovec = gInteractiveStructure[i].gridnovector; - - std::vector::iterator it_gridno = std::find( tmpgridnovec.begin( ), tmpgridnovec.end( ), pStruct->sGridNo ); - - if ( it_gridno != tmpgridnovec.end() ) - { - foundmatch_precise = TRUE; - break; - } - } - } - else if ( !foundmatch_sector && gInteractiveStructure[i].sector == -1 && gInteractiveStructure[i].sectorlevel == -1 ) - { - foundmatch_any = TRUE; - foundindex = i; - } - } + foundmatch_any = TRUE; + foundindex = i; } } } - - if ( foundmatch_any || foundmatch_sector || foundmatch_precise ) - { - arusStructIndex = foundindex; - - return gInteractiveStructure[foundindex].sActionType; - } } } + // otherwise, check first tileset (GENERIC 1) + else if ( gTilesets[0].TileSurfaceFilenames[uiTileType][0] ) + { + for ( int i = 0; i < gMaxInteractiveStructureRead; ++i ) + { + if ( !_strnicmp( gTilesets[0].TileSurfaceFilenames[uiTileType], gInteractiveStructure[i].szTileSetName, 11 ) ) + { + std::vector tmpvec = gInteractiveStructure[i].tileindexvector; + + std::vector::iterator it = std::find( tmpvec.begin( ), tmpvec.end( ), structurenumber ); + + if ( it != tmpvec.end() ) + { + if ( gInteractiveStructure[i].sector == sector && gInteractiveStructure[i].sectorlevel == gbWorldSectorZ ) + { + foundmatch_sector = TRUE; + foundindex = i; + + if ( gInteractiveStructure[i].sLevel == usLevel || gInteractiveStructure[i].sLevel == -1 ) + { + std::vector tmpgridnovec = gInteractiveStructure[i].gridnovector; + + std::vector::iterator it_gridno = std::find( tmpgridnovec.begin( ), tmpgridnovec.end( ), structuregridno ); + + if ( it_gridno != tmpgridnovec.end() ) + { + foundmatch_precise = TRUE; + break; + } + } + } + else if ( !foundmatch_sector && gInteractiveStructure[i].sector == -1 && gInteractiveStructure[i].sectorlevel == -1 ) + { + foundmatch_any = TRUE; + foundindex = i; + } + } + } + } + } + + if ( foundmatch_any || foundmatch_sector || foundmatch_precise ) + { + arusStructIndex = foundindex; + + return gInteractiveStructure[foundindex].sActionType; + } } return INTERACTIVE_STRUCTURE_NO_ACTION; diff --git a/TileEngine/tiledef.cpp b/TileEngine/tiledef.cpp index 0a1b9083..0af32752 100644 --- a/TileEngine/tiledef.cpp +++ b/TileEngine/tiledef.cpp @@ -1098,6 +1098,16 @@ BOOLEAN GetTileFlags( UINT16 usIndex, UINT32 *puiFlags ) return( TRUE ); } +BOOLEAN GetTileRegionIndex( UINT16 usIndex, UINT16& arRegionIndex ) +{ + CHECKF( usIndex != NO_TILE ); + CHECKF( usIndex < giNumberOfTiles ); //lal bugfix + + arRegionIndex = gTileDatabase[usIndex].usRegionIndex; + + return( TRUE ); +} + BOOLEAN GetTileTypeLogicalHeight( UINT32 fType, UINT8 *pubLogHeight ) { *pubLogHeight = gTileTypeLogicalHeight[ fType ]; diff --git a/TileEngine/tiledef.h b/TileEngine/tiledef.h index 40056a11..0ca72926 100644 --- a/TileEngine/tiledef.h +++ b/TileEngine/tiledef.h @@ -230,6 +230,7 @@ BOOLEAN GetTypeSubIndexFromTileIndexChar( UINT32 uiCheckType, UINT16 usIndex, UI BOOLEAN GetTileIndexFromTypeSubIndex( UINT32 uiCheckType, UINT16 usSubIndex, UINT16 *pusTileIndex ); BOOLEAN GetTileType( UINT16 usIndex, UINT32 *puiType ); BOOLEAN GetTileFlags( UINT16 usIndex, UINT32 *puiFlags ); +BOOLEAN GetTileRegionIndex( UINT16 usIndex, UINT16& arRegionIndex ); BOOLEAN GetTileTypeLogicalHeight( UINT32 fType, UINT8 *pubLogHeight ); BOOLEAN AnyHeigherLand( UINT32 iMapIndex, UINT32 uiSrcType, UINT8 *pubLastLevel ); diff --git a/TileEngine/worldman.cpp b/TileEngine/worldman.cpp index c8999433..68880690 100644 --- a/TileEngine/worldman.cpp +++ b/TileEngine/worldman.cpp @@ -1790,6 +1790,61 @@ BOOLEAN RemoveAllStructsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 return fRetVal; } +STRUCTURE* GetStructForLevelNodeOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType ) +{ + if ( TileIsOutOfBounds( iMapIndex ) ) + return NULL; + + UINT32 fTileType; + + LEVELNODE* pLevelNode = gpWorldLevelData[iMapIndex].pStructHead; + + // Look through all structs and Search for type + while ( pLevelNode != NULL ) + { + if ( pLevelNode->usIndex != NO_TILE ) + { + GetTileType( pLevelNode->usIndex, &fTileType ); + + if ( fTileType >= fStartType && fTileType <= fEndType ) + { + return pLevelNode->pStructureData; + } + } + + pLevelNode = pLevelNode->pNext; + } + + return NULL; +} + +bool GetTypeRegionIndexForLevelNodeOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32& arTileType, UINT16& arRegionIndex ) +{ + if ( TileIsOutOfBounds( iMapIndex ) ) + return NULL; + + LEVELNODE* pLevelNode = gpWorldLevelData[iMapIndex].pStructHead; + + // Look through all structs and Search for type + while ( pLevelNode != NULL ) + { + if ( pLevelNode->usIndex != NO_TILE ) + { + GetTileType( pLevelNode->usIndex, &arTileType ); + + if ( arTileType >= fStartType && arTileType <= fEndType + && GetTileRegionIndex( pLevelNode->usIndex, arRegionIndex ) ) + { + return true; + } + } + + pLevelNode = pLevelNode->pNext; + } + + return false; +} + // Flugente: permanently remove structures BOOLEAN RemoveAllRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType ) { diff --git a/TileEngine/worldman.h b/TileEngine/worldman.h index 293ffadb..7e504d12 100644 --- a/TileEngine/worldman.h +++ b/TileEngine/worldman.h @@ -85,6 +85,8 @@ LEVELNODE *ForceStructToTail( INT32 iMapIndex, UINT16 usIndex ); BOOLEAN AddStructToHead( INT32 iMapIndex, UINT16 usIndex ); BOOLEAN TypeExistsInStructLayer( INT32 iMapIndex, UINT32 fType, UINT16 *pusStructIndex ); BOOLEAN RemoveAllStructsOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType ); +STRUCTURE* GetStructForLevelNodeOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType ); +bool GetTypeRegionIndexForLevelNodeOfTypeRange( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType, UINT32& arTileType, UINT16& arRegionIndex ); // Flugente: permanently remove structures BOOLEAN RemoveAllRoofsOfTypeRangeAdjustSaveFile( INT32 iMapIndex, UINT32 fStartType, UINT32 fEndType );