Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions Client/game_sa/CModelInfoSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,12 @@ class CModelInfoSA : public CModelInfo
return pInterface ? pInterface->pRwObject : NULL;
}

void SetRwObject(RwObject* pRwObject)
{
if (m_pInterface)
m_pInterface->pRwObject = pRwObject;
}

// CModelInfoSA methods
void MakePedModel(const char* szTexture);
void MakeObjectModel(ushort usBaseModelID);
Expand Down
26 changes: 22 additions & 4 deletions Client/game_sa/CVehicleSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,9 +782,25 @@ void CVehicleSA::LockDoors(bool bLocked)
}
}

static DWORD GetCustomUpgradeParentModelID(DWORD dwModelID)
{
CModelInfo* pModelInfo = pGame->GetModelInfo(dwModelID);
if (pModelInfo && pModelInfo->GetParentID() != 0)
{
unsigned int parentID = pModelInfo->GetParentID();
if (parentID >= 1000 && parentID <= 1193)
{
return parentID;
}
}
return dwModelID;
}

void CVehicleSA::AddVehicleUpgrade(DWORD dwModelID)
{
if (dwModelID >= 1000 && dwModelID <= 1193)
DWORD dwActualModelID = GetCustomUpgradeParentModelID(dwModelID);

if (dwActualModelID >= 1000 && dwActualModelID <= 1193)
{
DWORD dwThis = (DWORD)m_pInterface;

Expand All @@ -793,7 +809,7 @@ void CVehicleSA::AddVehicleUpgrade(DWORD dwModelID)
__asm
{
mov ecx, dwThis
push dwModelID
push dwActualModelID
call dwFunc
}
// clang-format on
Expand All @@ -802,14 +818,16 @@ void CVehicleSA::AddVehicleUpgrade(DWORD dwModelID)

void CVehicleSA::RemoveVehicleUpgrade(DWORD dwModelID)
{
DWORD dwActualModelID = GetCustomUpgradeParentModelID(dwModelID);

DWORD dwThis = (DWORD)m_pInterface;
DWORD dwFunc = FUNC_CVehicle_RemoveVehicleUpgrade;

// clang-format off
__asm
{
mov ecx, dwThis
push dwModelID
push dwActualModelID
call dwFunc
}
// clang-format on
Expand All @@ -818,7 +836,7 @@ void CVehicleSA::RemoveVehicleUpgrade(DWORD dwModelID)
// In the case of hydraulics and nitro, this function does not return false and the upgrade is never removed from the array
for (std::int16_t& upgrade : GetVehicleInterface()->m_upgrades)
{
if (upgrade == dwModelID)
if (upgrade == dwModelID || upgrade == dwActualModelID)
{
upgrade = -1;
break;
Expand Down
27 changes: 27 additions & 0 deletions Client/mods/deathmatch/logic/CClientModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ bool CClientModel::Allocate(ushort usParentID)
allocated = true;
}
break;
case eClientModelType::VEHICLE_UPGRADE:
{
if (CVehicleUpgrades::IsUpgrade(usParentID))
{
pModelInfo->MakeObjectModel(usParentID);
return true;
}
break;
}
default:
return false;
}
Expand Down Expand Up @@ -140,6 +149,7 @@ void CClientModel::RestoreEntitiesUsingThisModel()
case eClientModelType::CLUMP:
case eClientModelType::TIMED_OBJECT:
case eClientModelType::VEHICLE:
case eClientModelType::VEHICLE_UPGRADE:
RestoreDFF(pModelInfo);
return;
case eClientModelType::TXD:
Expand Down Expand Up @@ -257,6 +267,23 @@ void CClientModel::RestoreDFF(CModelInfo* pModelInfo)
[usParentID](auto& element) { element.SetModelBlocking(usParentID, 255, 255); });
break;
}
case eClientModelType::VEHICLE_UPGRADE:
{
CClientVehicleManager* pVehicleManager = g_pClientGame->GetManager()->GetVehicleManager();
const auto usParentID = static_cast<unsigned short>(g_pGame->GetModelInfo(m_iModelID)->GetParentID());

// Remove custom upgrade and restore parent
unloadModelsAndCallEvents(pVehicleManager->IterBegin(), pVehicleManager->IterEnd(), usParentID,
[=](auto& element)
{
element.GetUpgrades()->RemoveUpgrade(m_iModelID);
if (usParentID >= 1000 && usParentID <= 1193)
{
element.GetUpgrades()->AddUpgrade(usParentID, false);
}
});
break;
}
}

g_pClientGame->GetManager()->GetDFFManager()->RestoreModel(modelId);
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CClientModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum class eClientModelType
OBJECT,
OBJECT_DAMAGEABLE,
VEHICLE,
VEHICLE_UPGRADE,
TIMED_OBJECT,
CLUMP,
TXD,
Expand Down
64 changes: 59 additions & 5 deletions Client/mods/deathmatch/logic/CVehicleUpgrades.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,30 @@ CVehicleUpgrades::CVehicleUpgrades(CClientVehicle* pVehicle)
m_usLastLocalAddNitroType = 0;
}

static unsigned short GetCustomUpgradeParentModelID(unsigned short usModelID)
{
auto* upgradeModelInfo = g_pGame->GetModelInfo(usModelID);
if (upgradeModelInfo && upgradeModelInfo->GetParentID() != 0)
{
unsigned short parentID = upgradeModelInfo->GetParentID();
if (parentID >= 1000 && parentID <= 1193)
{
return parentID;
}
}
return usModelID;
}

