diff --git a/examples/CreateCar/Main.cpp b/examples/CreateCar/Main.cpp index 29c850467..170832370 100644 --- a/examples/CreateCar/Main.cpp +++ b/examples/CreateCar/Main.cpp @@ -4,116 +4,205 @@ https://github.com/DK22Pac/plugin-sdk Do not delete this comment block. Respect others' work! */ -#include "plugin.h" +#include // Plugin-SDK version 1003 from 2026-03-28 00:44:29 #include "common.h" -#include "CStreaming.h" +#include "CBmx.h" +#include "CBoat.h" +#include "CHeli.h" +#include "CMessages.h" #include "CModelInfo.h" #include "CMonsterTruck.h" -#include "CQuadBike.h" -#include "CHeli.h" #include "CPlane.h" -#include "CBmx.h" +#include "CQuadBike.h" +#include "CStreaming.h" +#include "CTimer.h" +#include "CTheScripts.h" #include "CTrailer.h" -#include "CBoat.h" +#include "CTrain.h" #include "CWorld.h" -#include "CTheScripts.h" -#include "CTimer.h" using namespace plugin; -class CreateCarExample { -public: - static unsigned int m_nLastSpawnedTime; // время последнего спавна ; last spawned time +struct Main +{ + bool keyCarSpawnPressed = false; + + Main() + { + // register event callbacks + Events::gameProcessEvent += []{ gInstance.OnGameProcess(); }; + } + + void OnGameProcess() + { + bool pressed; + + // handle car spawning hotkey + pressed = KeyPressed(VK_TAB); + if (pressed && !keyCarSpawnPressed) // just pressed + { + SpawnRandomCar(); + } + keyCarSpawnPressed = pressed; + } + + void SpawnRandomCar() + { + auto player = FindPlayerPed(); + if (!player || player->m_nAreaCode != 0) + { + return; // player not found or inside interior + } - // Вынесем создание авто в отдельную функцию SpawnVehicle ; Put everything related to car creation into SpawnVehicle function - static CVehicle *SpawnVehicle(unsigned int modelIndex, CVector position, float orientation) { - // Загружаем модель + unsigned int modelCount = MODEL_UTILTR1 - MODEL_LANDSTAL + 1; + std::srand(CTimer::m_snTimeInMilliseconds); // initialize random seed + unsigned int model = MODEL_LANDSTAL + (std::rand() % modelCount); // get random from range + + CVector position = player->TransformFromObjectSpace({0.0f, 8.0f, -1.0f}); // get offset from player + float rotation = player->m_fCurrentRotation + DegToRad(120.0f); + + auto vehicle = SpawnVehicle(model, position, rotation); + + static char msg[128]; // static, as it must exist as long, as it is printed on the screen + + if (!vehicle) + { + sprintf_s(msg, "~r~~h~Failed to spawn vehicle model: %d", model); + CMessages::AddMessageJumpQ(msg, 10000, 0); + return; // failed to spawn + } + + sprintf_s(msg, "Vehicle model: %d~n~Base type: %d, Type: %d", model, vehicle->m_nVehicleClass, vehicle->m_nVehicleSubClass); + CMessages::AddMessageJumpQ(msg, 10000, 0); + + // try modify components + if (!vehicle->m_pRwClump) + { + return; // graphical object not available + } + + // get component by name + RwFrame* component = CClumpModelInfo::GetFrameFromName(vehicle->m_pRwClump, "bonnet_dummy"); + if (component) + { + component->modelling.pos.z += 1.0f; // move up + } + + // get component by index + if (vehicle->m_nVehicleSubClass == VEHICLE_AUTOMOBILE) // eCarNodes enum only applies to the CAutomobile class! + { + auto car = reinterpret_cast(vehicle); + + if (car->m_aCarNodes[eCarNodes::CAR_BUMP_FRONT]) // make sure the component is present + { + car->m_aCarNodes[eCarNodes::CAR_BUMP_FRONT]->modelling.pos.z += 1.0f; // move up + } + } + } + + // pack everything related to car creation into SpawnVehicle function + static CVehicle* SpawnVehicle(unsigned int modelIndex, CVector position, float heading) + { unsigned char oldFlags = CStreaming::ms_aInfoForModel[modelIndex].m_nFlags; + CStreaming::RequestModel(modelIndex, GAME_REQUIRED); CStreaming::LoadAllRequestedModels(false); - if (CStreaming::ms_aInfoForModel[modelIndex].m_nLoadState == LOADSTATE_LOADED) { - if (!(oldFlags & GAME_REQUIRED)) { - CStreaming::SetModelIsDeletable(modelIndex); - CStreaming::SetModelTxdIsDeletable(modelIndex); - } - CVehicle *vehicle = nullptr; - // Выделяем обьект из пула - switch (reinterpret_cast(CModelInfo::ms_modelInfoPtrs[modelIndex])->m_nVehicleType) { - case VEHICLE_MTRUCK: - vehicle = new CMonsterTruck(modelIndex, 1); - break; - case VEHICLE_QUAD: - vehicle = new CQuadBike(modelIndex, 1); + if (CStreaming::ms_aInfoForModel[modelIndex].m_nLoadState != LOADSTATE_LOADED) + { + return nullptr; // failed to load + } + + if (!(oldFlags & GAME_REQUIRED)) + { + CStreaming::SetModelIsDeletable(modelIndex); + CStreaming::SetModelTxdIsDeletable(modelIndex); + } + + auto modelInfo = CModelInfo::GetModelInfo(modelIndex); + if (!modelInfo || modelInfo->GetModelType() != ModelInfoType::MODEL_INFO_VEHICLE) + { + return nullptr; // invalid model type + } + auto vehModelInfo = reinterpret_cast(modelInfo); + + CVehicle* vehicle = nullptr; + switch (vehModelInfo->m_nVehicleType) + { + case VEHICLE_BMX: + vehicle = new CBmx(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); break; - case VEHICLE_HELI: - vehicle = new CHeli(modelIndex, 1); + + case VEHICLE_BIKE: + vehicle = new CBike(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); break; - case VEHICLE_PLANE: - vehicle = new CPlane(modelIndex, 1); + + case VEHICLE_QUAD: + vehicle = new CQuadBike(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); break; - case VEHICLE_BIKE: - vehicle = new CBike(modelIndex, 1); - reinterpret_cast(vehicle)->m_nDamageFlags |= 0x10; + + case VEHICLE_AUTOMOBILE: + vehicle = new CAutomobile(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE, true); break; - case VEHICLE_BMX: - vehicle = new CBmx(modelIndex, 1); - reinterpret_cast(vehicle)->m_nDamageFlags |= 0x10; + + case VEHICLE_MTRUCK: + vehicle = new CMonsterTruck(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); break; + case VEHICLE_TRAILER: - vehicle = new CTrailer(modelIndex, 1); + vehicle = new CTrailer(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); break; + case VEHICLE_BOAT: - vehicle = new CBoat(modelIndex, 1); + vehicle = new CBoat(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); + break; + + case VEHICLE_HELI: + vehicle = new CHeli(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); + break; + + case VEHICLE_PLANE: + vehicle = new CPlane(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); + break; + + case VEHICLE_TRAIN: + vehicle = new CTrain(modelIndex, eVehicleCreatedBy::RANDOM_VEHICLE); + reinterpret_cast(vehicle)->m_nTrainFlags.bNotOnARailRoad = true; break; + default: - vehicle = new CAutomobile(modelIndex, 1, true); + // unsupported type break; - } - if (vehicle) { - // Размещаем транспорт в игровом мире - vehicle->SetPosn(position); - vehicle->SetOrientation(0.0f, 0.0f, orientation); - vehicle->m_nStatus = 4; - vehicle->m_eDoorLock = DOORLOCK_UNLOCKED; - CWorld::Add(vehicle); - CTheScripts::ClearSpaceForMissionEntity(position, vehicle); // удаляем другие обьекты, которые находятся в этих координатах - if (vehicle->m_nVehicleClass == VEHICLE_BIKE) - reinterpret_cast(vehicle)->PlaceOnRoadProperly(); - else if (vehicle->m_nVehicleClass != VEHICLE_BOAT) - reinterpret_cast(vehicle)->PlaceOnRoadProperly(); - return vehicle; - } } - return nullptr; - } + if (!vehicle) + { + return nullptr; // failed to spawn + } - // Наша функция спавна ; Our spawning function - static void ProcessSpawn() { - if (KeyPressed(VK_TAB) && CTimer::m_snTimeInMilliseconds > (m_nLastSpawnedTime + 1000)) { // Если нажата клавиша и прошло больше секунды с момента последнего спавна - CPed *player = FindPlayerPed(-1); // находим игрока ; find player - if (player && !player->m_nAreaCode) { // если найден и не в интерьере ; if found - CVector position = FindPlayerPed(-1)->TransformFromObjectSpace(CVector(0.0f, 5.0f, 0.0f)); // получаем координаты по офсету от игрока ; get coords on offset from player - CAutomobile *automobile = reinterpret_cast(SpawnVehicle(MODEL_INFERNUS, position, FindPlayerPed(-1)->m_fCurrentRotation + 1.5707964f)); // Создаём в этих координатах авто ; Create a car at these coords - if (automobile) { // если авто создано ; if car was created - m_nLastSpawnedTime = CTimer::m_snTimeInMilliseconds; // записываем новое время спавна ; store new spawning time - if (automobile->m_pRwClump) { // если создан графический обьект (RpClump) ; if graphical object was created (RpClump) - RwFrame *component = CClumpModelInfo::GetFrameFromName(automobile->m_pRwClump, (char*)"bonnet_dummy"); // находим компонент в иерархии ; find component in hierarchy - if (component) // если компонент есть в иерархии ; if component found - component->modelling.pos.z += 1.0f; // двигаем компонент вверх ; move component up - - // Ещё один вариант управления компонентом - обращаемся к компонентам, которые записаны в структуре авто ; Another way to control components - work with components that are stored in car structure - if (automobile->m_aCarNodes[CAR_BUMP_FRONT]) // если компонент присутствует ; if component present - automobile->m_aCarNodes[CAR_BUMP_FRONT]->modelling.pos.z += 1.0f; // двигаем компонент вверх ; move component up - } - } - } + position.z += vehicle->GetHeightAboveRoad(); + vehicle->SetOrientation(0.0f, 0.0f, heading); + vehicle->Teleport(position); // includes CWorld::Add + + vehicle->m_nStatus = eEntityStatus::STATUS_ABANDONED; + vehicle->bEngineOn = false; + vehicle->m_eDoorLock = DOORLOCK_UNLOCKED; + + switch (vehicle->m_nVehicleClass) // basic type + { + case VEHICLE_BIKE: // anything based on CBike class + reinterpret_cast(vehicle)->bOnSideStand = true; + reinterpret_cast(vehicle)->PlaceOnRoadProperly(); + break; + + case VEHICLE_AUTOMOBILE: // anything based on CAutomobile class + reinterpret_cast(vehicle)->PlaceOnRoadProperly(); + break; } - } + vehicle->UpdateRwMatrix(); // make updated position visible right away - CreateCarExample() { - // Добавляем нашу функцию в gameProcessEvent; Add our function to gameProcessEvent - Events::gameProcessEvent.Add(ProcessSpawn); // Это то же, что и Events::gameProcessEvent += ProcessSpawn ; Same as Events::gameProcessEvent += ProcessSpawn - } -} example; + CTheScripts::ClearSpaceForMissionEntity(vehicle->GetPosition(), vehicle); -unsigned int CreateCarExample::m_nLastSpawnedTime = 0; \ No newline at end of file + vehicle->ProcessControl(); // process suspension, ground brightness etc. + + return vehicle; + } +} gInstance; \ No newline at end of file diff --git a/examples/GPS/Main.cpp b/examples/GPS/Main.cpp index 9973806a4..b5e0ee428 100644 --- a/examples/GPS/Main.cpp +++ b/examples/GPS/Main.cpp @@ -94,8 +94,8 @@ class GPS { CRadar::TransformRadarPointToScreenSpace(posn, CVector2D(1.0f, 1.0f)); rect.right = static_cast(posn.x - 2.0f); rect.top = static_cast(posn.y + 2.0f); - ((IDirect3DDevice9*)GetD3DDevice)->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - ((IDirect3DDevice9*)GetD3DDevice)->SetScissorRect(&rect); + ((IDirect3DDevice9*)GetD3DDevice())->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + ((IDirect3DDevice9*)GetD3DDevice())->SetScissorRect(&rect); } RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); @@ -135,7 +135,7 @@ class GPS { if (!FrontEndMenuManager.m_bDrawRadarOrMap && reinterpret_cast(RwD3D9GetCaps())->RasterCaps & D3DPRASTERCAPS_SCISSORTEST) { - ((IDirect3DDevice9*)GetD3DDevice)->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + ((IDirect3DDevice9*)GetD3DDevice())->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); } gpsDistance += DistanceBetweenPoints(FindPlayerCoors(0), ThePaths.GetPathNode(resultNodes[0])->GetNodeCoors()); diff --git a/plugin_sa/game_sa/CAutomobile.h b/plugin_sa/game_sa/CAutomobile.h index eaf1bef01..742e2b00c 100644 --- a/plugin_sa/game_sa/CAutomobile.h +++ b/plugin_sa/game_sa/CAutomobile.h @@ -44,30 +44,32 @@ enum eCarNodes { CAR_NUM_NODES }; +#pragma pack(push, 4) class CAutomobile : public CVehicle { protected: CAutomobile(plugin::dummy_func_t) : CVehicle(plugin::dummy) {} + public: - CDamageManager m_damageManager; - CDoor m_doors[6]; - RwFrame *m_aCarNodes[CAR_NUM_NODES]; - CBouncingPanel m_panels[3]; - CDoor m_swingingChassis; + CDamageManager m_damageManager; + CDoor m_doors[6]; + RwFrame* m_aCarNodes[CAR_NUM_NODES]; + CBouncingPanel m_panels[3]; + CDoor m_swingingChassis; - CColPoint m_wheelColPoint[4]; - float wheelsDistancesToGround1[4]; // m_fWheelsSuspensionCompression: 0.0 compressed, 1.0 completely relaxed - float wheelsDistancesToGround2[4]; // m_fWheelsSuspensionCompressionPrev - float m_WheelCounts[4]; - float m_fBrakeCount; - float m_fIntertiaValue1; - float m_fIntertiaValue2; + CColPoint m_wheelColPoint[4]; + float m_fWheelsSuspensionCompression[4]; // 0.0 compressed, 1.0 completely relaxed + float m_fWheelsSuspensionCompressionPrev[4]; + float m_fWheelCounts[4]; + float m_fBrakeCount; + float m_fIntertiaValue1; + float m_fIntertiaValue2; eSkidmarkType m_wheelSkidmarkType[4]; - bool m_wheelSkidmarkBloodState[4]; - bool m_wheelSkidmarkMuddy[4]; - float m_fWheelRotation[4]; - float m_wheelPosition[4]; - float m_fWheelSpeed[4]; - float m_fWheelBurnoutSpeed[4]; // unused + bool m_bWheelSkidmarkBloody[4]; + bool m_bWheelSkidmarkMuddy[4]; + float m_fWheelRotation[4]; + float m_fWheelPosition[4]; + float m_fWheelSpeed[4]; + float m_fWheelBurnoutSpeed[4]; // unused struct { bool bTaxiLight : 1; @@ -78,10 +80,8 @@ class CAutomobile : public CVehicle { bool bTankExplodesCars : 1; bool bIsBoggedDownInSand : 1; bool bIsMonsterTruck : 1; - } autoFlags; - char field_869; // pad - bool m_bDoingBurnout; - char field_867; // pad + } m_nAutomobileFlags; + short m_bDoingBurnout; short m_wMiscComponentAngle; short m_wMiscComponentAnglePrev; @@ -94,42 +94,43 @@ class CAutomobile : public CVehicle { float m_fFrontHeightAboveRoad; float m_fRearHeightAboveRoad; - float m_fCarTraction; + float m_fExtraTractionMult; float m_fNitroValue; // m_fTireTemperature float m_fAircraftGoToHeading; float m_fRotationBalance; // controls destroyed helicopter rotation float m_fMoveDirection; // prev speed - CVector m_moveForce; - CVector m_turnForce; + CVector m_vecMoveForce; + CVector m_vecTurnForce; float m_aDoorRotation[6]; // unused float m_fBurningTimer; // starts when vehicle health is lower than 250.0, car blows up when it hits 5000.0 + CEntity* m_pWheelCollisionEntity[4]; - CVector m_vWheelCollisionPos[4]; + CVector m_vWheelCollisionPos[4]; CPed* m_pExplosionVictim; - char field_92C[24]; - int field_940; // m_fLeftDoorOpenForDriveBys - int field_944; // m_fRightDoorOpenForDriveBys + char field_92C[24]; // unknown + float m_fLeftDoorOpenForDriveBys; + float m_fRightDoorOpenForDriveBys; float m_fDoomVerticalRotation; float m_fDoomHorizontalRotation; float m_fForcedOrientation; float m_fPropRotate; // previously m_fUpDownLightAngle[0] float m_fCumulativeDamage; // previously m_fUpDownLightAngle[1] - unsigned char m_nNumContactWheels; - unsigned char m_nWheelsOnGround; - unsigned char m_NumDriveWheelsOnGroundLastFrame; - char field_963; // pad - float m_GasPedalAudioRevs; // adjusts the speed of playback of the skiding sound (0.0 to 1.0) - eWheelState m_WheelStates[4]; - FxSystem_c* pNitroParticle[2]; - unsigned char m_harvesterParticleCounter; - unsigned char m_fireParticleCounter; - short field_982; // pad - float m_heliDustFxTimeConst; + + uint8_t m_nNumContactWheels; + uint8_t m_nWheelsOnGround; + uint8_t m_nNumDriveWheelsOnGroundLastFrame; + float m_fGasPedalAudioRevs; // adjusts the speed of playback of the skiding sound (0.0 to 1.0) + eWheelState m_wheelState[4]; + + FxSystem_c* m_pNitroParticle[2]; + uint8_t m_harvesterParticleCounter; + uint8_t m_fireParticleCounter; + float m_heliDustFxTimeConst; // variables static bool &m_sAllTaxiLights; @@ -241,13 +242,18 @@ class CAutomobile : public CVehicle { void FireTruckControl(float arg0); bool HasCarStoppedBecauseOfLight(); }; +#pragma pack(pop) +VALIDATE_OFFSET(CAutomobile, m_swingingChassis, 0x70C); +VALIDATE_OFFSET(CAutomobile, m_wheelColPoint, 0x724); +VALIDATE_OFFSET(CAutomobile, m_nAutomobileFlags, 0x868); VALIDATE_OFFSET(CAutomobile, m_wMiscComponentAngle, 0x86C); VALIDATE_OFFSET(CAutomobile, m_aSuspensionSpringLength, 0x878); VALIDATE_OFFSET(CAutomobile, m_fBurningTimer, 0x8E4); VALIDATE_OFFSET(CAutomobile, m_pExplosionVictim, 0x928); VALIDATE_OFFSET(CAutomobile, m_fDoomVerticalRotation, 0x94C); -VALIDATE_OFFSET(CAutomobile, field_982, 0x982); +VALIDATE_OFFSET(CAutomobile, m_pNitroParticle, 0x978); +VALIDATE_OFFSET(CAutomobile, m_heliDustFxTimeConst, 0x984); VALIDATE_SIZE(CAutomobile, 0x988); extern CColPoint *aAutomobileColPoints; diff --git a/plugin_sa/game_sa/CBike.h b/plugin_sa/game_sa/CBike.h index 8492017e5..fd6692ae8 100644 --- a/plugin_sa/game_sa/CBike.h +++ b/plugin_sa/game_sa/CBike.h @@ -7,8 +7,8 @@ #pragma once #include "PluginBase.h" #include "CVehicle.h" +#include "tBikeHandlingData.h" -struct tBikeHandlingData; enum eBikeNodes { BIKE_NODE_NONE = 0, @@ -24,62 +24,79 @@ enum eBikeNodes { BIKE_NUM_NODES }; -class CBike : public CVehicle { +#pragma pack(push, 4) +class CBike : public CVehicle{ protected: CBike(plugin::dummy_func_t) : CVehicle(plugin::dummy), m_mLeanMatrix(plugin::dummy) {} + public: - RwFrame *m_aBikeNodes[BIKE_NUM_NODES]; - bool m_bLeanMatrixCalculated; - char _pad0[3]; - CMatrix m_mLeanMatrix; - unsigned char m_nDamageFlags; - char field_615[27]; - CVector field_630; - void *m_pBikeHandlingData; - CRideAnimData m_rideAnimData; - unsigned char m_anWheelDamageState[2]; - char field_65E; - char field_65F; - CColPoint m_anWheelColPoint[4]; - float field_710[4]; - float field_720[4]; - float field_730[4]; - float field_740; - int m_anWheelSurfaceType[2]; - char field_74C[2]; - char field_74E[2]; - float m_afWheelRotationX[2]; - float m_fWheelSpeed[2]; - float field_760; - float field_764; - float field_768; - float field_76C; - float field_770[4]; - float field_780[4]; - float m_fHeightAboveRoad; - float m_fCarTraction; - float field_798; - float field_79C; - float field_7A0; - float field_7A4; - short field_7A8; - char field_7AA[2]; - int field_7AC; - int field_7B0; - bool m_bPedLeftHandFixed; - bool m_bPedRightHandFixed; - char field_7B6[2]; - int field_7B8; + static constexpr auto NUM_WHEELS = 2; + static constexpr auto NUM_SUSP_LINES = 4; + + RwFrame* m_aBikeNodes[BIKE_NUM_NODES]; + + bool m_bLeanMatrixCalculated; + CMatrix m_mLeanMatrix; + + union { + struct { + bool bShouldNotChangeColour : 1; + bool bPanelsAreThougher : 1; + bool bWaterTight : 1; // ignores water + bool bGettingPickedUp : 1; + bool bOnSideStand : 1; // is standing + bool bPlayerBoost : 1; + bool bEngineOnFire : 1; + bool bWheelieForCamera : 1; + }; + uint8_t m_nBikeFlags; + }; + + CVector m_vecAveGroundNormal; + CVector m_vecGroundRight; + CVector m_vecOldSpeedForPlayback; + tBikeHandlingData* m_pBikeHandlingData; + CRideAnimData m_rideAnimData; + + uint8_t m_nWheelStatus[NUM_WHEELS]; + CColPoint m_anWheelColPoint[NUM_SUSP_LINES]; + float m_aWheelRatios[NUM_SUSP_LINES]; + float m_aRatioHistory[NUM_SUSP_LINES]; + float m_fWheelCounts[NUM_SUSP_LINES]; + float m_fBrakeCount; + eSkidmarkType m_aWheelSkidmarkType[NUM_WHEELS]; + bool m_bWheelBloody[NUM_WHEELS]; + bool m_bMoreSkidMarks[NUM_WHEELS]; + float m_aWheelPitchAngles[NUM_WHEELS]; + float m_aWheelAngularVelocity[NUM_WHEELS]; + float m_aWheelSuspensionHeights[NUM_WHEELS]; + float m_aWheelOrigHeights[NUM_WHEELS]; + float m_fSuspensionLength[NUM_SUSP_LINES]; + float m_fLineLength[NUM_SUSP_LINES]; + float m_fHeightAboveRoad; + float m_fExtraTractionMult; + float m_fSwingArmLength; + float m_fForkYOffset; + float m_fForkZOffset; + float m_fSteerAngleTan; + uint16_t m_nBrakesOn; + float m_fNitroValue; // m_fTyreTemp + float m_fBrakingSlide; + uint8_t m_nFixLeftHand; + uint8_t m_nFixRightHand; + uint8_t m_nTestPedCollision; + float m_fPrevSpeed; + float m_fBurningTimer; // starts when vehicle health is lower than 250.0, bike blows up when it hits 5000.0 - CEntity *m_apWheelCollisionEntity[4]; - CVector m_avTouchPointsLocalSpace[4]; - CEntity *m_pDamager; - unsigned char m_nNumContactWheels; - unsigned char m_nNumWheelsOnGround; - char field_806; - char field_807; - int field_808; - unsigned int m_anWheelState[2]; // enum tWheelState + + CEntity* m_apWheelCollisionEntity[NUM_SUSP_LINES]; + CVector m_avTouchPointsLocalSpace[NUM_SUSP_LINES]; + CEntity* m_pDamager; + uint8_t m_nNumContactWheels; + uint8_t m_nNumWheelsOnGround; + uint8_t m_nNumDriveWheelsOnGroundLastFrame; + float m_fGasPedalAudioRevs; + eWheelState m_wheelState[NUM_WHEELS]; //vtable @@ -107,5 +124,16 @@ class CBike : public CVehicle { void PlaceOnRoadProperly(); void GetCorrectedWorldDoorPosition(CVector& out, CVector arg1, CVector arg2); }; +#pragma pack(pop) +VALIDATE_OFFSET(CBike, m_bLeanMatrixCalculated, 0x5C8); +VALIDATE_OFFSET(CBike, m_nBikeFlags, 0x614); +VALIDATE_OFFSET(CBike, m_vecOldSpeedForPlayback, 0x630); +VALIDATE_OFFSET(CBike, m_rideAnimData, 0x640); +VALIDATE_OFFSET(CBike, m_anWheelColPoint, 0x660); +VALIDATE_OFFSET(CBike, m_aWheelSkidmarkType, 0x744); +VALIDATE_OFFSET(CBike, m_fHeightAboveRoad, 0x790); +VALIDATE_OFFSET(CBike, m_apWheelCollisionEntity, 0x7C0); +VALIDATE_OFFSET(CBike, m_nNumWheelsOnGround, 0x805); +VALIDATE_OFFSET(CBike, m_wheelState, 0x80C); VALIDATE_SIZE(CBike, 0x814); diff --git a/plugin_sa/game_sa/CClumpModelInfo.cpp b/plugin_sa/game_sa/CClumpModelInfo.cpp index 257f8b5cb..0936e66dc 100644 --- a/plugin_sa/game_sa/CClumpModelInfo.cpp +++ b/plugin_sa/game_sa/CClumpModelInfo.cpp @@ -46,9 +46,9 @@ RwFrame *CClumpModelInfo::GetFrameFromId(RpClump *clump, int id) return ((RwFrame *(__cdecl *)(RpClump *, int))0x4C53C0)(clump, id); } -RwFrame *CClumpModelInfo::GetFrameFromName(RpClump *clump, char *name) +RwFrame *CClumpModelInfo::GetFrameFromName(RpClump *clump, const char *name) { - return ((RwFrame *(__cdecl *)(RpClump *, char *))0x4C5400)(clump, name); + return ((RwFrame *(__cdecl *)(RpClump *, const char *))0x4C5400)(clump, name); } void CClumpModelInfo::FillFrameArray(RpClump *clump, RwFrame **frames) diff --git a/plugin_sa/game_sa/CClumpModelInfo.h b/plugin_sa/game_sa/CClumpModelInfo.h index cc243cb01..8e19d3acd 100644 --- a/plugin_sa/game_sa/CClumpModelInfo.h +++ b/plugin_sa/game_sa/CClumpModelInfo.h @@ -36,7 +36,7 @@ class PLUGIN_API CClumpModelInfo : public CBaseModelInfo { static RwFrame *FindFrameFromIdCB(RwFrame *frame, void *searchData); static RwFrame *FillFrameArrayCB(RwFrame *frame, void *data); static RwFrame *GetFrameFromId(RpClump *clump, int id); - static RwFrame *GetFrameFromName(RpClump *clump, char *name); + static RwFrame *GetFrameFromName(RpClump *clump, const char *name); static void FillFrameArray(RpClump *clump, RwFrame **frames); void SetFrameIds(RwObjectNameIdAssocation* data); }; diff --git a/plugin_sa/game_sa/CModelInfo.cpp b/plugin_sa/game_sa/CModelInfo.cpp index 0bf06dd4e..b75f498e4 100644 --- a/plugin_sa/game_sa/CModelInfo.cpp +++ b/plugin_sa/game_sa/CModelInfo.cpp @@ -6,7 +6,7 @@ */ #include "CModelInfo.h" -CBaseModelInfo **CModelInfo::ms_modelInfoPtrs = (CBaseModelInfo**)0xA9B0C8; +CBaseModelInfo **CModelInfo::ms_modelInfoPtrs = *(CBaseModelInfo***)0x40CD67; // limit adjusters support - get from reference in CStreaming::RequestModelStream // Converted from stdcall void CModelInfo::ReInit2dEffects(void) 0x4C63B0 void CModelInfo::ReInit2dEffects() @@ -181,7 +181,3 @@ int CModelInfo::IsVehicleModelType(int index) { return ((int (__cdecl *)(int))0x4C5C80)(index); } - -CBaseModelInfo *CModelInfo::GetModelInfo(int index) { - return plugin::CallAndReturn(index); -} \ No newline at end of file diff --git a/plugin_sa/game_sa/CModelInfo.h b/plugin_sa/game_sa/CModelInfo.h index ccc5a2b7e..905c84a37 100644 --- a/plugin_sa/game_sa/CModelInfo.h +++ b/plugin_sa/game_sa/CModelInfo.h @@ -19,8 +19,7 @@ class PLUGIN_API CModelInfo { public: // variables - //static CBaseModelInfo *ms_modelInfoPtrs[20000]; Use GetModelInfo(int index) to get model info by id - static CBaseModelInfo **ms_modelInfoPtrs; + static CBaseModelInfo **ms_modelInfoPtrs; // 20000, might be extended by limit adjusters // functions static void ReInit2dEffects(); @@ -55,7 +54,9 @@ class PLUGIN_API CModelInfo // return -1 if model is not a vehicle model otherwise returns vehicle model type static int IsVehicleModelType(int index); - static CBaseModelInfo *GetModelInfo(int index); + static inline CBaseModelInfo* GetModelInfo(int index) { + return ms_modelInfoPtrs[index]; + } static inline CColModel* GetColModel(int id) { return ms_modelInfoPtrs[id]->m_pColModel; diff --git a/plugin_sa/game_sa/CPathFind.cpp b/plugin_sa/game_sa/CPathFind.cpp index 0888b59cb..e0053932c 100644 --- a/plugin_sa/game_sa/CPathFind.cpp +++ b/plugin_sa/game_sa/CPathFind.cpp @@ -6,7 +6,7 @@ */ #include "CPathFind.h" -CPathFind &ThePaths = **(CPathFind **)(0x40CA27); +CPathFind &ThePaths = **(CPathFind**)(0x40CA27); // limit adjusters support - get from reference in CStreaming::ConvertBufferToObject void CPathFind::DoPathSearch(unsigned char pathType, CVector origin, CNodeAddress originAddr, CVector target, CNodeAddress *pResultNodes, short *pNodesCount, int maxNodesToFind, float *pDistance, diff --git a/plugin_sa/game_sa/CStreaming.cpp b/plugin_sa/game_sa/CStreaming.cpp index ed04e5d4c..13f490945 100644 --- a/plugin_sa/game_sa/CStreaming.cpp +++ b/plugin_sa/game_sa/CStreaming.cpp @@ -46,7 +46,7 @@ unsigned int &CStreaming::ms_streamingBufferSize = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x8E4CAC, 0, 0, 0, 0, 0)); unsigned int &CStreaming::ms_memoryUsed = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x8E4CB4, 0, 0, 0, 0, 0)); unsigned int &CStreaming::ms_numModelsRequested = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x8E4CB8, 0, 0, 0, 0, 0)); -CStreamingInfo *CStreaming::ms_aInfoForModel = reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x8E4CC0, 0, 0, 0, 0, 0)); +CStreamingInfo *CStreaming::ms_aInfoForModel = *reinterpret_cast(0x408B25); // limit adjusters support - get from reference in CStreaming::RemoveModel bool &CStreaming::ms_disableStreaming = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x9654B0, 0, 0, 0, 0, 0)); int &CStreaming::ms_bIsInitialised = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x9654B8, 0, 0, 0, 0, 0)); bool &CStreaming::m_bBoatsNeeded = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x9654BC, 0, 0, 0, 0, 0)); diff --git a/plugin_sa/game_sa/CVehicle.h b/plugin_sa/game_sa/CVehicle.h index 7ae1b3b70..954c39ad9 100644 --- a/plugin_sa/game_sa/CVehicle.h +++ b/plugin_sa/game_sa/CVehicle.h @@ -312,7 +312,7 @@ class PLUGIN_API CVehicle : public CPhysical { RwTexture* m_pCustomCarPlate; float m_fRawSteerAngle; // AKA m_fSteeringLeftRight or fSteer - eVehicleType m_nVehicleClass; // m_nVehicleType + eVehicleType m_nVehicleClass; // m_nVehicleType - base class eVehicleType m_nVehicleSubClass; // m_nVehicleSubType short m_nPreviousRemapTxd; short m_nRemapTxd; diff --git a/plugin_sa/game_sa/CVehicleModelInfo.h b/plugin_sa/game_sa/CVehicleModelInfo.h index 5ecf77950..cfbd09259 100644 --- a/plugin_sa/game_sa/CVehicleModelInfo.h +++ b/plugin_sa/game_sa/CVehicleModelInfo.h @@ -66,7 +66,7 @@ class PLUGIN_API CVehicleModelInfo : public CClumpModelInfo { private: char _pad3A[2]; public: - unsigned int m_nVehicleType; + eVehicleType m_nVehicleType; float m_fWheelSizeFront; float m_fWheelSizeRear; short m_nWheelModelIndex; @@ -296,5 +296,7 @@ class PLUGIN_API CVehicleModelInfo : public CClumpModelInfo { int GetNumDoors(); }; +VALIDATE_OFFSET(CVehicleModelInfo, field_51, 0x51); +VALIDATE_SIZE(CVehicleModelInfo, 0x308); + VALIDATE_SIZE(CVehicleModelInfo::CVehicleStructure, 0x314); -VALIDATE_SIZE(CVehicleModelInfo, 0x308); \ No newline at end of file diff --git a/shared/Other.h b/shared/Other.h index 7f8978e4a..0560c2644 100644 --- a/shared/Other.h +++ b/shared/Other.h @@ -218,13 +218,13 @@ namespace plugin template static T DegToRad(T x) { - return (x * PI / (T)180); + return (T)(x * PI / (T)180); } template static T RadToDeg(T x) { - return (x * (T)180 / PI); + return (T)(x * (T)180 / PI); } template diff --git a/shared/plugin.h b/shared/plugin.h index a58c3729a..dde3a16f4 100644 --- a/shared/plugin.h +++ b/shared/plugin.h @@ -9,10 +9,10 @@ #define __TO_STR(x) #x #define TO_STR(x) __TO_STR(x) -#define PLUGIN_SDK_VERSION 1002 +#define PLUGIN_SDK_VERSION 1003 #define PLUGIN_SDK_VERSION_STR TO_STR(PLUGIN_SDK_VERSION) -#define PLUGIN_SDK_DATE 2025-12-09 23:18:09 +#define PLUGIN_SDK_DATE 2026-03-28 00:44:29 #define PLUGIN_SDK_DATE_STR TO_STR(PLUGIN_SDK_DATE) #include "PluginBase.h"