Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
93606b5
Adds replacement CJ clothing models
W3lac3 Jan 18, 2025
0b8106c
Update due to code revision
W3lac3 Jan 25, 2025
363363d
Fixes clothing size crash
W3lac3 Jan 25, 2025
38a520d
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Jan 25, 2025
3b6b736
Create CDirectorySA Class
W3lac3 Jan 26, 2025
5c5619f
Replaces CDirectorySA structure for class in ClothesReplacing
W3lac3 Jan 26, 2025
08606b2
Merge branch 'master' into feature/replace-cj-clothe-model
W3lac3 Jan 29, 2025
0f1ceeb
Adds comments to the CDirectorySA.cpp and CDirectorySA.h files
W3lac3 Jan 29, 2025
18a2f7b
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Feb 5, 2025
fa14863
Update due to code revision
W3lac3 Feb 5, 2025
80a0840
Merge branch 'master' into feature/replace-cj-clothe-model
W3lac3 Feb 7, 2025
81dcfef
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Feb 8, 2025
806a3d5
Update due to code revision
W3lac3 Feb 8, 2025
cdb8902
Update clothes directory memory address
W3lac3 Feb 9, 2025
1fdbd29
Fix crash when turning off resource
W3lac3 Feb 9, 2025
ec1e0bc
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Feb 9, 2025
18f34d6
Update due to code revision
W3lac3 Feb 9, 2025
102369b
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Feb 11, 2025
9403ec5
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Feb 14, 2025
a2f6218
Merge remote-tracking branch 'upstream/master' into feature/replace-c…
W3lac3 Feb 15, 2025
a185b76
Fix invalid return in CDirectorySAInterface::GetModelStreamingSize
W3lac3 Feb 15, 2025
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
40 changes: 40 additions & 0 deletions Client/game_sa/CDirectorySA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "StdInc.h"
#include "CDirectorySA.h"

DirectoryInfo* CDirectorySA::GetModelEntry(ushort modelId)
{
if (m_nNumEntries <= 0)
return nullptr;

DirectoryInfo* entry = m_pEntries + modelId;

if (!entry)
return nullptr;

return entry;
}

bool CDirectorySA::SetModelStreamingSize(ushort modelId, uint16 size)
{
DirectoryInfo* entry = GetModelEntry(modelId);

if (!entry)
return false;

if (entry->m_nStreamingSize == size)
return false;

entry->m_nStreamingSize = size;
return true;
}


uint16 CDirectorySA::GetModelStreamingSize(ushort modelId)
{
DirectoryInfo* entry = GetModelEntry(modelId);

if (!entry)
return false;

return entry->m_nStreamingSize;
}
23 changes: 23 additions & 0 deletions Client/game_sa/CDirectorySA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <SharedUtil.IntTypes.h>

struct DirectoryInfo
{
uint32 m_nOffset;
uint16 m_nStreamingSize;
uint16 m_nSizeInArchive;
char m_szName[24];
};

class CDirectorySA
{
public:
DirectoryInfo* GetModelEntry(ushort modelId);
bool SetModelStreamingSize(ushort modelId, uint16 size);
uint16 GetModelStreamingSize(ushort modelId);

private:
DirectoryInfo* m_pEntries{};
uint32 m_nCapacity{};
uint32 m_nNumEntries{};
bool m_bOwnsEntries{};
};
50 changes: 38 additions & 12 deletions Client/game_sa/CRenderWareSA.ClothesReplacing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "StdInc.h"
#include "CGameSA.h"
#include "CDirectorySA.h"
#include "gamesa_renderware.h"

extern CGameSA* pGame;
Expand All @@ -28,8 +29,10 @@ namespace
uint uiLoadflag; // 0-not loaded 2-requested 3-loaded 1-processed
};

std::map<ushort, char*> ms_ReplacementClothesFileDataMap;
bool bClothesReplacementChanged = false;
std::map<ushort, char*> ms_ReplacementClothesFileDataMap;
std::map<ushort, uint16> ms_OriginalStreamingSizesMap;

bool bClothesReplacementChanged = false;

struct SPlayerImgItem
{
Expand All @@ -45,44 +48,67 @@ namespace
uint uiArraySize;
};

DWORD FUNC_CStreamingConvertBufferToObject = 0x40C6B0;
int iReturnFileId;
char* pReturnBuffer;
DWORD FUNC_CStreamingConvertBufferToObject = 0x40C6B0;
CDirectorySA* CLOTHES_DIRECTORY = *reinterpret_cast<CDirectorySA**>(0x5A419B);
int iReturnFileId;
char* pReturnBuffer;


uint32_t GetSizeInBlocks(uint32_t size)
{
auto div = std::div(size, 2048);
return (div.quot + (div.rem ? 1 : 0));
}

uint32_t GetSizeInBlocks(uint64_t size)
{
return GetSizeInBlocks((uint32_t)size);
}
} // namespace