bool CVehicleUpgrades::IsUpgrade(unsigned short usModel)
{
usModel = GetCustomUpgradeParentModelID(usModel);

return (usModel >= 1000 && usModel <= 1193);
}

bool CVehicleUpgrades::IsUpgradeCompatible(unsigned short usUpgrade)
{
unsigned short us = usUpgrade;
unsigned short us = GetCustomUpgradeParentModelID(usUpgrade);
eClientVehicleType vehicleType = m_pVehicle->GetVehicleType();

// No upgrades for trains/boats
Expand Down Expand Up @@ -451,6 +467,9 @@ bool CVehicleUpgrades::IsUpgradeCompatible(unsigned short usUpgrade)

bool CVehicleUpgrades::GetSlotFromUpgrade(unsigned short us, unsigned char& ucSlot)
{
// Check if this is a custom upgrade model
us = GetCustomUpgradeParentModelID(us);

if (us == 1011 || us == 1012 || us == 1111 || us == 1112 || us == 1142 || /* bonet */
us == 1143 || us == 1144 || us == 1145)
{
Expand Down Expand Up @@ -610,18 +629,53 @@ void CVehicleUpgrades::ForceAddUpgrade(unsigned short usUpgrade)
CVehicle* pVehicle = m_pVehicle->GetGameVehicle();
if (pVehicle)
{
// Grab the upgrade model
// Load the upgrade model
CModelInfo* pModelInfo = g_pGame->GetModelInfo(usUpgrade);
if (pModelInfo)
{
if (!g_pGame->IsASyncLoadingEnabled() || !pModelInfo->IsLoaded())
{
// Request and load now
pModelInfo->Request(BLOCKING, "CVehicleUpgrades::ForceAddUpgrade");
}
// Add the upgrade
pVehicle->AddVehicleUpgrade(usUpgrade);

// If this is a custom model with parent ID, swap RwObjects
unsigned short parentID = static_cast<unsigned short>(pModelInfo->GetParentID());
if (parentID != 0 && IsUpgrade(parentID))
{
CModelInfo* pParentModelInfo = g_pGame->GetModelInfo(parentID);
if (pParentModelInfo)
{
if (!g_pGame->IsASyncLoadingEnabled() || !pParentModelInfo->IsLoaded())
{
pParentModelInfo->Request(BLOCKING, "CVehicleUpgrades::ForceAddUpgrade (parent)");
}

// Wait for both to be loaded
if (pModelInfo->IsLoaded() && pParentModelInfo->IsLoaded())
{
RwObject* pCustomRwObject = pModelInfo->GetRwObject();
RwObject* pParentRwObject = pParentModelInfo->GetRwObject();

if (pCustomRwObject && pParentRwObject)
{
// Temporarily swap to custom RwObject ONLY during AddVehicleUpgrade call
pParentModelInfo->SetRwObject(pCustomRwObject);
pVehicle->AddVehicleUpgrade(usUpgrade);
pParentModelInfo->SetRwObject(pParentRwObject);

// Early return since we already added the upgrade
m_SlotStates[ucSlot] = usUpgrade;
if (ucSlot == 12)
m_pVehicle->ResetWheelScale();

return;
}
}
}
}
}

pVehicle->AddVehicleUpgrade(usUpgrade);
}

// Add it to the slot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ ADD_ENUM(eClientModelType::PED, "ped")
ADD_ENUM(eClientModelType::OBJECT, "object")
ADD_ENUM(eClientModelType::OBJECT_DAMAGEABLE, "object-damageable")
ADD_ENUM(eClientModelType::VEHICLE, "vehicle")
ADD_ENUM(eClientModelType::VEHICLE_UPGRADE, "vehicle-upgrade")
ADD_ENUM(eClientModelType::TIMED_OBJECT, "timed-object")
ADD_ENUM(eClientModelType::CLUMP, "clump")
IMPLEMENT_ENUM_CLASS_END("client-model-type")
Expand Down
4 changes: 4 additions & 0 deletions Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,7 @@ int CLuaEngineDefs::EngineRequestModel(lua_State* luaVM)
constexpr int defaultClumpParentId = 3425;
constexpr int defaultObjectParentId = 1337;
constexpr int defaultDamageableObjectParentId = 994;
constexpr int defaultVehicleUpgradeId = 1025;

switch (eModelType)
{
Expand All @@ -982,6 +983,9 @@ int CLuaEngineDefs::EngineRequestModel(lua_State* luaVM)
case eClientModelType::VEHICLE:
iParentID = static_cast<int>(VehicleType::VT_LANDSTAL);
break;
case eClientModelType::VEHICLE_UPGRADE:
iParentID = defaultVehicleUpgradeId;
break;
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions Client/sdk/game/CModelInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ class CModelInfo
// Call this to make sure the custom vehicle models are being used after a load.
virtual void MakeCustomModel() = 0;
virtual RwObject* GetRwObject() = 0;
virtual void SetRwObject(RwObject* pRwObject) = 0;
virtual void MakePedModel(const char* szTexture) = 0;
virtual void MakeObjectModel(unsigned short usBaseID) = 0;
virtual void MakeObjectDamageableModel(std::uint16_t baseID) = 0;
Expand Down