diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index ddb5e4a1b..e5679ba33 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -555,6 +555,16 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto return 1; } +void CGraphics_Threaded::CopyTextureBufferSub(uint8_t* pDestBuffer, uint8_t* pSourceBuffer, size_t FullWidth, size_t FullHeight, size_t ColorChannelCount, size_t SubOffsetX, size_t SubOffsetY, size_t SubCopyWidth, size_t SubCopyHeight) +{ + for(size_t Y = 0; Y < SubCopyHeight; ++Y) + { + size_t ImgOffset = ((SubOffsetY + Y) * FullWidth * ColorChannelCount) + (SubOffsetX * ColorChannelCount); + size_t CopySize = SubCopyWidth * ColorChannelCount; + mem_copy(&pDestBuffer[ImgOffset], &pSourceBuffer[ImgOffset], CopySize); + } +} + void CGraphics_Threaded::KickCommandBuffer() { m_pBackend->RunBuffer(m_pCommandBuffer); diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index d0779b0af..968b2e122 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -751,6 +751,8 @@ public: virtual IGraphics::CTextureHandle LoadTexture(const char *pFilename, int StorageType, int StoreFormat, int Flags); virtual int LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType); + void CopyTextureBufferSub(uint8_t* pDestBuffer, uint8_t* pSourceBuffer, size_t FullWidth, size_t FullHeight, size_t ColorChannelCount, size_t SubOffsetX, size_t SubOffsetY, size_t SubCopyWidth, size_t SubCopyHeight) override; + void ScreenshotDirect(); virtual void TextureSet(CTextureHandle TextureID); diff --git a/src/engine/graphics.h b/src/engine/graphics.h index 5a19047c9..98ac411ad 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -193,6 +193,9 @@ public: virtual int LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType) = 0; + // destination and source buffer require to have the same width and height + virtual void CopyTextureBufferSub(uint8_t* pDestBuffer, uint8_t* pSourceBuffer, size_t FullWidth, size_t FullHeight, size_t ColorChannelCount, size_t SubOffsetX, size_t SubOffsetY, size_t SubCopyWidth, size_t SubCopyHeight) = 0; + virtual int UnloadTexture(CTextureHandle Index) = 0; virtual CTextureHandle LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags, const char *pTexName = NULL) = 0; virtual int LoadTextureRawSub(CTextureHandle TextureID, int x, int y, int Width, int Height, int Format, const void *pData) = 0; diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index 64381d98f..d61920a74 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -18,7 +18,7 @@ CMapImages::CMapImages(int TextureSize) { m_Count = 0; m_TextureScale = TextureSize; - m_EntitiesIsLoaded = false; + mem_zero(m_EntitiesIsLoaded, sizeof(m_EntitiesIsLoaded)); m_SpeedupArrowIsLoaded = false; mem_zero(m_aTextureUsedByTileOrQuadLayerFlag, sizeof(m_aTextureUsedByTileOrQuadLayerFlag)); @@ -111,36 +111,201 @@ void CMapImages::LoadBackground(class CLayers *pLayers, class IMap *pMap) OnMapLoadImpl(pLayers, pMap); } -IGraphics::CTextureHandle CMapImages::GetEntities() +bool CMapImages::HasFrontLayer() { - // DDNet default to prevent delay in seeing entities - const char *pEntities = "ddnet"; - if(GameClient()->m_GameInfo.m_EntitiesDDNet) - pEntities = "ddnet"; - else if(GameClient()->m_GameInfo.m_EntitiesDDRace) - pEntities = "ddrace"; - else if(GameClient()->m_GameInfo.m_EntitiesRace) - pEntities = "race"; - else if (GameClient()->m_GameInfo.m_EntitiesBW) - pEntities = "blockworlds"; - else if(GameClient()->m_GameInfo.m_EntitiesFNG) - pEntities = "fng"; - else if(GameClient()->m_GameInfo.m_EntitiesVanilla) - pEntities = "vanilla"; + return GameClient()->m_GameInfo.m_EntitiesDDNet || GameClient()->m_GameInfo.m_EntitiesDDRace; +} - if(!m_EntitiesIsLoaded || m_pEntitiesGameType != pEntities) +bool CMapImages::HasSpeedupLayer() +{ + return GameClient()->m_GameInfo.m_EntitiesDDNet || GameClient()->m_GameInfo.m_EntitiesDDRace; +} + +bool CMapImages::HasSwitchLayer() +{ + return GameClient()->m_GameInfo.m_EntitiesDDNet || GameClient()->m_GameInfo.m_EntitiesDDRace; +} + +bool CMapImages::HasTeleLayer() +{ + return GameClient()->m_GameInfo.m_EntitiesDDNet || GameClient()->m_GameInfo.m_EntitiesDDRace; +} + +bool CMapImages::HasTuneLayer() +{ + return GameClient()->m_GameInfo.m_EntitiesDDNet || GameClient()->m_GameInfo.m_EntitiesDDRace; +} + +IGraphics::CTextureHandle CMapImages::GetEntities(EMapImageEntityLayerType EntityLayerType) +{ + const char *pEntities = "ddnet"; + EMapImageModType EntitiesModType = MAP_IMAGE_MOD_TYPE_UNKNOWN; + bool EntitesAreMasked = !GameClient()->m_GameInfo.m_DontMaskEntities; + + if(GameClient()->m_GameInfo.m_EntitiesDDNet && EntitesAreMasked) { + pEntities = "ddnet"; + EntitiesModType = MAP_IMAGE_MOD_TYPE_DDNET; + } + else if(GameClient()->m_GameInfo.m_EntitiesDDRace && EntitesAreMasked) + { + pEntities = "ddrace"; + EntitiesModType = MAP_IMAGE_MOD_TYPE_DDRACE; + } + else if(GameClient()->m_GameInfo.m_EntitiesRace) + { + pEntities = "race"; + EntitiesModType = MAP_IMAGE_MOD_TYPE_RACE; + } + else if (GameClient()->m_GameInfo.m_EntitiesBW) + { + pEntities = "blockworlds"; + EntitiesModType = MAP_IMAGE_MOD_TYPE_BLOCKWORLDS; + } + else if(GameClient()->m_GameInfo.m_EntitiesFNG) + { + pEntities = "fng"; + EntitiesModType = MAP_IMAGE_MOD_TYPE_FNG; + } + else if(GameClient()->m_GameInfo.m_EntitiesVanilla) + { + pEntities = "vanilla"; + EntitiesModType = MAP_IMAGE_MOD_TYPE_VANILLA; + } + + if(!m_EntitiesIsLoaded[EntitiesModType]) + { + m_EntitiesIsLoaded[EntitiesModType] = true; + + bool WasUnknwon = EntitiesModType == MAP_IMAGE_MOD_TYPE_UNKNOWN; + char aPath[64]; str_format(aPath, sizeof(aPath), "editor/entities_clear/%s.png", pEntities); - if(m_EntitiesTextures >= 0) - Graphics()->UnloadTexture(m_EntitiesTextures); + bool GameTypeHasFrontLayer = HasFrontLayer() || WasUnknwon; + bool GameTypeHasSpeedupLayer = HasSpeedupLayer() || WasUnknwon; + bool GameTypeHasSwitchLayer = HasSwitchLayer() || WasUnknwon; + bool GameTypeHasTeleLayer = HasTeleLayer() || WasUnknwon; + bool GameTypeHasTuneLayer = HasTuneLayer() || WasUnknwon; + int TextureLoadFlag = Graphics()->HasTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE; - m_EntitiesTextures = Graphics()->LoadTexture(aPath, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, TextureLoadFlag); - m_EntitiesIsLoaded = true; - m_pEntitiesGameType = pEntities; + + CImageInfo ImgInfo; + if(Graphics()->LoadPNG(&ImgInfo, aPath, IStorage::TYPE_ALL) && ImgInfo.m_Width > 0 && ImgInfo.m_Height > 0) + { + size_t ColorChannelCount = 0; + if(ImgInfo.m_Format == CImageInfo::FORMAT_ALPHA) + ColorChannelCount = 1; + else if(ImgInfo.m_Format == CImageInfo::FORMAT_RGB) + ColorChannelCount = 3; + else if(ImgInfo.m_Format == CImageInfo::FORMAT_RGBA) + ColorChannelCount = 4; + + size_t BuildImageSize = ColorChannelCount * (size_t)ImgInfo.m_Width * (size_t)ImgInfo.m_Height; + + uint8_t* pTmpImgData = (uint8_t*)ImgInfo.m_pData; + uint8_t* pBuildImgData = (uint8_t*)malloc(BuildImageSize); + + // build game layer + for(size_t n = 0; n < MAP_IMAGE_ENTITY_LAYER_TYPE_COUNT; ++n) + { + bool BuildThisLayer = true; + if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_FRONT && !GameTypeHasFrontLayer) + BuildThisLayer = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_SPEEDUP && !GameTypeHasSpeedupLayer) + BuildThisLayer = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH && !GameTypeHasSwitchLayer) + BuildThisLayer = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_TELE && !GameTypeHasTeleLayer) + BuildThisLayer = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_TUNE && !GameTypeHasTuneLayer) + BuildThisLayer = false; + + dbg_assert(m_EntitiesTextures[EntitiesModType][n] == -1, "This should not happen."); + + if(BuildThisLayer) + { + // set everything transparent + mem_zero(pBuildImgData, BuildImageSize); + + for(size_t i = 0; i < 256; ++i) + { + bool ValidTile = i != 0; + size_t TileIndex = i; + if(EntitiesModType == MAP_IMAGE_MOD_TYPE_DDNET || EntitiesModType == MAP_IMAGE_MOD_TYPE_DDRACE) + { + if(EntitiesModType == MAP_IMAGE_MOD_TYPE_DDNET || TileIndex != TILE_BOOST) + { + if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_GAME && !IsValidGameTile((int)TileIndex)) + ValidTile = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_FRONT && !IsValidFrontTile((int)TileIndex)) + ValidTile = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_SPEEDUP && !IsValidSpeedupTile((int)TileIndex)) + ValidTile = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH) + { + if(!IsValidSwitchTile((int)TileIndex)) + ValidTile = false; + else + { + if(TileIndex == TILE_SWITCHTIMEDOPEN) + TileIndex = 8; + } + } + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_TELE && !IsValidTeleTile((int)TileIndex)) + ValidTile = false; + else if(n == (size_t)MAP_IMAGE_ENTITY_LAYER_TYPE_TUNE && !IsValidTuneTile((int)TileIndex)) + ValidTile = false; + } + } + else if((EntitiesModType == MAP_IMAGE_MOD_TYPE_RACE) && IsCreditsTile((int)TileIndex)) + { + ValidTile = false; + } + else if((EntitiesModType == MAP_IMAGE_MOD_TYPE_FNG) && IsCreditsTile((int)TileIndex)) + { + ValidTile = false; + } + else if((EntitiesModType == MAP_IMAGE_MOD_TYPE_VANILLA) && IsCreditsTile((int)TileIndex)) + { + ValidTile = false; + } + /*else if((EntitiesModType == MAP_IMAGE_MOD_TYPE_RACE_BLOCKWORLD) && ...) + { + ValidTile = false; + }*/ + + size_t X = TileIndex % 16; + size_t Y = TileIndex / 16; + + size_t CopyWidth = (size_t)ImgInfo.m_Width / 16; + size_t CopyHeight = (size_t)ImgInfo.m_Height / 16; + if(ValidTile) + { + Graphics()->CopyTextureBufferSub(pBuildImgData, pTmpImgData, (size_t)ImgInfo.m_Width, (size_t)ImgInfo.m_Height, ColorChannelCount, X * CopyWidth, Y * CopyHeight, CopyWidth, CopyHeight); + } + } + + m_EntitiesTextures[EntitiesModType][n] = Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, pBuildImgData, ImgInfo.m_Format, TextureLoadFlag, aPath); + } + else + { + if(m_TransparentTexture == -1) + { + // set everything transparent + mem_zero(pBuildImgData, BuildImageSize); + + m_TransparentTexture = Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, pBuildImgData, ImgInfo.m_Format, TextureLoadFlag, aPath); + } + m_EntitiesTextures[EntitiesModType][n] = m_TransparentTexture; + } + } + + free(pBuildImgData); + } } - return m_EntitiesTextures; + + return m_EntitiesTextures[EntitiesModType][(size_t)EntityLayerType]; } IGraphics::CTextureHandle CMapImages::GetSpeedupArrow() diff --git a/src/game/client/components/mapimages.h b/src/game/client/components/mapimages.h index 028473e92..a80fd6192 100644 --- a/src/game/client/components/mapimages.h +++ b/src/game/client/components/mapimages.h @@ -4,6 +4,31 @@ #define GAME_CLIENT_COMPONENTS_MAPIMAGES_H #include +enum EMapImageEntityLayerType +{ + MAP_IMAGE_ENTITY_LAYER_TYPE_GAME = 0, + MAP_IMAGE_ENTITY_LAYER_TYPE_FRONT, + MAP_IMAGE_ENTITY_LAYER_TYPE_SPEEDUP, + MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH, + MAP_IMAGE_ENTITY_LAYER_TYPE_TELE, + MAP_IMAGE_ENTITY_LAYER_TYPE_TUNE, + + MAP_IMAGE_ENTITY_LAYER_TYPE_COUNT, +}; + +enum EMapImageModType +{ + MAP_IMAGE_MOD_TYPE_UNKNOWN = 0, + MAP_IMAGE_MOD_TYPE_DDNET, + MAP_IMAGE_MOD_TYPE_DDRACE, + MAP_IMAGE_MOD_TYPE_RACE, + MAP_IMAGE_MOD_TYPE_BLOCKWORLDS, + MAP_IMAGE_MOD_TYPE_FNG, + MAP_IMAGE_MOD_TYPE_VANILLA, + + MAP_IMAGE_MOD_TYPE_COUNT, +}; + class CMapImages : public CComponent { friend class CBackground; @@ -12,7 +37,11 @@ class CMapImages : public CComponent int m_aTextureUsedByTileOrQuadLayerFlag[64]; // 0: nothing, 1(as flag): tile layer, 2(as flag): quad layer int m_Count; - const char *m_pEntitiesGameType; + bool HasFrontLayer(); + bool HasSpeedupLayer(); + bool HasSwitchLayer(); + bool HasTeleLayer(); + bool HasTuneLayer(); public: CMapImages(); CMapImages(int ImageSize); @@ -26,7 +55,7 @@ public: void LoadBackground(class CLayers *pLayers, class IMap *pMap); // DDRace - IGraphics::CTextureHandle GetEntities(); + IGraphics::CTextureHandle GetEntities(EMapImageEntityLayerType EntityLayerType); IGraphics::CTextureHandle GetSpeedupArrow(); IGraphics::CTextureHandle GetOverlayBottom(); @@ -37,13 +66,14 @@ public: int GetTextureScale(); private: - bool m_EntitiesIsLoaded; + bool m_EntitiesIsLoaded[MAP_IMAGE_MOD_TYPE_COUNT]; bool m_SpeedupArrowIsLoaded; - IGraphics::CTextureHandle m_EntitiesTextures; + IGraphics::CTextureHandle m_EntitiesTextures[MAP_IMAGE_MOD_TYPE_COUNT][MAP_IMAGE_ENTITY_LAYER_TYPE_COUNT]; IGraphics::CTextureHandle m_SpeedupArrowTexture; IGraphics::CTextureHandle m_OverlayBottomTexture; IGraphics::CTextureHandle m_OverlayTopTexture; IGraphics::CTextureHandle m_OverlayCenterTexture; + IGraphics::CTextureHandle m_TransparentTexture; int m_TextureScale; void InitOverlayTextures(); diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 67f83e389..0f79d1c70 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -589,23 +589,17 @@ void CMapLayers::OnMapLoad() { Index = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Index; Flags = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Flags; - if(!GameClient()->m_GameInfo.m_DontMaskEntities && !IsValidGameTile(Index)) - Index = 0; } if(IsFrontLayer) { Index = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Index; Flags = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Flags; - if(!GameClient()->m_GameInfo.m_DontMaskEntities && !IsValidFrontTile(Index)) - Index = 0; } if(IsSwitchLayer) { Flags = 0; Index = ((CSwitchTile*)pTiles)[y*pTMap->m_Width+x].m_Type; - if(!IsValidSwitchTile(Index)) - Index = 0; - else if(CurOverlay == 0) + if(CurOverlay == 0) { Flags = ((CSwitchTile*)pTiles)[y*pTMap->m_Width+x].m_Flags; if(Index == TILE_SWITCHTIMEDOPEN) Index = 8; @@ -619,9 +613,7 @@ void CMapLayers::OnMapLoad() { Index = ((CTeleTile*)pTiles)[y*pTMap->m_Width+x].m_Type; Flags = 0; - if(!IsValidTeleTile(Index)) - Index = 0; - else if(CurOverlay == 1) + if(CurOverlay == 1) { if(Index != TILE_TELECHECKIN && Index != TILE_TELECHECKINEVIL) Index = ((CTeleTile*)pTiles)[y*pTMap->m_Width+x].m_Number; @@ -633,7 +625,7 @@ void CMapLayers::OnMapLoad() Index = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Type; Flags = 0; AngleRotate = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width + x].m_Angle; - if(!IsValidSpeedupTile(Index) || ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Force == 0) + if(((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Force == 0) Index = 0; else if(CurOverlay == 1) Index = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Force; @@ -643,8 +635,6 @@ void CMapLayers::OnMapLoad() if(IsTuneLayer) { Index = ((CTuneTile*)pTiles)[y*pTMap->m_Width+x].m_Type; - if(!IsValidTuneTile(Index)) - Index = 0; Flags = 0; } } else @@ -1684,7 +1674,7 @@ void CMapLayers::OnRender() if(!IsGameLayer) Graphics()->TextureClear(); else - Graphics()->TextureSet(m_pImages->GetEntities()); + Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_GAME)); } else Graphics()->TextureSet(m_pImages->Get(pTMap->m_Image)); @@ -1784,7 +1774,7 @@ void CMapLayers::OnRender() else if(Render && g_Config.m_ClOverlayEntities && IsFrontLayer) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; - Graphics()->TextureSet(m_pImages->GetEntities()); + Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_FRONT)); CTile *pFrontTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Front); unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Front); @@ -1811,7 +1801,7 @@ void CMapLayers::OnRender() else if(Render && g_Config.m_ClOverlayEntities && IsSwitchLayer) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; - Graphics()->TextureSet(m_pImages->GetEntities()); + Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH)); CSwitchTile *pSwitchTiles = (CSwitchTile *)m_pLayers->Map()->GetData(pTMap->m_Switch); unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Switch); @@ -1844,7 +1834,7 @@ void CMapLayers::OnRender() else if(Render && g_Config.m_ClOverlayEntities && IsTeleLayer) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; - Graphics()->TextureSet(m_pImages->GetEntities()); + Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_TELE)); CTeleTile *pTeleTiles = (CTeleTile *)m_pLayers->Map()->GetData(pTMap->m_Tele); unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Tele); @@ -1875,7 +1865,7 @@ void CMapLayers::OnRender() else if(Render && g_Config.m_ClOverlayEntities && IsSpeedupLayer) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; - Graphics()->TextureSet(m_pImages->GetEntities()); + Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_SPEEDUP)); CSpeedupTile *pSpeedupTiles = (CSpeedupTile *)m_pLayers->Map()->GetData(pTMap->m_Speedup); unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Speedup); @@ -1913,7 +1903,7 @@ void CMapLayers::OnRender() else if(Render && g_Config.m_ClOverlayEntities && IsTuneLayer) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; - Graphics()->TextureSet(m_pImages->GetEntities()); + Graphics()->TextureSet(m_pImages->GetEntities(MAP_IMAGE_ENTITY_LAYER_TYPE_TUNE)); CTuneTile *pTuneTiles = (CTuneTile *)m_pLayers->Map()->GetData(pTMap->m_Tune); unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Tune); diff --git a/src/game/mapitems.cpp b/src/game/mapitems.cpp index 3eceb38a2..927f29271 100644 --- a/src/game/mapitems.cpp +++ b/src/game/mapitems.cpp @@ -111,3 +111,17 @@ bool IsRotatableTile(int Index) || Index - ENTITY_OFFSET == ENTITY_CRAZY_SHOTGUN ); } + +bool IsCreditsTile(int TileIndex) +{ + return ( + (TILE_CREDITS_1 == TileIndex) + || (TILE_CREDITS_2 == TileIndex) + || (TILE_CREDITS_3 == TileIndex) + || (TILE_CREDITS_4 == TileIndex) + || (TILE_CREDITS_5 == TileIndex) + || (TILE_CREDITS_6 == TileIndex) + || (TILE_CREDITS_7 == TileIndex) + || (TILE_CREDITS_8 == TileIndex) + ); +} diff --git a/src/game/mapitems.h b/src/game/mapitems.h index 1dca846d9..b8d634f3b 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -484,5 +484,6 @@ bool IsValidSwitchTile(int Index); bool IsValidTuneTile(int Index); bool IsValidEntity(int Index); bool IsRotatableTile(int Index); +bool IsCreditsTile(int TileIndex); #endif