Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds replacement CJ clothing models #3967

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
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"
W3lac3 marked this conversation as resolved.
Show resolved Hide resolved
#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>
W3lac3 marked this conversation as resolved.
Show resolved Hide resolved

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