////////////////////////////////////////////////////////////////
//
// CRenderWareSA::ClothesAddReplacementTxd
// CRenderWareSA::ClothesAddReplacement
//
// Add replacement txd for a clothing component
// Add replacement txd/dff for a clothing component
//
////////////////////////////////////////////////////////////////
void CRenderWareSA::ClothesAddReplacementTxd(char* pFileData, ushort usFileId)
void CRenderWareSA::ClothesAddReplacement(char* pFileData, size_t fileSize, ushort usFileId)
{
if (!pFileData)
return;

if (pFileData != MapFindRef(ms_ReplacementClothesFileDataMap, usFileId))
{
MapSet(ms_ReplacementClothesFileDataMap, usFileId, pFileData);
MapSet(ms_OriginalStreamingSizesMap, usFileId, CLOTHES_DIRECTORY->GetModelStreamingSize(usFileId));
CLOTHES_DIRECTORY->SetModelStreamingSize(usFileId, GetSizeInBlocks(fileSize));

bClothesReplacementChanged = true;
}
}

////////////////////////////////////////////////////////////////
//
// CRenderWareSA::ClothesRemoveReplacementTxd
// CRenderWareSA::ClothesRemoveReplacement
//
// Remove replacement txd for a clothing component
// Remove replacement txd/dff for a clothing component
//
////////////////////////////////////////////////////////////////
void CRenderWareSA::ClothesRemoveReplacementTxd(char* pFileData)
void CRenderWareSA::ClothesRemoveReplacement(char* pFileData)
{
if (!pFileData)
return;

for (std::map<ushort, char*>::iterator iter = ms_ReplacementClothesFileDataMap.begin(); iter != ms_ReplacementClothesFileDataMap.end();)
{
if (iter->second == pFileData)
{
uint16 originalStreamingSize = MapFindRef(ms_OriginalStreamingSizesMap, iter->first);

if (originalStreamingSize)
CLOTHES_DIRECTORY->SetModelStreamingSize(iter->first, originalStreamingSize);

ms_ReplacementClothesFileDataMap.erase(iter++);
bClothesReplacementChanged = true;
}
Expand Down Expand Up @@ -110,7 +136,7 @@ bool CRenderWareSA::HasClothesReplacementChanged()
// CStreaming_RequestModel_Mid
//
// If request is for a file inside player.img (imgId 5)
// then maybe switch to replacement txd file data
// then maybe switch to replacement txd/dff file data
//
////////////////////////////////////////////////////////////////
__declspec(noinline) bool _cdecl OnCStreaming_RequestModel_Mid(int flags, SImgGTAItemInfo* pImgGTAInfo)
Expand Down
4 changes: 2 additions & 2 deletions Client/game_sa/CRenderWareSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class CRenderWareSA : public CRenderWare
bool ModelInfoTXDLoadTextures(SReplacementTextures* pReplacementTextures, const SString& strFilename, const SString& buffer, bool bFilteringEnabled);
bool ModelInfoTXDAddTextures(SReplacementTextures* pReplacementTextures, ushort usModelId);
void ModelInfoTXDRemoveTextures(SReplacementTextures* pReplacementTextures);
void ClothesAddReplacementTxd(char* pFileData, ushort usFileId);
void ClothesRemoveReplacementTxd(char* pFileData);
void ClothesAddReplacement(char* pFileData, size_t fileSize, ushort usFileId);
void ClothesRemoveReplacement(char* pFileData);
bool HasClothesReplacementChanged();

// Reads and parses a TXD file specified by a path (szTXD)
Expand Down
25 changes: 25 additions & 0 deletions Client/mods/deathmatch/logic/CClientDFF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ bool CClientDFF::DoReplaceModel(unsigned short usModel, bool bAlphaTransparency)
if (!CClientDFFManager::IsReplacableModel(usModel))
return false;

if (CClientPlayerClothes::IsValidModel(usModel))
return ReplaceClothes(usModel);

// Get clump loaded for this model id
RpClump* pClump = GetLoadedClump(usModel);

Expand Down Expand Up @@ -268,6 +271,12 @@ void CClientDFF::InternalRestoreModel(unsigned short usModel)
m_pManager->GetObjectManager()->RestreamObjects(usModel);
g_pGame->GetModelInfo(usModel)->RestreamIPL();
}
// Is This a clothe ID?
else if (CClientPlayerClothes::IsValidModel(usModel))
{
g_pGame->GetRenderWare()->ClothesRemoveReplacement(m_RawDataBuffer.data());
return;
}
else
return;

Expand Down Expand Up @@ -296,6 +305,22 @@ void CClientDFF::InternalRestoreModel(unsigned short usModel)
}
}

bool CClientDFF::ReplaceClothes(ushort usModel)
{
if (m_RawDataBuffer.empty() && m_bIsRawData)
return false;

if (m_RawDataBuffer.empty())
{
if (!FileLoad(std::nothrow, m_strDffFilename, m_RawDataBuffer))
return false;
}

m_Replaced.push_back(usModel);
g_pGame->GetRenderWare()->ClothesAddReplacement(m_RawDataBuffer.data(), m_RawDataBuffer.size(), usModel - CLOTHES_MODEL_ID_FIRST);
return true;
}

