From 14c7c1d7ca722935195a20817c96b1af75046359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 12 Sep 2019 03:43:18 +0300 Subject: [PATCH] World and Peds --- src/animation/RpAnimBlend.h | 1 + src/control/Population.cpp | 9 ++ src/control/Population.h | 1 + src/control/Record.cpp | 4 + src/control/Record.h | 16 ++- src/core/CutsceneMgr.cpp | 1 + src/core/CutsceneMgr.h | 3 + src/core/Messages.cpp | 1 + src/core/Messages.h | 1 + src/core/PlayerInfo.cpp | 1 + src/core/PlayerInfo.h | 1 + src/core/World.cpp | 248 +++++++++++++++++++++++++++++++++++- src/core/World.h | 4 + src/core/config.h | 1 + src/core/re3.cpp | 5 +- src/peds/Ped.cpp | 218 ++++++++++++++++++++++++++++++- src/peds/Ped.h | 1 + src/peds/PedIK.cpp | 2 + src/peds/PedIK.h | 4 +- 19 files changed, 505 insertions(+), 17 deletions(-) diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h index 68fa03cb..55a4456b 100644 --- a/src/animation/RpAnimBlend.h +++ b/src/animation/RpAnimBlend.h @@ -34,6 +34,7 @@ CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation_N(RpClump *clump, int CAnimBlendAssociation *RpAnimBlendClumpGetMainPartialAssociation_N(RpClump *clump, int n); CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump, uint32 mask); CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump); +void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta); extern CAnimBlendClumpData *&gpAnimBlendClump; diff --git a/src/control/Population.cpp b/src/control/Population.cpp index 83259616..3e7ab427 100644 --- a/src/control/Population.cpp +++ b/src/control/Population.cpp @@ -1,6 +1,8 @@ #include "common.h" #include "patcher.h" #include "Game.h" +#include "World.h" +#include "Entity.h" #include "Population.h" PedGroup *CPopulation::ms_pPedGroups = (PedGroup*)0x6E9248; @@ -14,3 +16,10 @@ WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); } WRAPPER void CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool) { EAXJMP(0x4F6200); } WRAPPER CPed *CPopulation::AddPedInCar(CVehicle *vehicle) { EAXJMP(0x4F5800); } WRAPPER bool CPopulation::IsPointInSafeZone(CVector *coors) { EAXJMP(0x4F60C0); } + +void +CPopulation::RemovePed(CEntity* ent) +{ + CWorld::Remove(ent); + delete ent; +} diff --git a/src/control/Population.h b/src/control/Population.h index 3582ccef..7757a7a6 100644 --- a/src/control/Population.h +++ b/src/control/Population.h @@ -24,4 +24,5 @@ public: static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool); static CPed *AddPedInCar(CVehicle *vehicle); static bool IsPointInSafeZone(CVector *coors); + static void RemovePed(CEntity* ent); }; diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 4cc2dccd..cff4a19b 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -1,6 +1,10 @@ #include "common.h" +#include "patcher.h" #include "Record.h" uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24; uint8 &CRecordDataForChase::Status = *(uint8*)0x95CDCE; + +WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); } +WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); } \ No newline at end of file diff --git a/src/control/Record.h b/src/control/Record.h index 2705a955..08e9f7c8 100644 --- a/src/control/Record.h +++ b/src/control/Record.h @@ -6,14 +6,18 @@ enum { RECORDSTATE_2, }; +class CRecordDataForChase +{ +public: + static uint8 &Status; + + static void ProcessControlCars(void); + static void SaveOrRetrieveCarPositions(void); +}; + + class CRecordDataForGame { public: static uint16 &RecordingState; }; - -class CRecordDataForChase -{ -public: - static uint8 &Status; -}; diff --git a/src/core/CutsceneMgr.cpp b/src/core/CutsceneMgr.cpp index 744ef53d..a54e8ff6 100644 --- a/src/core/CutsceneMgr.cpp +++ b/src/core/CutsceneMgr.cpp @@ -5,3 +5,4 @@ bool &CCutsceneMgr::ms_running = *(bool*)0x95CCF5; bool &CCutsceneMgr::ms_cutsceneProcessing = *(bool*)0x95CD9F; CDirectory *&CCutsceneMgr::ms_pCutsceneDir = *(CDirectory**)0x8F5F88; +CCutsceneObject *(&CCutsceneMgr::ms_pCutsceneObjects)[NUMCUTSCENEOBJECTS] = *(CCutsceneObject*(*)[NUMCUTSCENEOBJECTS]) *(uintptr*) 0x862170; diff --git a/src/core/CutsceneMgr.h b/src/core/CutsceneMgr.h index 89f6ab8d..aa5a2eb2 100644 --- a/src/core/CutsceneMgr.h +++ b/src/core/CutsceneMgr.h @@ -1,4 +1,5 @@ #pragma once +#include "CutsceneObject.h" class CDirectory; @@ -6,10 +7,12 @@ class CCutsceneMgr { static bool &ms_running; static bool &ms_cutsceneProcessing; + static CCutsceneObject *(&ms_pCutsceneObjects)[NUMCUTSCENEOBJECTS]; public: static CDirectory *&ms_pCutsceneDir; static bool IsRunning(void) { return ms_running; } static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; } + static CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; } }; diff --git a/src/core/Messages.cpp b/src/core/Messages.cpp index b7b6a738..07784eda 100644 --- a/src/core/Messages.cpp +++ b/src/core/Messages.cpp @@ -15,6 +15,7 @@ WRAPPER void CMessages::AddMessageJumpQ(wchar* key, uint32 time, uint16 pos) { E WRAPPER void CMessages::AddMessageSoon(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529AF0); } WRAPPER void CMessages::ClearMessages() { EAXJMP(0x529CE0); } WRAPPER void CMessages::Init() { EAXJMP(0x529310); } +WRAPPER void CMessages::Process() { EAXJMP(0x529580); } tPreviousBrief *CMessages::PreviousBriefs = (tPreviousBrief *)0x713C08; tMessage *CMessages::BriefMessages = (tMessage *)0x8786E0; tBigMessage *CMessages::BIGMessages = (tBigMessage *)0x773628; diff --git a/src/core/Messages.h b/src/core/Messages.h index 1cdcd3b7..3ee5d026 100644 --- a/src/core/Messages.h +++ b/src/core/Messages.h @@ -47,4 +47,5 @@ public: static void AddMessageSoon(wchar* key, uint32 time, uint16 pos); static void ClearMessages(); static void Init(); + static void Process(); }; diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index d9a4c0b0..8c505eb4 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -8,6 +8,7 @@ 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); } void CPlayerInfo::SetPlayerSkin(char *skin) { diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 5edbc8d0..29290f6e 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -71,6 +71,7 @@ public: void AwardMoneyForExplosion(CVehicle *vehicle); void SetPlayerSkin(char* skin); CVector& GetPos(); + void Process(void); }; static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error"); diff --git a/src/core/World.cpp b/src/core/World.cpp index 150e87d5..29d0ac18 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -12,6 +12,13 @@ #include "TempColModels.h" #include "World.h" #include "ModelIndices.h" +#include "References.h" +#include "CutsceneMgr.h" +#include "Record.h" +#include "RpAnimBlend.h" +#include "Messages.h" +#include "Replay.h" +#include "Population.h" CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60; CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C; @@ -31,7 +38,6 @@ bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C; bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA; -WRAPPER void CWorld::Process(void) { EAXJMP(0x4B1A60); } WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); } WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } @@ -930,6 +936,244 @@ FindPlayerHeading(void) return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetForward().Heading(); } +void +CWorld::RemoveEntityInsteadOfProcessingIt(CEntity* ent) +{ + if (ent->IsPed()) { + if (FindPlayerPed() == ent) + CWorld::Remove(ent); + else + CPopulation::RemovePed(ent); + } else { + CWorld::Remove(ent); + delete ent; + } +} + +void +CWorld::RemoveFallenPeds(void) +{ + int poolSize = CPools::GetPedPool()->GetSize(); + for(int poolIndex = poolSize-1; poolIndex >= 0; poolIndex--) { + CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex); + if (ped) { + if (ped->GetPosition().z < -100.0f) { + if (ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) { + int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED, 999999.9f, false, false); + CVector newPos = ThePaths.m_pathNodes[closestNode].pos; + newPos.z += 2.0f; + ped->Teleport(newPos); + ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } else { + CPopulation::RemovePed(ped); + } + } + } + } +} + +void +CWorld::RemoveFallenCars(void) +{ + int poolSize = CPools::GetVehiclePool()->GetSize(); + for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if (veh) { + if (veh->GetPosition().z < -100.0f) { + if (veh->VehicleCreatedBy == MISSION_VEHICLE || veh == FindPlayerVehicle() || (veh->pDriver && veh->pDriver->IsPlayer())) { + int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR, 999999.9f, false, false); + CVector newPos = ThePaths.m_pathNodes[closestNode].pos; + newPos.z += 3.0f; + veh->Teleport(newPos); + veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + } else if (veh->VehicleCreatedBy == RANDOM_VEHICLE || veh->VehicleCreatedBy == PARKED_VEHICLE) { + CWorld::Remove(veh); + delete veh; + } + } + } + } +} + +void +CWorld::Process(void) +{ + if (!(CTimer::GetFrameCounter() & 63)) + CReferences::PruneAllReferencesInWorld(); + + if (CWorld::bProcessCutsceneOnly) { + for (int i = 0; i < NUMCUTSCENEOBJECTS; i++) { + CCutsceneObject *csObj = CCutsceneMgr::GetCutsceneObject(i); + if (csObj && csObj->m_entryInfoList.first) { + if (csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP + && RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) { + RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), 0.02f * (csObj->m_type == ENTITY_TYPE_OBJECT ? CTimer::GetTimeStepNonClipped() : CTimer::GetTimeStep())); + } + csObj->ProcessControl(); + csObj->ProcessCollision(); + csObj->GetMatrix().UpdateRW(); + csObj->UpdateRwFrame(); + } + } + CRecordDataForChase::ProcessControlCars(); + CRecordDataForChase::SaveOrRetrieveCarPositions(); + } else { + for (CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity*)node->item; + if (movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP + && RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) { + RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), 0.02f * (movingEnt->m_type == ENTITY_TYPE_OBJECT ? CTimer::GetTimeStepNonClipped() : CTimer::GetTimeStep())); + } + } + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPhysical* movingEnt = (CPhysical*)node->item; + if (movingEnt->bRemoveFromWorld) { + RemoveEntityInsteadOfProcessingIt(movingEnt); + } else { + movingEnt->ProcessControl(); + if (movingEnt->bIsStatic) { + movingEnt->RemoveFromMovingList(); + } + } + } + CWorld::bForceProcessControl = 1; + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPhysical* movingEnt = (CPhysical*)node->item; + if (movingEnt->bWasPostponed) { + if (movingEnt->bRemoveFromWorld) { + RemoveEntityInsteadOfProcessingIt(movingEnt); + } else { + movingEnt->ProcessControl(); + if (movingEnt->bIsStatic) { + movingEnt->RemoveFromMovingList(); + } + } + } + } + CWorld::bForceProcessControl = 0; + if (CReplay::IsPlayingBack()) { + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity* movingEnt = (CEntity*)node->item; + movingEnt->bIsInSafePosition = true; + movingEnt->GetMatrix().UpdateRW(); + movingEnt->UpdateRwFrame(); + } + } else { + CWorld::bNoMoreCollisionTorque = 0; + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity* movingEnt = (CEntity*)node->item; + if (!movingEnt->bIsInSafePosition) { + movingEnt->ProcessCollision(); + movingEnt->GetMatrix().UpdateRW(); + movingEnt->UpdateRwFrame(); + } + } + CWorld::bNoMoreCollisionTorque = 1; + for (int i = 0; i < 4; i++) { + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity* movingEnt = (CEntity*)node->item; + if (!movingEnt->bIsInSafePosition) { + movingEnt->ProcessCollision(); + movingEnt->GetMatrix().UpdateRW(); + movingEnt->UpdateRwFrame(); + } + } + } + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity* movingEnt = (CEntity*)node->item; + if (!movingEnt->bIsInSafePosition) { + movingEnt->bIsStuck = true; + movingEnt->ProcessCollision(); + movingEnt->GetMatrix().UpdateRW(); + movingEnt->UpdateRwFrame(); + if (!movingEnt->bIsInSafePosition) { + movingEnt->bIsStuck = true; + } + } + } + CWorld::bSecondShift = 0; + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity* movingEnt = (CEntity*)node->item; + if (!movingEnt->bIsInSafePosition) { + movingEnt->ProcessShift(); + movingEnt->GetMatrix().UpdateRW(); + movingEnt->UpdateRwFrame(); + if (!movingEnt->bIsInSafePosition) { + movingEnt->bIsStuck = true; + } + } + } + CWorld::bSecondShift = 1; + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPhysical* movingEnt = (CPhysical*)node->item; + if (!movingEnt->bIsInSafePosition) { + movingEnt->ProcessShift(); + movingEnt->GetMatrix().UpdateRW(); + movingEnt->UpdateRwFrame(); + if (!movingEnt->bIsInSafePosition) { + movingEnt->bIsStuck = true; + if (movingEnt->m_status == STATUS_PLAYER) { + printf("STUCK: Final Step: Player Entity %d Is Stuck\n", movingEnt->m_modelIndex); + movingEnt->m_vecMoveSpeed *= 3.0f; + movingEnt->ApplyMoveSpeed(); + movingEnt->ApplyTurnSpeed(); + } + } + } + } + } + for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPed* movingPed = (CPed*)node->item; + if (movingPed->IsPed()) { + if (movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN + || movingPed->m_nPedState == PED_ENTER_CAR || movingPed->m_nPedState == PED_CARJACK) { + CVehicle *movingCar = movingPed->m_pMyVehicle; + if (movingCar) { + if (movingCar->IsTrain()) { + movingPed->SetPedPositionInTrain(); + } else { + switch (movingPed->m_nPedState) { + case PED_ENTER_CAR: + case PED_CARJACK: + movingPed->EnterCar(); + break; + case PED_DRAG_FROM_CAR: + movingPed->BeingDraggedFromCar(); + break; + case PED_EXIT_CAR: + movingPed->ExitCar(); + break; + case PED_ARRESTED: + if (movingPed->m_nLastPedState == PED_DRAG_FROM_CAR) { + movingPed->BeingDraggedFromCar(); + break; + } + // fall through + default: + movingPed->SetPedPositionInCar(); + break; + } + } + movingPed->GetMatrix().UpdateRW(); + movingPed->UpdateRwFrame(); + } else { + movingPed->bInVehicle = false; + movingPed->QuitEnteringCar(); + } + } + } + } + CMessages::Process(); + Players[PlayerInFocus].Process(); + CRecordDataForChase::SaveOrRetrieveCarPositions(); + if ((CTimer::GetFrameCounter() & 7) == 1) { + CWorld::RemoveFallenPeds(); + } else if ((CTimer::GetFrameCounter() & 7) == 5) { + CWorld::RemoveFallenCars(); + } + } +} + STARTPATCHES InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP); InjectHook(0x4AE9D0, CWorld::Remove, PATCH_JUMP); @@ -951,4 +1195,6 @@ STARTPATCHES InjectHook(0x4B3A80, CWorld::FindGroundZForCoord, PATCH_JUMP); InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP); InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP); + + InjectHook(0x4B1A60, CWorld::Process, PATCH_JUMP); ENDPATCHES diff --git a/src/core/World.h b/src/core/World.h index c2ca75c4..b24e66f0 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -114,6 +114,10 @@ public: static float GetWorldX(int x) { return x*SECTOR_SIZE_X + WORLD_MIN_X; } static float GetWorldY(int y) { return y*SECTOR_SIZE_Y + WORLD_MIN_Y; } + static void RemoveEntityInsteadOfProcessingIt(CEntity* ent); + static void RemoveFallenPeds(); + static void RemoveFallenCars(); + static void Initialise(); static void ShutDown(); static void Process(); diff --git a/src/core/config.h b/src/core/config.h index d119fe09..8c7f66c9 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -30,6 +30,7 @@ enum Config { NUMOBJECTS = 450, NUMDUMMIES = 2802, // 2368 on PS2 NUMAUDIOSCRIPTOBJECTS = 256, + NUMCUTSCENEOBJECTS = 50, NUMTEMPOBJECTS = 30, diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 9737fddb..19b3c691 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -141,10 +141,9 @@ SpawnCar(int id) static void LetThemFollowYou(void) { - CPed* player = (CPed*) FindPlayerPed(); + CPed *player = (CPed*) FindPlayerPed(); for (int i = 0; i < player->m_numNearPeds; i++) { - - CPed* nearPed = player->m_nearPeds[i]; + CPed *nearPed = player->m_nearPeds[i]; if (nearPed && !nearPed->IsPlayer()) { nearPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, (void*)player); nearPed->m_pedFormation = rand() & 7; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 3c157237..5f010b20 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2833,7 +2833,7 @@ CPed::ReactToAttack(CEntity *attacker) SetLookTimer(700); return; } - + if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) { CPed *ourLeader = m_leader; if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader) @@ -9534,10 +9534,15 @@ CPed::ProcessControl(void) if (!IsPlayer() || !m_pVehicleAnim) break; + CPad *pad = CPad::GetPad(0); + + if (pad->ArePlayerControlsDisabled()) + break; + int vehAnim = m_pVehicleAnim->animId; - int16 padWalkX = CPad::GetPad(0)->GetPedWalkLeftRight(); - int16 padWalkY = CPad::GetPad(0)->GetPedWalkUpDown(); + int16 padWalkX = pad->GetPedWalkLeftRight(); + int16 padWalkY = pad->GetPedWalkUpDown(); if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { if (vehAnim == ANIM_CAR_OPEN_LHS || vehAnim == ANIM_CAR_OPEN_RHS || vehAnim == ANIM_COACH_OPEN_L || vehAnim == ANIM_COACH_OPEN_R || vehAnim == ANIM_VAN_OPEN_L || vehAnim == ANIM_VAN_OPEN) { @@ -9970,7 +9975,7 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg) } veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f); - if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_LR) + if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF) isVan = false; if (ped->m_nPedState != PED_CARJACK || isBus) { @@ -10276,13 +10281,212 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) } } +void +CPed::SetPedPositionInTrain(void) +{ + LineUpPedWithTrain(); +} + +void +CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed* ped = (CPed*)arg; + + CVehicle* veh = ped->m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (ped->m_nPedState == PED_CARJACK || ped->m_nPedState == PED_ENTER_CAR) { + if (!veh || veh->m_status == STATUS_WRECKED) + return; + + bool isLow = veh->bLowVehicle; + + int padNo; + if (ped->IsPlayer()) { + + switch (ped->m_nPedType) { + case PEDTYPE_PLAYER1: + padNo = 0; + break; + case PEDTYPE_PLAYER2: + padNo = 1; + break; + case PEDTYPE_PLAYER3: + padNo = 2; + break; + case PEDTYPE_PLAYER4: + padNo = 3; + break; + default: + // FIX: that was "break" + return; + } + CPad *pad = CPad::GetPad(padNo); + + if (!pad->ArePlayerControlsDisabled()) { + + if (pad->GetTarget() + || pad->NewState.LeftStickX + || pad->NewState.LeftStickY + || pad->NewState.DPadUp + || pad->NewState.DPadDown + || pad->NewState.DPadLeft + || pad->NewState.DPadRight) { + ped->QuitEnteringCar(); + ped->RestorePreviousObjective(); + return; + } + } + } + + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { + AnimationId animToPlay; + if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) { + if (isLow) + animToPlay = ANIM_CAR_GETIN_LOW_RHS; + else + animToPlay = ANIM_CAR_GETIN_RHS; + } else if (isLow) { + animToPlay = ANIM_CAR_GETIN_LOW_LHS; + } else { + animToPlay = ANIM_CAR_GETIN_LHS; + } + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay); + ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped); + } else { + ped->QuitEnteringCar(); + } + } else { + ped->QuitEnteringCar(); + } +} + +void +CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) +{ + CPed* ped = (CPed*)arg; + + CVehicle* veh = ped->m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + if (!veh) { + PedSetOutCarCB(nil, ped); + return; + } + veh->m_nStaticFrames = 0; + veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f); + veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f); + if (!veh->bIsBus) + veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f); + + // Duplicate and pointless code + if (!veh) { + PedSetOutCarCB(nil, ped); + return; + } + eDoors door; + switch (ped->m_vehEnterType) { + case CAR_DOOR_RF: + door = DOOR_FRONT_RIGHT; + break; + case CAR_DOOR_RR: + door = DOOR_REAR_RIGHT; + break; + case CAR_DOOR_LF: + door = DOOR_FRONT_LEFT; + break; + case CAR_DOOR_LR: + door = DOOR_REAR_LEFT; + break; + default: + break; + } + bool closeDoor = false; + if (!veh->IsDoorMissing(door)) + closeDoor = true; + + int padNo; + if (ped->IsPlayer()) { + + switch (ped->m_nPedType) { + case PEDTYPE_PLAYER1: + padNo = 0; + break; + case PEDTYPE_PLAYER2: + padNo = 1; + break; + case PEDTYPE_PLAYER3: + padNo = 2; + break; + case PEDTYPE_PLAYER4: + padNo = 3; + break; + default: + // FIX: that was "break" + return; + } + CPad* pad = CPad::GetPad(padNo); + bool engineIsIntact = false; + if (veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225) { + engineIsIntact = true; + } + if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS + && (pad->GetTarget() + || pad->NewState.LeftStickX + || pad->NewState.LeftStickY + || pad->NewState.DPadUp + || pad->NewState.DPadDown + || pad->NewState.DPadLeft + || pad->NewState.DPadRight) + || veh->bIsBus + || veh->m_pCarFire + || engineIsIntact) { + closeDoor = false; + } + } + + if (!closeDoor) { + if (!veh->IsDoorMissing(door) && !veh->bIsBus) { + ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); + } + PedSetOutCarCB(nil, ped); + return; + } + + if (ped->m_ped_flagE80 || ped->m_ped_flagG40) { + if (!veh->IsDoorMissing(door)) + ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING); + } else { + switch (door) { + case DOOR_FRONT_LEFT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS); + break; + case DOOR_FRONT_RIGHT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS); + break; + case DOOR_REAR_LEFT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS); + break; + case DOOR_REAR_RIGHT: + ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS); + break; + default: + break; + } + } + + if (ped->m_pVehicleAnim) + ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped); + return; +} + WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); } WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); } WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); } -WRAPPER void CPed::PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DEAF0); } WRAPPER void CPed::PedSetInCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CF220); } WRAPPER void CPed::PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8F0); } -WRAPPER void CPed::PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF5C0); } WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); } WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); } WRAPPER void CPed::PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E3290); } @@ -10470,4 +10674,6 @@ STARTPATCHES InjectHook(0x4D73D0, &CPed::SetJump, PATCH_JUMP); InjectHook(0x4E4E20, &CPed::RemoveInCarAnims, PATCH_JUMP); InjectHook(0x4DEC80, &CPed::PedAnimGetInCB, PATCH_JUMP); + InjectHook(0x4DEAF0, &CPed::PedAnimPullPedOutCB, PATCH_JUMP); + InjectHook(0x4DF5C0, &CPed::PedAnimStepOutCarCB, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 3003cd2d..2808824f 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -714,6 +714,7 @@ public: void RestoreHeadPosition(void); void PointGunAt(void); bool ServiceTalkingWhenDead(void); + void SetPedPositionInTrain(void); bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index f1da5d66..4912da97 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -13,6 +13,8 @@ WRAPPER bool CPedIK::RestoreLookAt(void) { EAXJMP(0x4ED810); } // TODO: These are hardcoded into exe, reverse it. LimbMovementInfo &CPedIK::ms_torsoInfo = *(LimbMovementInfo*)0x5F9F8C; LimbMovementInfo &CPedIK::ms_headInfo = *(LimbMovementInfo*)0x5F9F5C; +LimbMovementInfo &CPedIK::ms_upperArmInfo = *(LimbMovementInfo*)0x5F9FA4; +LimbMovementInfo &CPedIK::ms_lowerArmInfo = *(LimbMovementInfo*)0x5F9FBC; CPedIK::CPedIK(CPed *ped) { diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index 080cd103..c1600ebb 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -31,7 +31,7 @@ class CPedIK public: enum { FLAG_1 = 1, - LOOKING = 2, + LOOKING = 2, // looking while in car? AIMS_WITH_ARM = 4, }; @@ -44,6 +44,8 @@ public: static LimbMovementInfo &ms_torsoInfo; static LimbMovementInfo &ms_headInfo; + static LimbMovementInfo &ms_upperArmInfo; + static LimbMovementInfo &ms_lowerArmInfo; CPedIK(CPed *ped); bool PointGunInDirection(float phi, float theta);