diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/Frontend.cpp | 2 | ||||
-rw-r--r-- | src/core/PlayerInfo.cpp | 24 | ||||
-rw-r--r-- | src/core/PlayerInfo.h | 1 | ||||
-rw-r--r-- | src/core/PlayerSkin.cpp | 166 | ||||
-rw-r--r-- | src/core/PlayerSkin.h | 16 |
5 files changed, 205 insertions, 4 deletions
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index effcb0b4..30b80634 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -2383,7 +2383,7 @@ void CMenuManager::SwitchToNewScreen(int32 screen) // Set player skin. if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { - CPlayerSkin::BeginFrontEndSkinEdit(); + CPlayerSkin::BeginFrontendSkinEdit(); m_bSkinsFound = false; } diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 8c505eb4..dc72848d 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -4,9 +4,9 @@ #include "PlayerInfo.h" #include "Frontend.h" #include "Vehicle.h" +#include "PlayerSkin.h" WRAPPER void CPlayerInfo::MakePlayerSafe(bool) { EAXJMP(0x4A1400); } -WRAPPER void CPlayerInfo::LoadPlayerSkin() { EAXJMP(0x4A1700); } WRAPPER void CPlayerInfo::AwardMoneyForExplosion(CVehicle *vehicle) { EAXJMP(0x4A15F0); } WRAPPER void CPlayerInfo::Process(void) { EAXJMP(0x49FD30); } @@ -22,3 +22,25 @@ CVector& CPlayerInfo::GetPos() return m_pPed->m_pMyVehicle->GetPosition(); return m_pPed->GetPosition(); } + +void CPlayerInfo::LoadPlayerSkin() +{
+ DeletePlayerSkin();
+
+ m_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);
+ if (!m_pSkinTexture)
+ m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME); +} + +void CPlayerInfo::DeletePlayerSkin() +{
+ if (m_pSkinTexture) {
+ RwTextureDestroy(m_pSkinTexture);
+ m_pSkinTexture = NULL;
+ } +} + +STARTPATCHES +InjectHook(0x4A1700, &CPlayerInfo::LoadPlayerSkin, PATCH_JUMP); +InjectHook(0x4A1750, &CPlayerInfo::DeletePlayerSkin, PATCH_JUMP); +ENDPATCHES diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 29290f6e..f0b879ee 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -68,6 +68,7 @@ public: void MakePlayerSafe(bool); void LoadPlayerSkin(); + void DeletePlayerSkin(); void AwardMoneyForExplosion(CVehicle *vehicle); void SetPlayerSkin(char* skin); CVector& GetPos(); diff --git a/src/core/PlayerSkin.cpp b/src/core/PlayerSkin.cpp index 1c9ca2c6..6290351a 100644 --- a/src/core/PlayerSkin.cpp +++ b/src/core/PlayerSkin.cpp @@ -1,5 +1,169 @@ #include "common.h" #include "patcher.h" +#include "main.h" #include "PlayerSkin.h" +#include "TxdStore.h" +#include "rtbmp.h" +#include "ClumpModelInfo.h" +#include "VisibilityPlugins.h" +#include "World.h" +#include "PlayerInfo.h" +#include "CdStream.h" +#include "FileMgr.h" +#include "Directory.h" +#include "RwHelper.h" +#include "Timer.h" +#include "Lights.h" -WRAPPER void CPlayerSkin::BeginFrontEndSkinEdit() { EAXJMP(0x59BC70); } +int CPlayerSkin::m_txdSlot; + +void
+FindPlayerDff(uint32 &offset, uint32 &size)
+{
+ int file;
+ CDirectory::DirectoryInfo info;
+
+ file = CFileMgr::OpenFile("models\\gta3.dir", "rb");
+
+ do {
+ if (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))
+ return;
+ } while (strcmpi("player.dff", info.name));
+
+ offset = info.offset;
+ size = info.size;
+} + +void
+LoadPlayerDff(void)
+{
+ RwStream *stream;
+ RwMemory mem;
+ uint32 offset, size;
+ uint8 *buffer;
+ bool streamWasAdded = false;
+
+ if (!CdStreamGetNumImages()) {
+ CdStreamAddImage("models\\gta3.img");
+ streamWasAdded = true;
+ }
+
+ FindPlayerDff(offset, size);
+ buffer = (uint8*)RwMallocAlign(size << 11, 2048);
+ CdStreamRead(0, buffer, offset, size);
+ CdStreamSync(0);
+
+ mem.start = buffer;
+ mem.length = size << 11;
+ stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
+
+ if (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
+ gpPlayerClump = RpClumpStreamRead(stream);
+
+ RwStreamClose(stream, &mem);
+ RwFreeAlign(buffer);
+
+ if (streamWasAdded)
+ CdStreamRemoveImages();
+} + +void
+CPlayerSkin::Initialise(void)
+{
+ m_txdSlot = CTxdStore::AddTxdSlot("skin");
+ CTxdStore::Create(m_txdSlot);
+ CTxdStore::AddRef(m_txdSlot);
+} + +void
+CPlayerSkin::Shutdown(void)
+{
+ CTxdStore::RemoveTxdSlot(m_txdSlot);
+} + +RwTexture *
+CPlayerSkin::GetSkinTexture(const char *texName)
+{
+ RwTexture *tex;
+ RwRaster *raster;
+ int32 width, height, depth, format;
+
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(m_txdSlot);
+ tex = RwTextureRead(texName, NULL);
+ CTxdStore::PopCurrentTxd();
+ if (tex) return tex;
+
+ if (!strcmp(DEFAULT_SKIN_NAME, texName))
+ sprintf(gString, "models\\generic\\player.bmp");
+ else
+ sprintf(gString, "skins\\%s.bmp", texName);
+
+ if (RwImage *image = RtBMPImageRead(gString)) {
+ RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
+ raster = RwRasterCreate(width, height, depth, format);
+ RwRasterSetFromImage(raster, image);
+
+ tex = RwTextureCreate(raster);
+ RwTextureSetName(tex, texName);
+ RwTextureSetFilterMode(tex, rwFILTERLINEAR); // filtering bugfix from VC
+ RwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);
+
+ RwImageDestroy(image);
+ }
+ return tex;
+} + +void
+CPlayerSkin::BeginFrontendSkinEdit(void)
+{
+ LoadPlayerDff();
+ RpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
+ CWorld::Players[0].LoadPlayerSkin();
+ gOldFov = CDraw::GetFOV();
+ CDraw::SetFOV(30.0f);
+}
+
+void
+CPlayerSkin::EndFrontendSkinEdit(void)
+{
+ RpClumpDestroy(gpPlayerClump);
+ gpPlayerClump = NULL;
+ CDraw::SetFOV(gOldFov);
+}
+
+void
+CPlayerSkin::RenderFrontendSkinEdit(void)
+{
+ static float rotation = 0.0f;
+ RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
+ const RwV3d pos = { 1.35f, 0.35f, 7.725f };
+ const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
+ const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
+ static uint32 LastFlash = 0;
+
+ RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
+
+ if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {
+ rotation += 2.0f;
+ if (rotation > 360.0f)
+ rotation -= 360.0f;
+ LastFlash = CTimer::GetTimeInMillisecondsPauseMode();
+ }
+ RwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);
+ RwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);
+ RwFrameRotate(frame, &axis1, -90.0f, rwCOMBINEPRECONCAT);
+ RwFrameRotate(frame, &axis2, rotation, rwCOMBINEPRECONCAT);
+ RwFrameUpdateObjects(frame);
+ SetAmbientColours(&AmbientColor);
+ RpClumpRender(gpPlayerClump);
+}
+
+STARTPATCHES +InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP); +InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP); +InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP); +InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP); +InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP); +InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/core/PlayerSkin.h b/src/core/PlayerSkin.h index 61e09cdf..2d82ec12 100644 --- a/src/core/PlayerSkin.h +++ b/src/core/PlayerSkin.h @@ -1,7 +1,21 @@ #pragma once +#define DEFAULT_SKIN_NAME "$$\"\"" + +static RpClump *gpPlayerClump;// = *(RpClump**)0x660FF8; +static float gOldFov;// = *(float*)0x660FFC; + +void LoadPlayerDff(void); +void FindPlayerDff(uint32 &offset, uint32 &size); + class CPlayerSkin { + static int m_txdSlot; public: - static void BeginFrontEndSkinEdit(); + static void Initialise(); + static void Shutdown(); + static RwTexture *GetSkinTexture(const char *texName); + static void BeginFrontendSkinEdit(); + static void EndFrontendSkinEdit(); + static void RenderFrontendSkinEdit(); };
\ No newline at end of file |