diff --git a/examples/PedSpawner/Main.cpp b/examples/PedSpawner/Main.cpp index 9b0371539..663e5549b 100644 --- a/examples/PedSpawner/Main.cpp +++ b/examples/PedSpawner/Main.cpp @@ -6,51 +6,135 @@ */ #include "plugin.h" #include "common.h" -#include "CTimer.h" -#include "CPopulation.h" #include "CCivilianPed.h" -#include "CWorld.h" -#ifdef GTASA +#include "CMessages.h" #include "CStreaming.h" -#include "CTaskComplexWanderStandard.h" +#include "CTheScripts.h" +#include "CTimer.h" +#include "CWorld.h" + +#ifdef GTA3 +#include "RpAnimBlend.h" #endif -#include "CHud.h" - -int pedModelIds[] = { 0, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 57, 58, 59, 60, 61, 62, 66, 67, 68, 70, 71, 72, 73, 78, 79, 80, 81, 82, 83, 84, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 128, 132, - 133, 134, 135, 136, 137, 142, 143, 144, 146, 147, 153, 154, 155, 156, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 170, 171, - 173, 174, 175, 176, 177, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 200, 202, 203, 204, 206, 209, 210, 212, 213, 217, 220, - 221, 222, 223, 227, 228, 229, 230, 234, 235, 236, 239, 240, 241, 242, 247, 248, 249, 250, 252, 253, 254, 255, 258, 259, 260, 261, 262, - 9, 10, 11, 12, 13, 31, 38, 39, 40, 41, 53, 54, 55, 56, 63, 64, 69, 75, 76, 77, 85, 87, 88, 89, 90, 91, 92, 93, 129, 130, 131, 138, 139, - 140, 141, 145, 148, 150, 151, 152, 157, 169, 172, 178, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 201, 205, 207, 211, 214, 215, - 216, 218, 219, 224, 225, 226, 231, 232, 233, 237, 238, 243, 244, 245, 246, 251, 256, 257, 263 }; using namespace plugin; -class PedSpawner { -public: - PedSpawner() { - static int keyPressTime = 0; - Events::gameProcessEvent += [] { - if (FindPlayerPed() && KeyPressed(VK_F9) && CTimer::m_snTimeInMilliseconds - keyPressTime > 500) { - #ifdef GTASA - keyPressTime = CTimer::m_snTimeInMilliseconds; - int modelID = pedModelIds[rand() % 250]; - CStreaming::RequestModel(modelID, 0); - CStreaming::LoadAllRequestedModels(false); - CPed *ped = new CCivilianPed(CPopulation::IsFemale(modelID) ? PED_TYPE_CIVFEMALE : PED_TYPE_CIVMALE, modelID); - if (ped) { - ped->SetPosn(FindPlayerPed()->TransformFromObjectSpace(CVector(0.0f, 5.0f, 3.0f))); - ped->SetOrientation(0.0f, 0.0f, 0.0f); - CWorld::Add(ped); - ped->PositionAnyPedOutOfCollision(); - ped->m_pIntelligence->m_TaskMgr.SetTask(new CTaskComplexWanderStandard(4, rand() % 8, true), 4, false); - } - #else - CHud::SetHelpMessage(L"Not done yet!", true, false); - #endif - } - }; +struct Main +{ + char messageBuffer[128] = { 0 }; // it must exist as long, as it is printed on the screen + + bool tipDisplayed = false; + int modelId = eModelID::MODEL_INVALID; + bool keyPedSpawnPrevPressed = false; + bool keyPedSpawnNextPressed = false; + + Main() + { + // register event callbacks + Events::restartGameEvent += [this]{ OnGameRestart(); }; + Events::gameProcessEvent += [this]{ OnGameProcess(); }; + } + + void OnGameRestart() + { + tipDisplayed = false; + modelId = eModelID::MODEL_INVALID; + } + + void OnGameProcess() + { + if (!tipDisplayed) + { + CMessages::AddMessageJumpQ("Press ~h~.~s~ or ~h~,~s~ to spawn ped. Hold SHIFT for fast browsing.", 10000, 0); + tipDisplayed = true; + } + + bool pressed; + + // handle prev ped spawning hotkey + pressed = KeyPressed(VK_OEM_COMMA); // < key + if (pressed && !keyPedSpawnPrevPressed) // just pressed + { + int skip = KeyPressed(VK_SHIFT) ? 9 : 0; // fast browse key + SpawnNextPed(modelId - skip, false); + } + keyPedSpawnPrevPressed = pressed; + + pressed = KeyPressed(VK_OEM_PERIOD); // > key + if (pressed && !keyPedSpawnNextPressed) // just pressed + { + int skip = KeyPressed(VK_SHIFT) ? 9 : 0; // fast browse key + SpawnNextPed(modelId + skip, true); + } + keyPedSpawnNextPressed = pressed; + } + + void SpawnNextPed(int searchStartId, bool searchForward) + { + auto player = FindPlayerPed(); + if (!player) + { + return; // player not found + } + + // ground level position in front of the player + CVector position = player->TransformFromObjectSpace({0.0f, 4.0f, -1.0f}); + float heading = player->GetHeading() + DegToRad(180.0f); // face the player + + // find next model id + modelId = searchStartId; + while (true) + { + modelId = CModelInfo::FindNextModel(MODEL_INFO_PED, modelId, searchForward); + + if (modelId == MODEL_INVALID) + return; // error: not found + + if (modelId >= MODEL_SPECIAL_FIRST && modelId <= MODEL_SPECIAL_LAST) // ped special character slots + continue; // keep searching + + break; // found + } + + // load model + CStreaming::RequestModel(modelId, 0); + CStreaming::LoadAllRequestedModels(false); + if (!CStreaming::HasModelLoaded(modelId)) + { + sprintf_s(messageBuffer, "~r~~h~Failed to load ped model: %d", modelId); + CMessages::AddMessageJumpQ(messageBuffer, 10000, 0); + return; // failed to load model + } + + CWorld::ClearExcitingStuffFromArea(position, 2.0f, false); // clear non-mission entities in the radius + + auto ped = new CCivilianPed(PED_TYPE_CIVMALE, modelId); + if (!ped) + { + sprintf_s(messageBuffer, "~r~~h~Failed to spawn ped model: %d", modelId); + CMessages::AddMessageJumpQ(messageBuffer, 10000, 0); + return; // failed to spawn + } + + sprintf_s(messageBuffer, "Ped model: %d", modelId); + CMessages::AddMessageJumpQ(messageBuffer, 3000, 0); + + position.z += 1.0f; // offset from the ground to the ped center + ped->SetPosition(position.x, position.y, position.z); + ped->SetHeading(heading); + ped->m_fHeadingCurrent = ped->m_fHeadingGoal = heading; + ped->GetMatrix().UpdateRW(); + + if (ped->m_pRwClump) + { + RpAnimBlendClumpUpdateAnimations(ped->m_pRwClump, CTimer::ms_fTimeStep); + } + + #if defined(GTASA) + ped->m_fContactSurfaceBrightness = 0.5f; + #endif + + CTheScripts::ClearSpaceForMissionEntity(ped->GetPosition(), ped); // clear non-mission entities colliding with the ped + CWorld::Add(ped); } -} pedSpawner; +} gInstance; diff --git a/examples/PedSpawner/README.md b/examples/PedSpawner/README.md index 56532d077..d83159403 100644 --- a/examples/PedSpawner/README.md +++ b/examples/PedSpawner/README.md @@ -1,7 +1,13 @@ -## Random Ped Spawner -Spawns random male and female pedestrians in front of the player when F9 is pressed. +## Ped Spawner +Showcase browsing and creation of all (non-cutscene) ped models. +Supports new model IDs added with limit adjusters. -![Img1](http://i.imgur.com/J1m0lHH.png) ![Img2](http://i.imgur.com/BrkDKbn.png) +### Controls (keyboard) +* **<** - find previous ped model ID and spawn it +* **>** - find next ped model ID and spawn it +* **SHIFT** - hold for faster model browising -#### Controls (keyboard) -* F9 - Spawn Ped +### Target platforms +* Classic GTA 3 +* Classic GTA Vice City +* Classic GTA San Andreas \ No newline at end of file diff --git a/examples/examples.csv b/examples/examples.csv index af3e1c11c..025992c28 100644 --- a/examples/examples.csv +++ b/examples/examples.csv @@ -9,7 +9,7 @@ HandSignals, ASI, ---, ---, ---, YES, ---, ---, ---, ---, --- Neon, ASI, ---, ---, ---, YES, ---, ---, ---, ---, --- OpenDoorExample, ASI, ---, ---, ---, YES, ---, ---, ---, ---, --- PedPainting, ASI, ---, ---, YES, YES, ---, ---, ---, ---, --- -PedSpawner, ASI, ---, ---, YES, YES, ---, ---, ---, ---, --- +PedSpawner, ASI, ---, YES, YES, YES, ---, ---, ---, ---, --- PlayerWeapon, ASI, ---, ---, ---, YES, ---, ---, ---, ---, --- RotateDoor, ASI, ---, ---, ---, YES, ---, ---, ---, ---, --- ScriptCommands, ASI, ---, YES, YES, YES, ---, ---, ---, ---, --- diff --git a/plugin_III/game_III/CCivilianPed.cpp b/plugin_III/game_III/CCivilianPed.cpp index a42b3204d..4de6a2217 100644 --- a/plugin_III/game_III/CCivilianPed.cpp +++ b/plugin_III/game_III/CCivilianPed.cpp @@ -17,9 +17,21 @@ int dtor_gaddr(CCivilianPed) = GLOBAL_ADDRESS_BY_VERSION(0x4BFFC0, 0x4C00B0, 0x4 int del_dtor_addr(CCivilianPed) = ADDRESS_BY_VERSION(0x4C1170, 0x4C1260, 0x4C11F0); int del_dtor_gaddr(CCivilianPed) = GLOBAL_ADDRESS_BY_VERSION(0x4C1170, 0x4C1260, 0x4C11F0); +void* CCivilianPed::operator new(size_t size) { + return plugin::CallAndReturnDynGlobal(op_new_gaddr(CPed), size); +} + +void CCivilianPed::operator delete(void* data) { + return plugin::CallDynGlobal(op_delete_gaddr(CPed), data); +} + int addrof(CCivilianPed::ProcessControl) = ADDRESS_BY_VERSION(0x4BFFE0, 0x4C00D0, 0x4C0060); int gaddrof(CCivilianPed::ProcessControl) = GLOBAL_ADDRESS_BY_VERSION(0x4BFFE0, 0x4C00D0, 0x4C0060); +CCivilianPed::CCivilianPed(ePedType pedType, unsigned int modelIndex) { + plugin::CallMethodDynGlobal(ctor_gaddr_o(CCivilianPed, void(ePedType, unsigned int)), this, pedType, modelIndex); +} + void CCivilianPed::ProcessControl() { plugin::CallVirtualMethod<8, CCivilianPed *>(this); } diff --git a/plugin_III/game_III/CCivilianPed.h b/plugin_III/game_III/CCivilianPed.h index f1dd2cfb8..151f2ad67 100644 --- a/plugin_III/game_III/CCivilianPed.h +++ b/plugin_III/game_III/CCivilianPed.h @@ -9,11 +9,14 @@ #include "PluginBase.h" #include "CPed.h" -class PLUGIN_API CCivilianPed { +class PLUGIN_API CCivilianPed : public CPed +{ PLUGIN_NO_DEFAULT_CONSTRUCTION(CCivilianPed) + static void* operator new(size_t size); + static void operator delete(void* data); public: - CPed ped; //!< isbase:true + SUPPORTED_10EN_11EN_STEAM CCivilianPed(ePedType pedType, unsigned int modelIndex); // virtual function #0 (destructor) diff --git a/plugin_III/game_III/CPed.h b/plugin_III/game_III/CPed.h index f275d6ac4..2d3275c5d 100644 --- a/plugin_III/game_III/CPed.h +++ b/plugin_III/game_III/CPed.h @@ -397,10 +397,10 @@ class PLUGIN_API CPed : public CPhysical { short m_nRoutePointsPassed; short m_nRouteType; //!< see ePedRouteType short m_nRoutePointsBeingPassed; - CVector2D m_vec2dMoved; - float m_fRotationCur; - float m_fRotationDest; - float m_fHeadingRate; + CVector2D m_vecAnimMovingShift; // velocity from walk animations + float m_fHeadingCurrent; // current heading angle + float m_fHeadingGoal; // desired heading angle + float m_fHeadingChangeRate; // speed of turing to m_fHeadingGoal unsigned short m_nVehicleDoor; short m_nWalkAroundType; CPhysical *m_pCurrentPhysSurface; diff --git a/plugin_III/game_III/CPlaceable.h b/plugin_III/game_III/CPlaceable.h index 78fdc4020..7a93dcb59 100644 --- a/plugin_III/game_III/CPlaceable.h +++ b/plugin_III/game_III/CPlaceable.h @@ -23,15 +23,8 @@ class PLUGIN_API CPlaceable { SUPPORTED_10EN_11EN_STEAM bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2); SUPPORTED_10EN_11EN_STEAM void SetHeading(float angle); SUPPORTED_10EN_11EN_STEAM void SetPosition(float x, float y, float z); - - inline float GetHeading() { - float angle = atan2f(-m_matrix.up.x, m_matrix.up.y) * 57.295776f; - if (angle < 0.0f) - angle += 360.0f; - if (angle > 360.0f) - angle -= 360.0f; - return angle; - } + + inline float GetHeading() { return GetForward().Heading(); } inline void SetPos(CVector &pos) { this->m_matrix.pos = pos; diff --git a/plugin_III/game_III/CStreaming.cpp b/plugin_III/game_III/CStreaming.cpp index 5dff7126c..53fe0a8d5 100644 --- a/plugin_III/game_III/CStreaming.cpp +++ b/plugin_III/game_III/CStreaming.cpp @@ -28,7 +28,7 @@ int &CStreaming::ms_oldSectorX = *(int *)0x8F2C84; int &CStreaming::ms_oldSectorY = *(int *)0x8F2C88; int &CStreaming::ms_vehiclesLoaded = *(int *)0x773560; -CStreamingInfo *CStreaming::ms_aInfoForModel = (CStreamingInfo *)0x6C7088; +CStreamingInfo *CStreaming::ms_aInfoForModel = *(CStreamingInfo**)0x40A4AD; // limit adjusters support - get from reference in CStreaming::LoadAllRequestedModels CStreamingInfo *CStreaming::ms_endRequestedList = (CStreamingInfo *)0x940738; CStreamingInfo *CStreaming::ms_startLoadedList = (CStreamingInfo *)0x942F60; CStreamingInfo *CStreaming::ms_startRequestedList = (CStreamingInfo *)0x8F1B3C; @@ -236,6 +236,10 @@ int CStreaming::GetNextFileOnCd(int arg0, bool arg1) { return plugin::CallAndReturn(arg0, arg1); } +bool CStreaming::HasModelLoaded(int modelIndex) { + return ms_aInfoForModel[modelIndex].m_nLoadState == LOADSTATE_LOADED; +} + // Converted from cdecl bool CStreaming::HasSpecialCharLoaded(int modelIndex) 0x40ADC0 bool CStreaming::HasSpecialCharLoaded(int modelIndex) { return plugin::CallAndReturn(modelIndex); diff --git a/plugin_III/game_III/CStreaming.h b/plugin_III/game_III/CStreaming.h index cc8cad448..6eabca7a9 100644 --- a/plugin_III/game_III/CStreaming.h +++ b/plugin_III/game_III/CStreaming.h @@ -92,7 +92,10 @@ class CStreaming { static bool FinishLoadingLargeFile(char* FileName, int modelIndex); static unsigned int GetCdImageOffset(int arg0); static int GetNextFileOnCd(int arg0, bool arg1); + + static bool HasModelLoaded(int modelIndex); static bool HasSpecialCharLoaded(int modelIndex); + static void HaveAllBigBuildingsLoaded(eLevelName levelName); static void IHaveUsedStreamingMemory(); // empty function diff --git a/plugin_sa/game_sa/CPed.h b/plugin_sa/game_sa/CPed.h index fe4811a08..6166c0689 100644 --- a/plugin_sa/game_sa/CPed.h +++ b/plugin_sa/game_sa/CPed.h @@ -235,10 +235,10 @@ class PLUGIN_API CPed : public CPhysical { float m_fMaxHealth; float m_fArmour; unsigned int m_nTimeTillWeNeedThisPed; - CVector2D m_vecAnimMovingShift; - float m_fCurrentRotation; - float m_fAimingRotation; - float m_fHeadingChangeRate; + CVector2D m_vecAnimMovingShift; // velocity from walk animations + float m_fHeadingCurrent; // current heading angle + float m_fHeadingGoal; // desired heading angle + float m_fHeadingChangeRate; // speed of turing to m_fHeadingGoal int m_fMoveAnim; CEntity* m_standingOnEntity; CVector field_56C; diff --git a/plugin_sa/game_sa/CPlaceable.cpp b/plugin_sa/game_sa/CPlaceable.cpp index e2a059034..6be72de73 100644 --- a/plugin_sa/game_sa/CPlaceable.cpp +++ b/plugin_sa/game_sa/CPlaceable.cpp @@ -76,8 +76,8 @@ void CPlaceable::SetMatrix(CMatrix const& matrix) ((void (__thiscall *)(CPlaceable *, CMatrix const&))0x54F610)(this, matrix); } -CMatrixLink *CPlaceable::GetMatrix() { - return ((CMatrixLink *(__thiscall *)(CPlaceable *))0x411990)(this); +CMatrixLink& CPlaceable::GetMatrix() { + return *((CMatrixLink *(__thiscall *)(CPlaceable *))0x411990)(this); } void CPlaceable::ShutdownMatrixArray() { diff --git a/plugin_sa/game_sa/CPlaceable.h b/plugin_sa/game_sa/CPlaceable.h index bd9774132..ac5ab0ce0 100644 --- a/plugin_sa/game_sa/CPlaceable.h +++ b/plugin_sa/game_sa/CPlaceable.h @@ -20,7 +20,7 @@ class PLUGIN_API CPlaceable { virtual ~CPlaceable() {}; - CMatrixLink *GetMatrix(); + CMatrixLink& GetMatrix(); static void ShutdownMatrixArray(); static void InitMatrixArray(); @@ -30,8 +30,12 @@ class PLUGIN_API CPlaceable { CVector GetAtDirection(); void FreeStaticMatrix(); + void SetPosn(float x, float y, float z); - void SetPosn(CVector const& posn); + void SetPosn(CVector const& pos); + inline void SetPosition(float x, float y, float z) { SetPosn(x, y, z); } + inline void SetPosition(CVector const& pos) { SetPosn(pos); } + void SetOrientation(float x, float y, float z); void GetOrientation(float& x, float& y, float& z); void SetHeading(float heading); diff --git a/plugin_sa/game_sa/CStreaming.cpp b/plugin_sa/game_sa/CStreaming.cpp index 13f490945..5e75d9788 100644 --- a/plugin_sa/game_sa/CStreaming.cpp +++ b/plugin_sa/game_sa/CStreaming.cpp @@ -266,6 +266,10 @@ int CStreaming::GetNextFileOnCd(int pos, bool bNotPriority) { return plugin::CallAndReturnDynGlobal(gaddrof(CStreaming::GetNextFileOnCd), pos, bNotPriority); } +bool CStreaming::HasModelLoaded(int modelIndex) { + return ms_aInfoForModel[modelIndex].m_nLoadState == LOADSTATE_LOADED; +} + int addrof(CStreaming::HasSpecialCharLoaded) = ADDRESS_BY_VERSION(0x407F00, 0, 0, 0, 0, 0); int gaddrof(CStreaming::HasSpecialCharLoaded) = GLOBAL_ADDRESS_BY_VERSION(0x407F00, 0, 0, 0, 0, 0); diff --git a/plugin_sa/game_sa/CStreaming.h b/plugin_sa/game_sa/CStreaming.h index 7d3a27330..047eecfa7 100644 --- a/plugin_sa/game_sa/CStreaming.h +++ b/plugin_sa/game_sa/CStreaming.h @@ -133,8 +133,11 @@ class PLUGIN_API CStreaming { SUPPORTED_10US static signed int GetDiscInDrive(); //! return modelIndex SUPPORTED_10US static int GetNextFileOnCd(int pos, bool bNotPriority); + + static bool HasModelLoaded(int modelIndex); SUPPORTED_10US static bool HasSpecialCharLoaded(int slot); SUPPORTED_10US static bool HasVehicleUpgradeLoaded(int ModelIndex); + //! does nothing (NOP) SUPPORTED_10US static void IHaveUsedStreamingMemory(); //! does nothing (NOP) diff --git a/plugin_sa/game_sa/common.h b/plugin_sa/game_sa/common.h index 256368474..06170081b 100644 --- a/plugin_sa/game_sa/common.h +++ b/plugin_sa/game_sa/common.h @@ -157,7 +157,7 @@ void RpAnimBlendClumpRemoveAllAssociations(RpClump* clump); void RpAnimBlendClumpRemoveAssociations(RpClump* clump, unsigned int flags); void RpAnimBlendClumpSetBlendDeltas(RpClump* clump, unsigned int flags, float delta); void RpAnimBlendClumpUnPauseAllAnimations(RpClump* clump); -void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float step, bool onScreen); +void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float step, bool onScreen = true); RtAnimAnimation* RpAnimBlendCreateAnimationForHierarchy(RpHAnimHierarchy* hierarchy); char* RpAnimBlendFrameGetName(RwFrame* frame); void RpAnimBlendFrameSetName(RwFrame* frame, char* name); diff --git a/plugin_vc/game_vc/CEntity.h b/plugin_vc/game_vc/CEntity.h index 3513700fc..aedc853f5 100644 --- a/plugin_vc/game_vc/CEntity.h +++ b/plugin_vc/game_vc/CEntity.h @@ -141,14 +141,7 @@ class CEntity : public CPlaceable { return pos; } - inline float GetHeading() { - float angle = atan2f(-up.x, up.y) * 57.295776f; - if (angle < 0.0f) - angle += 360.0f; - if (angle > 360.0f) - angle -= 360.0f; - return angle; - } + inline float GetHeading() { return GetForward().Heading(); } inline void SetPosition(float x, float y, float z) { this->pos.x = x; diff --git a/plugin_vc/game_vc/CPed.h b/plugin_vc/game_vc/CPed.h index 24cf1bbb5..905c34d12 100644 --- a/plugin_vc/game_vc/CPed.h +++ b/plugin_vc/game_vc/CPed.h @@ -277,11 +277,10 @@ class CPed : public CPhysical { private: char _pad36A[2]; public: - float m_fMovedX; - float m_fMovedY; - float m_fRotationCur; - float m_fRotationDest; - float m_fHeadingRate; + CVector2D m_vecAnimMovingShift; // velocity from walk animations + float m_fHeadingCurrent; // current heading angle + float m_fHeadingGoal; // desired heading angle + float m_fHeadingChangeRate; // speed of turing to m_fHeadingGoal unsigned short m_nEnterType; //shows how the ped enters the vehicle (from the driver side or passenger side, from the back, etc : 11 - passenger side 15 - driver side) unsigned short m_nWalkAroundType; CPhysical *m_pCurPhysSurface; diff --git a/plugin_vc/game_vc/CPlaceable.h b/plugin_vc/game_vc/CPlaceable.h index 31eed9eb8..e6348b962 100644 --- a/plugin_vc/game_vc/CPlaceable.h +++ b/plugin_vc/game_vc/CPlaceable.h @@ -18,4 +18,6 @@ class CPlaceable : public CMatrix { void SetHeading(float heading); void SetOrientation(float x, float y, float z); void GetOrientation(float& x, float& y, float& z); + + inline CMatrix& GetMatrix() { return *this; } }; \ No newline at end of file diff --git a/plugin_vc/game_vc/CStreaming.cpp b/plugin_vc/game_vc/CStreaming.cpp index 9ffa0fa1b..0fbf65c40 100644 --- a/plugin_vc/game_vc/CStreaming.cpp +++ b/plugin_vc/game_vc/CStreaming.cpp @@ -15,7 +15,7 @@ PLUGIN_VARIABLE bool(&CStreaming::ms_bIsPedFromPedGroupLoaded)[16] = *reinterpre PLUGIN_VARIABLE char *&CStreaming::ms_pStreamingBuffer = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x94B840, 0, 0)); PLUGIN_VARIABLE int &CStreaming::ms_channelError = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x94DB60, 0, 0)); PLUGIN_VARIABLE int &CStreaming::ms_lastImageRead = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x94DBE4, 0, 0)); -PLUGIN_VARIABLE CStreamingInfo(&CStreaming::ms_aInfoForModel)[7951] = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x94DDD0, 0, 0)); +PLUGIN_VARIABLE CStreamingInfo* CStreaming::ms_aInfoForModel = *reinterpret_cast(0x40B6E3); // limit adjusters support - get from reference in CStreaming::LoadAllRequestedModels PLUGIN_VARIABLE int &CStreaming::ms_numModelsRequested = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x975354, 0, 0)); PLUGIN_VARIABLE int &CStreaming::ms_imageSize = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x978578, 0, 0)); PLUGIN_VARIABLE tModelRequest &CStreaming::ms_endLoadedList = *reinterpret_cast(GLOBAL_ADDRESS_BY_VERSION(0x978640, 0, 0)); @@ -143,6 +143,10 @@ int CStreaming::GetNextFileOnCd(int CdOffset, bool bOnlyPriorityRequests) { return plugin::CallAndReturnDynGlobal(gaddrof(CStreaming::GetNextFileOnCd), CdOffset, bOnlyPriorityRequests); } +bool CStreaming::HasModelLoaded(int modelIndex) { + return ms_aInfoForModel[modelIndex].m_nLoadState == LOADSTATE_LOADED; +} + int addrof(CStreaming::HasSpecialCharLoaded) = ADDRESS_BY_VERSION(0x409A10, 0, 0); int gaddrof(CStreaming::HasSpecialCharLoaded) = GLOBAL_ADDRESS_BY_VERSION(0x409A10, 0, 0); diff --git a/plugin_vc/game_vc/CStreaming.h b/plugin_vc/game_vc/CStreaming.h index a7992e841..4be5c3006 100644 --- a/plugin_vc/game_vc/CStreaming.h +++ b/plugin_vc/game_vc/CStreaming.h @@ -34,7 +34,7 @@ class PLUGIN_API CStreaming { SUPPORTED_10EN static char *&ms_pStreamingBuffer; SUPPORTED_10EN static int &ms_channelError; SUPPORTED_10EN static int &ms_lastImageRead; - SUPPORTED_10EN static CStreamingInfo(&ms_aInfoForModel)[7951]; // static CStreamingInfo ms_aInfoForModel[7951] + SUPPORTED_10EN static CStreamingInfo* ms_aInfoForModel; // 7951, extended by limit adjusters SUPPORTED_10EN static int &ms_numModelsRequested; SUPPORTED_10EN static int &ms_imageSize; SUPPORTED_10EN static tModelRequest &ms_endLoadedList; @@ -66,7 +66,10 @@ class PLUGIN_API CStreaming { SUPPORTED_10EN static void FlushRequestList(); SUPPORTED_10EN static unsigned int GetCdImageOffset(int CdPosn); SUPPORTED_10EN static int GetNextFileOnCd(int CdOffset, bool bOnlyPriorityRequests); + + static bool HasModelLoaded(int modelIndex); SUPPORTED_10EN static bool HasSpecialCharLoaded(int SpecialSlotID); + //! unused function SUPPORTED_10EN static void IHaveUsedStreamingMemory(); //! empty function diff --git a/plugin_vc/game_vc/common.h b/plugin_vc/game_vc/common.h index b45ea6a06..e4bc7ffee 100644 --- a/plugin_vc/game_vc/common.h +++ b/plugin_vc/game_vc/common.h @@ -61,7 +61,7 @@ bool RpAnimBlendClumpIsInitialized(RpClump* clump); void RpAnimBlendClumpRemoveAllAssociations(RpClump* clump); void RpAnimBlendClumpRemoveAssociations(RpClump* clump, unsigned int flags); void RpAnimBlendClumpSetBlendDeltas(RpClump* clump, unsigned int flags, float delta); -void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float step, bool onScreen = false); +void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float step, bool onScreen = true); CAnimBlendAssociation* RpAnimBlendGetNextAssociation(CAnimBlendAssociation* association); bool RpAnimBlendPluginAttach(); void DefinedState();