Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,13 @@ CClientGame::~CClientGame()
discord->UpdatePresence();
}

if (m_pPlayerMap)
{
m_pPlayerMap->ResetCustomMapImage();
m_pPlayerMap->ResetMapOpacity();
m_pPlayerMap->SetPlayerMapEnabled(true);
}

// Destroy our stuff
SAFE_DELETE(m_pManager); // Will trigger onClientResourceStop

Expand Down
271 changes: 266 additions & 5 deletions Client/mods/deathmatch/logic/CPlayerMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "StdInc.h"

using SharedUtil::CalcMTASAPath;
using SharedUtil::FileExists;
using std::list;

enum
Expand Down Expand Up @@ -61,6 +62,13 @@ CPlayerMap::CPlayerMap(CClientManager* pManager)
m_mapImageTexture = nullptr;
m_playerMarkerTexture = nullptr;

// Custom map image variables
m_ucCustomMapOpacity = 255;
m_bHasCustomMapOpacity = false;
m_pCustomOpacityResource = nullptr;
m_bRadarMapDisabled = false;
m_pRadarMapDisabledResource = nullptr;

// Create all map textures
CreateAllTextures();

Expand Down Expand Up @@ -109,6 +117,20 @@ CPlayerMap::~CPlayerMap()
// Delete our images
SAFE_RELEASE(m_mapImageTexture);
SAFE_RELEASE(m_playerMarkerTexture);

// Release custom map textures
for (int i = 0; i < 2; i++)
{
if (m_customMapData[i].bHasCustomMap && m_customMapData[i].pTexture && !m_customMapData[i].pTextureElement)
{
SAFE_RELEASE(m_customMapData[i].pTexture);
}
m_customMapData[i].pTexture = nullptr;
m_customMapData[i].pTextureElement = nullptr;
m_customMapData[i].pResource = nullptr;
m_customMapData[i].bHasCustomMap = false;
}

