Skip to content

Commit

Permalink
v4.0.0.806
Browse files Browse the repository at this point in the history
* Fixed menu options not working on My Cars menu when backed out from Backroom.
+ [EXPERIMENTAL] Added 2 new paint types (Traffic & Cop) to the Car Paint menu.
* The game no longer quits to freeroam from the customization menu when TestCareerCustomization is enabled.
* Fixed an issue where Presitter overrides customization records if they are also referenced by invalid car records.
  • Loading branch information
nlgxzef committed Jul 15, 2023
1 parent 85a0127 commit 46b3d32
Show file tree
Hide file tree
Showing 10 changed files with 417 additions and 17 deletions.
7 changes: 6 additions & 1 deletion CarCustomizeManager.h
Expand Up @@ -169,6 +169,11 @@ void __declspec(naked) IsLockedCodeCaveVisual()
}
}

bool __fastcall CarCustomizeManager_IsCategoryNew(DWORD* _CarCustomizeManager, void* EDX_Unused, unsigned int MenuID)
{
return CarCustomizeManager_IsCategoryNew_Game(_CarCustomizeManager, MenuID);
}

bool __fastcall CarCustomizeManager_AreAllRimsStock(DWORD* _CarCustomizeManager, void* EDX_Unused)
{
DWORD* StockFrontWheel = CarCustomizeManager_GetStockCarPart((DWORD*)_gCarCustomizeManager, 66); // FRONT_WHEEL
Expand All @@ -183,7 +188,7 @@ bool __fastcall CarCustomizeManager_AreAllRimsStock(DWORD* _CarCustomizeManager,
return IsFrontStock && IsRearStock;
}

bool __fastcall CarCustomizeManager_IsCareerMode_CheckTCC(DWORD* _CarCustomizeManager, void* EDX_Unused)
bool CarCustomizeManager_IsCareerMode_CheckTCC()
{
bool result = 1;
bool Test = !*(bool*)g_bTestCareerCustomization;
Expand Down
129 changes: 129 additions & 0 deletions CustomizeMain.h
Expand Up @@ -204,4 +204,133 @@ void __fastcall CustomizeMain_BuildOptionsList(DWORD* CustomizeMain, void* EDX_U
GetCarTextOptionHash(CarINI, GeneralINI, "Names", "Visual", "CO_VISUAL"),
0x803); // Visuals
}
}

void __fastcall CustomizeMain_SwitchRooms(DWORD* _CustomizeMain, void* EDX_Unused)
{
bool InBackroom; // bl
DWORD* TheIconScroller; // esi
int CurrIndex; // ebp
DWORD* TheFEManager; // eax
int GarageType; // [esp-4h] [ebp-18h]

InBackroom = CustomizeIsInBackRoom() == 0;
CustomizeSetInBackRoom(InBackroom);
CustomizeMain_SetTitle(_CustomizeMain, InBackroom);
TheIconScroller = _CustomizeMain + 11;

CurrIndex = _CustomizeMain[14] ? (*(int(__thiscall**)(DWORD*, DWORD))(*TheIconScroller + 36))(_CustomizeMain + 11, _CustomizeMain[14]) : 0; // IconScroller::GetOptionIndex

cFEng_QueuePackageMessage(*(int**)cFEng_mInstance, InBackroom ? 0xA1CAFF8D : 0x5C01C5, (const char*)_CustomizeMain[4], 0);

if (InBackroom) GarageType = 4;
else
{
cFEng_QueuePackageMessage(*(int**)cFEng_mInstance, 0x5C01C5, (const char*)_CustomizeMain[4], 0);
GarageType = CarCustomizeManager_IsCareerMode_CheckTCC() ? 3 : 1;
}

TheFEManager = FEManager_Get();
FEManager_SetGarageType(TheFEManager, GarageType);
CustomizeMain_SetScreenNames();
(*(void(__thiscall**)(DWORD*))(*TheIconScroller + 12))(_CustomizeMain + 11); // IconScroller::RemoveAll
(*(void(__thiscall**)(DWORD*))(*TheIconScroller + 60))(_CustomizeMain + 11); // IconScroller::AddInitialBookEnds
CustomizeMain_BuildOptionsList(_CustomizeMain, EDX_Unused);
if (*((BYTE*)_CustomizeMain + 297))
{
*((BYTE*)_CustomizeMain + 284) = 0;
*((BYTE*)_CustomizeMain + 281) = 1;
*((BYTE*)_CustomizeMain + 282) = 0;
_CustomizeMain[68] = 0;
}
(*(void(__thiscall**)(DWORD*, int))(*TheIconScroller + 64))(_CustomizeMain + 11, CurrIndex); // IconScroller::SetInitialPos
(*(void(__thiscall**)(DWORD*))(*_CustomizeMain + 12))(_CustomizeMain); // CustomizeMain::RefreshHeader
}