bool CClientDFF::ReplaceObjectModel(RpClump* pClump, ushort usModel, bool bAlphaTransparency)
{
// Stream out all the object models with matching ID.
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CClientDFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class CClientDFF final : public CClientEntity
void UnloadDFF();
void InternalRestoreModel(unsigned short usModel);

bool ReplaceClothes(ushort usModel);
bool ReplaceObjectModel(RpClump* pClump, ushort usModel, bool bAlphaTransparency);
bool ReplaceVehicleModel(RpClump* pClump, ushort usModel, bool bAlphaTransparency);
bool ReplaceWeaponModel(RpClump* pClump, ushort usModel, bool bAlphaTransparency);
Expand Down
3 changes: 2 additions & 1 deletion Client/mods/deathmatch/logic/CClientDFFManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ CClientDFF* CClientDFFManager::GetElementThatReplaced(unsigned short usModel, CC
bool CClientDFFManager::IsReplacableModel(unsigned short usModel)
{
// Either a vehicle model or an object model
return CClientObjectManager::IsValidModel(usModel) || CClientVehicleManager::IsValidModel(usModel) || CClientPlayerManager::IsValidModel(usModel);
return CClientObjectManager::IsValidModel(usModel) || CClientVehicleManager::IsValidModel(usModel) || CClientPlayerManager::IsValidModel(usModel) ||
CClientPlayerClothes::IsValidModel(usModel);
}

bool CClientDFFManager::RestoreModel(unsigned short usModel)
Expand Down
5 changes: 5 additions & 0 deletions Client/mods/deathmatch/logic/CClientPlayerClothes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,8 @@ const int CClientPlayerClothes::GetClothingGroupMax(unsigned char ucType)

return 0;
}

bool CClientPlayerClothes::IsValidModel(unsigned short usModel)
{
return usModel >= CLOTHES_MODEL_ID_FIRST && usModel <= CLOTHES_MODEL_ID_LAST;
}
2 changes: 1 addition & 1 deletion Client/mods/deathmatch/logic/CClientPlayerClothes.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class CClientPlayerClothes

static const SPlayerClothing* GetClothingGroup(unsigned char ucType);
static const int GetClothingGroupMax(unsigned char ucType);

static bool IsValidModel(unsigned short usModel);
private:
static const SPlayerClothing* GetClothing(const char* szTexture, const char* szModel, unsigned char ucType);

Expand Down
6 changes: 3 additions & 3 deletions Client/mods/deathmatch/logic/CClientTXD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CClientTXD::~CClientTXD()
}

// Remove us from all the clothes replacement doo dah
g_pGame->GetRenderWare()->ClothesRemoveReplacementTxd(m_FileData.data());
g_pGame->GetRenderWare()->ClothesRemoveReplacement(m_FileData.data());
}

bool CClientTXD::Load(bool isRaw, SString input, bool enableFiltering)
Expand Down Expand Up @@ -75,8 +75,8 @@ bool CClientTXD::Import(unsigned short usModelID)
return false;
}
m_bUsingFileDataForClothes = true;
// Note: ClothesAddReplacementTxd uses the pointer from m_FileData, so don't touch m_FileData until matching ClothesRemove call
g_pGame->GetRenderWare()->ClothesAddReplacementTxd(m_FileData.data(), usModelID - CLOTHES_MODEL_ID_FIRST);
// Note: ClothesAddReplacement uses the pointer from m_FileData, so don't touch m_FileData until matching ClothesRemove call
g_pGame->GetRenderWare()->ClothesAddReplacement(m_FileData.data(), m_FileData.size(), usModelID - CLOTHES_MODEL_ID_FIRST);
return true;
}
else
Expand Down
4 changes: 2 additions & 2 deletions Client/sdk/game/CRenderWare.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ class CRenderWare
bool bFilteringEnabled) = 0;
virtual bool ModelInfoTXDAddTextures(SReplacementTextures* pReplacementTextures, ushort usModelId) = 0;
virtual void ModelInfoTXDRemoveTextures(SReplacementTextures* pReplacementTextures) = 0;
virtual void ClothesAddReplacementTxd(char* pFileData, ushort usFileId) = 0;
virtual void ClothesRemoveReplacementTxd(char* pFileData) = 0;
virtual void ClothesAddReplacement(char* pFileData, size_t fileSize, ushort usFileId) = 0;
virtual void ClothesRemoveReplacement(char* pFileData) = 0;
virtual bool HasClothesReplacementChanged() = 0;
virtual RwTexDictionary* ReadTXD(const SString& strFilename, const SString& buffer) = 0;
virtual RpClump* ReadDFF(const SString& strFilename, const SString& buffer, unsigned short usModelID, bool bLoadEmbeddedCollisions) = 0;
Expand Down
Loading