for (uint i = 0; i < m_markerTextureList.size(); i++)
SAFE_RELEASE(m_markerTextureList[i]);
m_markerTextureList.clear();
Expand All @@ -118,7 +140,7 @@ CPlayerMap::~CPlayerMap()
void CPlayerMap::CreateOrUpdateMapTexture()
{
const std::uint32_t mapSize = MAP_IMAGE_SIZES[m_playerMapImageIndex];
const SString fileName("MTA\\cgui\\images\\map_%d.png", mapSize);
const SString fileName("MTA\\cgui\\images\\radar\\map_%d.png", mapSize);

auto* newTexture = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(CalcMTASAPath(fileName), nullptr, false, mapSize, mapSize, RFORMAT_DXT1);
if (!newTexture)
Expand Down Expand Up @@ -156,13 +178,17 @@ void CPlayerMap::CreateAllTextures()
{
// Create the map texture
m_playerMapImageIndex = g_pCore->GetCVars()->GetValue<std::size_t>("mapimage");
m_defaultMapImageIndex = m_playerMapImageIndex;
CreateOrUpdateMapTexture();

// Create the player blip texture
CreatePlayerBlipTexture();

// Create the other marker textures
CreateMarkerTextures();

// Try to load a user custom map if it exists
LoadUserCustomMapIfExists();
}
catch (const std::exception& e)
{
Expand Down Expand Up @@ -292,20 +318,43 @@ void CPlayerMap::DoRender()
// Render if showing and textures are all loaded
if (isMapShowing && !m_failedToLoadTextures)
{
// Check if the current size texture element is still valid
std::size_t currentIdx = m_playerMapImageIndex;
if (m_customMapData[currentIdx].bHasCustomMap && m_customMapData[currentIdx].pTextureElement)
{
if (m_customMapData[currentIdx].pTextureElement->IsBeingDeleted())
{
// Delete the texture, reset
m_customMapData[currentIdx].pTexture = nullptr;
m_customMapData[currentIdx].bHasCustomMap = false;
m_customMapData[currentIdx].strPath = "";
m_customMapData[currentIdx].pResource = nullptr;
m_customMapData[currentIdx].pTextureElement = nullptr;

// Try to load a user custom map if it exists
LoadUserCustomMapIfExists();
}
}

// Get the alpha value from the settings
int mapAlpha;
g_pCore->GetCVars()->Get("mapalpha", mapAlpha);
uchar mapAlpha = GetMapOpacity();
const SColorARGB mapColor(mapAlpha, 255, 255, 255);

// Update the image if the user changed it via a setting
auto mapImageIndex = g_pCore->GetCVars()->GetValue<std::size_t>("mapimage");
if (mapImageIndex != m_playerMapImageIndex)
{
UpdateOrRevertMapTexture(mapImageIndex);
if (!m_customMapData[m_playerMapImageIndex].bHasCustomMap)
LoadUserCustomMapIfExists();
}

g_pCore->GetGraphics()->DrawTexture(m_mapImageTexture, static_cast<float>(m_iMapMinX), static_cast<float>(m_iMapMinY),
m_fMapSize / m_mapImageTexture->m_uiSizeX, m_fMapSize / m_mapImageTexture->m_uiSizeY, 0.0f, 0.0f, 0.0f, mapColor);
CTextureItem* pMapTexture = m_customMapData[m_playerMapImageIndex].bHasCustomMap
? m_customMapData[m_playerMapImageIndex].pTexture
: m_mapImageTexture;

g_pCore->GetGraphics()->DrawTexture(pMapTexture, static_cast<float>(m_iMapMinX), static_cast<float>(m_iMapMinY),
m_fMapSize / pMapTexture->m_uiSizeX, m_fMapSize / pMapTexture->m_uiSizeY, 0.0f, 0.0f, 0.0f, mapColor);

// Grab the info for the local player blip
CVector2D vecLocalPos;
Expand Down Expand Up @@ -399,6 +448,9 @@ void CPlayerMap::DoRender()

void CPlayerMap::SetPlayerMapEnabled(bool show)
{
if (m_bRadarMapDisabled && show)
return;

bool alreadyEnabled = (m_bIsPlayerMapEnabled || m_bForcedState);
bool definitiveShow = (show || m_bForcedState);
if (alreadyEnabled != definitiveShow)
Expand Down Expand Up @@ -718,6 +770,9 @@ void CPlayerMap::SetAttachedToLocalPlayer(bool bIsAttachedToLocal)

bool CPlayerMap::IsPlayerMapShowing()
{
if (m_bRadarMapDisabled)
return false;

return ((m_bIsPlayerMapEnabled || m_bForcedState) && m_mapImageTexture && m_playerMarkerTexture && (!g_pCore->GetConsole()->IsVisible() && !g_pCore->IsMenuVisible()));
}

Expand Down Expand Up @@ -752,3 +807,209 @@ SString CPlayerMap::GetBoundKeyName(const SString& strCommand)
return strCommand;
return pCommandBind->boundKey->szKey;
}
bool CPlayerMap::SetCustomMapImage(const std::string& strTexturePath, uint uiSize, CResource* pResource)
{
if (uiSize != 1024 && uiSize != 2048)
throw std::invalid_argument("Invalid map size (must be 1024 or 2048)");

if (!pResource)
return false;

std::size_t idx = (uiSize == 1024) ? 0 : 1;
SString strFullPath = pResource->GetResourceDirectoryPath() + strTexturePath;

CTextureItem* pNewTexture = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(strFullPath, nullptr, false, uiSize, uiSize, RFORMAT_DXT1);

if (!pNewTexture)
throw std::invalid_argument("Failed to load texture from path: " + strTexturePath);

// Release old texture if it existed and was not element-based
if (!m_customMapData[idx].pTextureElement && m_customMapData[idx].pTexture)
{
SAFE_RELEASE(m_customMapData[idx].pTexture);
m_customMapData[idx].pTexture = nullptr;
}

m_customMapData[idx].pTexture = pNewTexture;
m_customMapData[idx].strPath = strFullPath;
m_customMapData[idx].bHasCustomMap = true;
m_customMapData[idx].pResource = pResource;
m_customMapData[idx].pTextureElement = nullptr;

return true;
}

bool CPlayerMap::SetCustomMapImageFromTexture(CClientTexture* pTexture, uint uiSize, CResource* pResource)
{
if (!pTexture || !pResource)
return false;

if (uiSize != 1024 && uiSize != 2048)
throw std::invalid_argument("Invalid map size (must be 1024 or 2048)");

CTextureItem* pTextureItem = pTexture->GetTextureItem();
if (!pTextureItem)
throw std::invalid_argument("Invalid texture element");

std::size_t idx = (uiSize == 1024) ? 0 : 1;

// If the current map index does not match, update it
if (idx != m_playerMapImageIndex)
{
m_playerMapImageIndex = idx;
try {
CreateOrUpdateMapTexture();
} catch (...) {
// Ignore errors
}
}

// Release old texture if it existed and was not element-based
if (!m_customMapData[idx].pTextureElement && m_customMapData[idx].pTexture)
{
SAFE_RELEASE(m_customMapData[idx].pTexture);
m_customMapData[idx].pTexture = nullptr;
}

m_customMapData[idx].pTexture = pTextureItem;
m_customMapData[idx].strPath = "";
m_customMapData[idx].bHasCustomMap = true;
m_customMapData[idx].pResource = pResource;
m_customMapData[idx].pTextureElement = pTexture;

return true;
}

void CPlayerMap::ResetCustomMapImage(uint uiSize)
{
// If size is 0, reset both sizes
if (uiSize == 0)
{
ResetCustomMapImage(1024);
ResetCustomMapImage(2048);
return;
}

if (uiSize != 1024 && uiSize != 2048)
return;

std::size_t idx = (uiSize == 1024) ? 0 : 1;

if (!m_customMapData[idx].pTextureElement && m_customMapData[idx].pTexture)
{
SAFE_RELEASE(m_customMapData[idx].pTexture);
m_customMapData[idx].pTexture = nullptr;
}

m_customMapData[idx].bHasCustomMap = false;
m_customMapData[idx].strPath = "";
m_customMapData[idx].pResource = nullptr;
m_customMapData[idx].pTextureElement = nullptr;

// Try to load the user custom map if it exists
if (idx == m_playerMapImageIndex)
LoadUserCustomMapIfExists();
}

bool CPlayerMap::SetMapOpacity(uchar ucOpacity, CResource* pResource)
{
m_ucCustomMapOpacity = static_cast<uchar>(Clamp(0, static_cast<int>(ucOpacity), 255));
m_bHasCustomMapOpacity = true;
m_pCustomOpacityResource = pResource;
return true;
}

void CPlayerMap::ResetMapOpacity()
{
m_bHasCustomMapOpacity = false;
m_ucCustomMapOpacity = 255;
m_pCustomOpacityResource = nullptr;
}

uchar CPlayerMap::GetMapOpacity() const
{
if (m_bHasCustomMapOpacity)
return m_ucCustomMapOpacity;

int mapAlpha;
g_pCore->GetCVars()->Get("mapalpha", mapAlpha);
return static_cast<uchar>(Clamp(0, mapAlpha, 255));
}

bool CPlayerMap::SetRadarMapDisabled(bool bDisabled, CResource* pResource)
{
m_bRadarMapDisabled = bDisabled;
m_pRadarMapDisabledResource = pResource;
return true;
}

void CPlayerMap::LoadUserCustomMapIfExists()
{
std::size_t idx = m_playerMapImageIndex;

// If already has a script-set custom map for this size, do not override
if (m_customMapData[idx].bHasCustomMap && m_customMapData[idx].pResource != nullptr)
return;

const std::uint32_t mapSize = MAP_IMAGE_SIZES[idx];
const SString customFileName = CalcMTASAPath(SString("MTA\\cgui\\images\\radar\\map_%d-custom.png", mapSize));

if (FileExists(customFileName))
{
CTextureItem* pCustomTexture = g_pCore->GetGraphics()->GetRenderItemManager()->CreateTexture(customFileName, nullptr, false, mapSize, mapSize, RFORMAT_DXT1);

if (pCustomTexture)
{
// Release old texture if it existed and was not element-based
if (!m_customMapData[idx].pTextureElement && m_customMapData[idx].pTexture)
SAFE_RELEASE(m_customMapData[idx].pTexture);

m_customMapData[idx].pTexture = pCustomTexture;
m_customMapData[idx].strPath = customFileName;
m_customMapData[idx].bHasCustomMap = true;
m_customMapData[idx].pResource = nullptr;
m_customMapData[idx].pTextureElement = nullptr;
}
}
}

void CPlayerMap::OnResourceStopping(CResource* pResource)
{
// Check both size custom maps
for (int i = 0; i < 2; i++)
{
if (m_customMapData[i].bHasCustomMap && m_customMapData[i].pResource == pResource)
{
if (!m_customMapData[i].pTextureElement && m_customMapData[i].pTexture)
{
SAFE_RELEASE(m_customMapData[i].pTexture);
m_customMapData[i].pTexture = nullptr;
}
else
{
m_customMapData[i].pTexture = nullptr;
}

m_customMapData[i].bHasCustomMap = false;
m_customMapData[i].strPath = "";
m_customMapData[i].pResource = nullptr;
m_customMapData[i].pTextureElement = nullptr;
}
}

// If the current map size had a custom map, try to load the user custom map
LoadUserCustomMapIfExists();

if (m_bHasCustomMapOpacity && m_pCustomOpacityResource == pResource)
{
m_bHasCustomMapOpacity = false;
m_ucCustomMapOpacity = 255;
m_pCustomOpacityResource = nullptr;
}

if (m_bRadarMapDisabled && m_pRadarMapDisabledResource == pResource)
{
m_bRadarMapDisabled = false;
m_pRadarMapDisabledResource = nullptr;
}
}
Loading