void __fastcall CustomizeMain_NotificationMessage(DWORD* _CustomizeMain, void* EDX_Unused, DWORD Message, DWORD* FEObject, DWORD param1, DWORD param2)
{
int NumMarkers; // eax
int JoyPort; // al

DWORD* GarageMainScreen = FEngFindScreen("GarageMain.fng");
DWORD* FEDatabase = *(DWORD**)_FEDatabase;
bool TestCareerCustomization = *(bool*)g_bTestCareerCustomization;
BYTE* MemoryCard_s_pThis = *(BYTE**)_MemoryCard_s_pThis;

if (!CustomizeIsInBackRoom() || Message != 0x911AB364) CustomizeCategoryScreen_NotificationMessage(_CustomizeMain, Message, FEObject, param1, param2);

switch (Message)
{
case 0x911AB364: // PAD_BACK
if (CustomizeIsInBackRoom())
{
CustomizeMain_SwitchRooms(_CustomizeMain, EDX_Unused);
}
else
{
cFEng_QueuePackageMessage(*(int**)cFEng_mInstance, 0x6D5D86A1, (const char*)_CustomizeMain[4], 0);
if (CarCustomizeManager_IsCareerMode_CheckTCC()) // Is Career Mode
{
if (GarageMainScreen) *(DWORD*)(GarageMainScreen + 34) = -1;
JoyPort = FEngMapJoyParamToJoyport(param1);
cFrontendDatabase_SetPlayersJoystickPort(FEDatabase, 0, JoyPort);
if (!cFrontendDatabase_IsCarStableDirty(FEDatabase))
*((BYTE*)MemoryCard_s_pThis + 43) = 1;
*(int*)_CarViewer_haveLoadedOnce = 0;
RaceStarter_StartCareerFreeRoam();
}
CarCustomizeManager_RelinquishControl((DWORD*)_gCarCustomizeManager);
}
break;

case 0x1265ECE9:
GarageMainScreen_UpdateCurrentCameraView(GarageMainScreen, 0);
cFEng_QueuePackageMessage(*(int**)cFEng_mInstance, CustomizeIsInBackRoom() ? 0xA1CAFF8D : 0x5C01C5, (const char*)_CustomizeMain[4], 0);
break;

case 0x34DC1BEC: // OK to MISSING_PARTS_MARKER dialog
NumMarkers = (MyCarsBackroom || TestCareerCustomization) ? 1 : FEMarkerManager_GetNumCustomizeMarkers((DWORD*)TheFEMarkerManager);
if (NumMarkers > _CustomizeMain[107]) CustomizeMain_SwitchRooms(_CustomizeMain, EDX_Unused);
_CustomizeMain[107] = 0;
break;

case 0xC519BFC4: // PAD_BUTTON5
if (CarCustomizeManager_IsCareerMode_CheckTCC() || MyCarsBackroom)
{
NumMarkers = (MyCarsBackroom || TestCareerCustomization) ? 1 : FEMarkerManager_GetNumCustomizeMarkers((DWORD*)TheFEMarkerManager);
if (!CustomizeIsInBackRoom() && NumMarkers)
{
_CustomizeMain[107] = 0;
if (FEMarkerManager_IsMarkerAvailable((DWORD*)TheFEMarkerManager, 4, 0) && !CarCustomizeManager_CanInstallJunkman((DWORD*)_gCarCustomizeManager, 5))
{
++_CustomizeMain[107];
}
if (FEMarkerManager_IsMarkerAvailable((DWORD*)TheFEMarkerManager, 3, 0) && !CarCustomizeManager_CanInstallJunkman((DWORD*)_gCarCustomizeManager, 6))
{
++_CustomizeMain[107];
}
if (_CustomizeMain[107] > 0)
{
DialogInterface_ShowOneButton((const char*)_CustomizeMain[4], "", 2, 0x417B2601, 0x34DC1BEC, 0x3B3E83); // COMMON_OK, 0x34DC1BEC (OK message??), MISSING_PARTS_MARKER
return;
}
CustomizeMain_SwitchRooms(_CustomizeMain, EDX_Unused);
}
}
break;
}
}

void __fastcall CustomizeMain_RefreshHeader(DWORD* _CustomizeMain, void* EDX_Unused)
{
CustomizeCategoryScreen_RefreshHeader(_CustomizeMain);

DWORD* BackroomGroup = (DWORD*)FEngFindObject((const char*)_CustomizeMain[4], 0xDC6EE739); // BACKROOM_GROUP
int NumMarkers = (MyCarsBackroom || *(bool*)g_bTestCareerCustomization) ? 1 : FEMarkerManager_GetNumCustomizeMarkers((DWORD*)TheFEMarkerManager);

if ((CarCustomizeManager_IsCareerMode_CheckTCC() || MyCarsBackroom) && !CustomizeIsInBackRoom() && NumMarkers) FEngSetVisible(BackroomGroup);
else FEngSetInvisible(BackroomGroup);

DWORD* v4 = (DWORD*)_CustomizeMain[14];
if (v4) CarCustomizeManager_IsCategoryNew((DWORD*)_gCarCustomizeManager, EDX_Unused, (WORD)v4[20]);
}
223 changes: 222 additions & 1 deletion CustomizePaint.h
Expand Up @@ -50,6 +50,12 @@ void __fastcall CustomizePaint_RefreshHeader(DWORD* CustomizePaint, void* EDX_Un
case 2:
PaintCategoryNameHash = 0xB715070A; // CP_FILTER_PEARL
break;
case 3:
PaintCategoryNameHash = bStringHash("CP_FILTER_TRAFFIC"); // CP_FILTER_RIM
break;
case 4:
PaintCategoryNameHash = bStringHash("CP_FILTER_COP"); // CP_FILTER_RIM
break;
}
SelectedPaintCarPart = *(DWORD**)((*(int(__thiscall**)(DWORD*))(*CustomizePaint + 20))(CustomizePaint) + 12);
SelectedPaintSelectablePart = (DWORD*)(*(int(__thiscall**)(DWORD*))(*CustomizePaint + 20))(CustomizePaint); // GetSelectedPart
Expand Down Expand Up @@ -166,9 +172,224 @@ void __fastcall CustomizePaint_RefreshHeader(DWORD* CustomizePaint, void* EDX_Un
BYTE Green = (BYTE)CarPart_GetAppliedAttributeIParam(SelectedPaintCarPart, bStringHash("GREEN"), 0);
BYTE Blue = (BYTE)CarPart_GetAppliedAttributeIParam(SelectedPaintCarPart, bStringHash("BLUE"), 0);

FEngSetColor_obj(*(DWORD**)(PaintSlot + 3), Blue | (((unsigned __int8)Green | ((Red | 0xFFFFFF00) << 8)) << 8));
FEngSetColor_obj(*(DWORD**)(PaintSlot + 3), Blue | ((Green | ((Red | 0xFFFFFF00) << 8)) << 8));
}
}
}
}

DWORD __fastcall CustomizePaint_CalcBrandHash(DWORD* _CustomizePaint, void* EDX_Unused, DWORD* ActivePaint)
{
DWORD result;

int MenuID = _CustomizePaint[82];
int PaintScrollerIndex = _CustomizePaint[111];

switch (MenuID)
{
case 0x301:
switch (PaintScrollerIndex)
{
case 4:
result = 0x9B21; // COP
break;
case 3:
result = 0x19E0ECBE; // TRAFFIC
break;
case 2:
result = 0x3797533; // PEARL
break;
case 1:
result = 0x3437A52; // METAL
break;
case 0:
result = 0x2DAAB07; // GLOSS
break;
default:
result = CarPart_GetAppliedAttributeUParam(ActivePaint, 0xEBB03E66, 0); // BRAND_NAME
break;
}
break;

case 0x303:
result = 0xDA27; // RIM
break;

default:
result = 0x3E871F1; // VINYL
break;
}

return result;
}

DWORD __fastcall CustomizePaint_CalcIndexFromBrandHash(DWORD* _CustomizePaint, void* EDX_Unused, DWORD BrandHash)
{
DWORD result = 0;

switch (BrandHash)
{
case 0x9B21:
result = 4; // COP
break;
case 0x19E0ECBE:
result = 3; // TRAFFIC
break;
case 0x3797533:
result = 2; // PEARL
break;
case 0x3437A52:
result = 1; // METAL
break;
case 0x2DAAB07:
default:
result = 0; // GLOSS
break;
}

_CustomizePaint[111] = result;
return result;
}

void __fastcall CustomizePaint_BuildSwatchList(DWORD* _CustomizePaint, void* EDX_Unused, unsigned int CarSlotID)
{
int VinylColorLayer; // eax
DWORD* ShowcasePaintPart; // ecx
unsigned int BrandHash; // eax MAPDST
bool IsIndexInvalid; // zf
DWORD* ListItem; // eax
DWORD* PaintSelectablePart; // eax
DWORD* NextPaintSelectablePart; // eax
int Unlockhash; // ebp
DWORD* PaintDatum; // esi
DWORD* pl_itm_nxt; // ecx MAPDST
DWORD* pl_itm; // edx MAPDST
DWORD* pl_itm_prv; // eax MAPDST
DWORD* SelectablePartFromDatum; // edi
DWORD* pItemIndex; // eax
DWORD* ArraySlot; // ebp
DWORD* PaintPart; // edi MAPDST
int AttrNameHash; // eax MAPDST
unsigned __int8 r; // al MAPDST
unsigned __int8 b; // al
DWORD InitialPosition; // eax
int i; // [esp+Ch] [ebp-24h]
DWORD* ActivePaint; // [esp+10h] [ebp-20h] MAPDST
DWORD* PartList[2]; // [esp+1Ch] [ebp-14h] BYREF
int v38; // [esp+2Ch] [ebp-4h]
unsigned __int8 g; // [esp+34h] [ebp+4h]

ArrayScroller_ClearData(_CustomizePaint + 136);
if (CarSlotID < 79 || CarSlotID > 81)
goto LABEL_11;
if (CarSlotID == 79)
VinylColorLayer = 0;
else
VinylColorLayer = CarSlotID == 80 ? 1 : 2;
ShowcasePaintPart = *(DWORD**)(_Showcase_FromColor + 4 * VinylColorLayer);
if (!ShowcasePaintPart)
goto LABEL_11;
if (_CustomizePaint[VinylColorLayer + 181])
goto LABEL_11;
ActivePaint = (DWORD*)ShowcasePaintPart[3];
if (!ActivePaint)
LABEL_11:
ActivePaint = (DWORD*)CarCustomizeManager_GetActivePartFromSlot(
(DWORD*)_gCarCustomizeManager,
CarSlotID);
BrandHash = CustomizePaint_CalcBrandHash(_CustomizePaint, EDX_Unused, ActivePaint);
IsIndexInvalid = _CustomizePaint[111] == -1;
if (IsIndexInvalid) CustomizePaint_CalcIndexFromBrandHash(_CustomizePaint, EDX_Unused, BrandHash);

PartList[0] = (DWORD*)PartList;
PartList[1] = (DWORD*)PartList;
v38 = 0;
CarCustomizeManager_GetCarPartList((DWORD*)_gCarCustomizeManager, CarSlotID, (DWORD*)PartList, 0);
ListItem = PartList[0];
for (i = 0; (DWORD**)PartList[0] != PartList; ListItem = PartList[0])
{
if (ListItem)
PaintSelectablePart = ListItem - 1;
else
PaintSelectablePart = 0;
if (CarPart_GetAppliedAttributeUParam((DWORD*)PaintSelectablePart[3], 0xEBB03E66, 0) == BrandHash)
{
if (PartList[0])
NextPaintSelectablePart = PartList[0] - 1;
else
NextPaintSelectablePart = 0;
Unlockhash = CarCustomizeManager_GetUnlockHash(
(DWORD*)_gCarCustomizeManager,
_CustomizePaint[82],
*(BYTE*)(NextPaintSelectablePart[3] + 5) >> 5);
PaintDatum = (DWORD*)j_malloc(0x20u);
v38 = 1;
if (PaintDatum)
{
pl_itm_nxt = (DWORD*)*PartList[0];
pl_itm = PartList[0];
pl_itm_prv = (DWORD*)PartList[0][1];
*pl_itm_prv = *PartList[0];
pl_itm_nxt[1] = (DWORD)pl_itm_prv;
SelectablePartFromDatum = pl_itm - 1;
ArrayDatum_ArrayDatum(PaintDatum, 0xC6AFDD7E, 0);
*PaintDatum = _CustomizePaintDatum_vtable;
PaintDatum[6] = (DWORD)SelectablePartFromDatum;
PaintDatum[7] = Unlockhash;
}
else
{
PaintDatum = 0;
}
pItemIndex = &_CustomizePaint[_CustomizePaint[111]%3 + 112];
IsIndexInvalid = *pItemIndex == -1;
v38 = 0;
if (IsIndexInvalid && ActivePaint == *(DWORD**)(PaintDatum[6] + 12))
*pItemIndex = i;
ArrayScroller_AddDatum((_CustomizePaint + 136), PaintDatum);
ArraySlot = (DWORD*)ArrayScroller_GetSlotAt((_CustomizePaint + 136), i);
if (ArraySlot)
{
PaintPart = *(DWORD**)(PaintDatum[6] + 12);
AttrNameHash = bStringHash("RED");
r = CarPart_GetAppliedAttributeIParam(PaintPart, AttrNameHash, 0);
PaintPart = *(DWORD**)(PaintDatum[6] + 12);
AttrNameHash = bStringHash("GREEN");
g = CarPart_GetAppliedAttributeIParam(PaintPart, AttrNameHash, 0);
PaintPart = *(DWORD**)(PaintDatum[6] + 12);
AttrNameHash = bStringHash("BLUE");
b = CarPart_GetAppliedAttributeIParam(PaintPart, AttrNameHash, 0);
FEngSetColor_obj((DWORD*)ArraySlot[3], b | ((g | ((r | 0xFFFFFF00) << 8)) << 8));
}
++i;
}
else // remove from list
{
pl_itm_nxt = (DWORD*)*PartList[0];
pl_itm = PartList[0];
pl_itm_prv = (DWORD*)PartList[0][1];
*pl_itm_prv = *PartList[0];
pl_itm_nxt[1] = (DWORD)pl_itm_prv;
if (pl_itm != (DWORD*)4)
(*(void(__thiscall**)(DWORD*, int)) * (pl_itm - 1))(pl_itm - 1, 1);
}
}
if (*(int*)_Showcase_FromIndex)
{
_CustomizePaint[_CustomizePaint[111]%3 + 112] = *(int*)_Showcase_FromIndex - 1;
ArrayScroller_SetInitialPosition((_CustomizePaint + 136), *(int*)_Showcase_FromIndex - 1);
*(int*)_Showcase_FromIndex = 0;
}
else
{
InitialPosition = (DWORD)&_CustomizePaint[_CustomizePaint[111]%3 + 112];
if (*(DWORD*)InitialPosition == -1)
*(DWORD*)InitialPosition = 0;
ArrayScroller_SetInitialPosition(
(_CustomizePaint + 136),
_CustomizePaint[_CustomizePaint[111]%3 + 112]);
}
(*(void(__thiscall**)(DWORD*))(*_CustomizePaint + 12))(_CustomizePaint);// RefreshHeader
v38 = -1;
bTList_SelectablePart_dtor((int**)PartList);
}

0 comments on commit 46b3d32

Please sign in to comment.