diff options
Diffstat (limited to '')
-rw-r--r-- | src/peds/Ped.cpp | 42 | ||||
-rw-r--r-- | src/peds/PlayerPed.cpp | 6 | ||||
-rw-r--r-- | src/peds/Population.cpp | 304 | ||||
-rw-r--r-- | src/peds/Population.h | 8 |
4 files changed, 343 insertions, 17 deletions
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 1ea13cc2..8803b5ec 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -237,7 +237,8 @@ static char PersonalityTypeText[][18] = { "Geek Girl", "Old Girl", "Tough Girl", - "Tramp", + "Tramp Male", + "Tramp Female", "Tourist", "Prostitute", "Criminal", @@ -246,6 +247,8 @@ static char PersonalityTypeText[][18] = { "Psycho", "Steward", "Sports Fan", + "Shopper", + "Old Shopper" }; static char WaitStateText[][16] = { @@ -1519,7 +1522,7 @@ CPed::BeingDraggedFromCar(void) #ifdef VC_PED_PORTS if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { if (m_pMyVehicle) { - m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime); + m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f); } } #endif @@ -2954,6 +2957,11 @@ CPed::QuitEnteringCar(void) if (veh->m_nNumGettingIn != 0) veh->m_nNumGettingIn--; +#ifdef VC_PED_PORTS + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) + RestorePreviousObjective(); +#endif + veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType); } @@ -2965,7 +2973,7 @@ CPed::QuitEnteringCar(void) animAssoc = m_pVehicleAnim; if (animAssoc) { animAssoc->blendDelta = -4.0f; - animAssoc->flags |= ASSOC_FADEOUTWHENDONE; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; animAssoc = m_pVehicleAnim; animAssoc->flags &= ~ASSOC_RUNNING; } @@ -4161,7 +4169,10 @@ CPed::ClearObjective(void) { if (IsPedInControl() || m_nPedState == PED_DRIVING) { m_objective = OBJECTIVE_NONE; - +#ifdef VC_PED_PORTS + m_pedInObjective = nil; + m_carInObjective = nil; +#endif if (m_nPedState == PED_DRIVING && m_pMyVehicle) { if (m_pMyVehicle->pDriver != this) { @@ -13603,7 +13614,10 @@ CPed::ProcessObjective(void) if (InVehicle()) { if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN && (m_nPedType != PEDTYPE_COP - || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < 0.000025f)) { +#ifdef VC_PED_PORTS + || m_pMyVehicle->IsBoat() +#endif + || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) { if (m_pMyVehicle->IsTrain()) SetExitTrain(m_pMyVehicle); #ifdef VC_PED_PORTS @@ -16651,6 +16665,14 @@ CPed::WarpPedIntoCar(CVehicle *car) car->bEngineOn = true; DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f); } + +#ifdef VC_PED_PORTS + RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f); + + // VC uses AddInCarAnims but we don't have that + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); + RemoveWeaponWhenEnteringVehicle(); +#else if (car->IsBoat()) { m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); @@ -16664,6 +16686,8 @@ CPed::WarpPedIntoCar(CVehicle *car) else m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); } +#endif + StopNonPartialAnims(); if (car->bIsBus) bRenderPedInCar = false; @@ -16893,11 +16917,17 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) m_vecOffsetSeek = doorOpenPos - GetPosition(); m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; if (car->IsBoat()) { - m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); #ifdef VC_PED_PORTS + // VC checks for handling flag, but we can't do that + if(car->GetModelIndex() == MI_SPEEDER) + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); + else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); + PedSetInCarCB(nil, this); m_ped_flagI4 = true; #else + m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f); m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this); #endif if (IsPlayer()) diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 9d4adcef..b459ed84 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -79,7 +79,11 @@ void CPlayerPed::MakeObjectTargettable(int32 handle)
{
for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {
- if (CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
+ if (
+#ifdef FIX_BUGS
+ m_nTargettableObjects[i] == -1 ||
+#endif
+ CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {
m_nTargettableObjects[i] = handle;
return;
}
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index a2dd5c38..6b15d8c7 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -17,6 +17,7 @@ #include "VisibilityPlugins.h" #include "PedPlacement.h" #include "DummyObject.h" +#include "Script.h" #define CREATION_DIST_MULT_TO_DIST 40.0f #define CREATION_RANGE 10.0f // Being added over the CREATION_DIST_MULT_TO_DIST. @@ -56,10 +57,8 @@ CVector &CPopulation::RegenerationPoint_a = *(CVector*)0x8E2AA4; CVector &CPopulation::RegenerationPoint_b = *(CVector*)0x8E2A98; CVector &CPopulation::RegenerationForward = *(CVector*)0x8F1AD4; -WRAPPER CPed *CPopulation::AddPedInCar(CVehicle *vehicle) { EAXJMP(0x4F5800); } WRAPPER void CPopulation::ManagePopulation(void) { EAXJMP(0x4F3B90); } -WRAPPER void CPopulation::MoveCarsAndPedsOutOfAbandonedZones(void) { EAXJMP(0x4F5BE0); } -WRAPPER void CPopulation::ConvertToRealObject(CDummyObject* obj) { EAXJMP(0x4F45A0); } +WRAPPER bool CPopulation::TestSafeForRealObject(CDummyObject*) { EAXJMP(0x4F4700); } void CPopulation::Initialise() @@ -470,13 +469,13 @@ CPopulation::PedCreationDistMultiplier() } CPed* -CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors) +CPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors) { switch (pedType) { case PEDTYPE_CIVMALE: case PEDTYPE_CIVFEMALE: { - CCivilianPed *ped = new CCivilianPed(pedType, mi); + CCivilianPed *ped = new CCivilianPed(pedType, miOrCopType); ped->GetPosition() = coors; ped->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(ped); @@ -490,7 +489,7 @@ CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors) } case PEDTYPE_COP: { - CCopPed *ped = new CCopPed((eCopType)mi); + CCopPed *ped = new CCopPed((eCopType)miOrCopType); ped->GetPosition() = coors; ped->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(ped); @@ -506,7 +505,7 @@ CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors) case PEDTYPE_GANG8: case PEDTYPE_GANG9: { - CCivilianPed *ped = new CCivilianPed(pedType, mi); + CCivilianPed *ped = new CCivilianPed(pedType, miOrCopType); ped->GetPosition() = coors; ped->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(ped); @@ -538,7 +537,7 @@ CPopulation::AddPed(ePedType pedType, uint32 mi, CVector const &coors) case PEDTYPE_CRIMINAL: case PEDTYPE_PROSTITUTE: { - CCivilianPed *ped = new CCivilianPed(pedType, mi); + CCivilianPed *ped = new CCivilianPed(pedType, miOrCopType); ped->GetPosition() = coors; ped->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(ped); @@ -721,6 +720,291 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree } } +CPed* +CPopulation::AddPedInCar(CVehicle* car) +{ + int defaultModel = MI_MALE01; + bool imSureThatModelIsLoaded = true; + CVector coors = FindPlayerCoors(); + CZoneInfo zoneInfo; + int pedType; + + // May be eCopType, model index or non-sense(for medic), AddPed knows that by looking to ped type. + int preferredModel; + + CTheZones::GetZoneInfoForTimeOfDay(&coors, &zoneInfo); + switch (car->m_modelIndex) { + case MI_FIRETRUCK: + preferredModel = 0; + pedType = PEDTYPE_FIREMAN; + break; + case MI_AMBULAN: + preferredModel = 0; + pedType = PEDTYPE_EMERGENCY; + break; + case MI_FBICAR: + preferredModel = COP_FBI; + pedType = PEDTYPE_COP; + break; + case MI_POLICE: + preferredModel = COP_STREET; + pedType = PEDTYPE_COP; + break; + case MI_ENFORCER: + preferredModel = COP_SWAT; + pedType = PEDTYPE_COP; + break; + case MI_RHINO: + case MI_BARRACKS: + preferredModel = COP_ARMY; + pedType = PEDTYPE_COP; + break; + case MI_TAXI: + case MI_CABBIE: + case MI_BORGNINE: + if (CGeneral::GetRandomTrueFalse()) { + pedType = PEDTYPE_CIVMALE; + preferredModel = MI_TAXI_D; + break; + } + defaultModel = MI_TAXI_D; + + // fall through + default: + int gangOfPed = GANG_MAFIA; + imSureThatModelIsLoaded = false; + + while (gangOfPed < NUM_GANGS && CGangs::GetGangInfo(gangOfPed)->m_nVehicleMI != car->m_modelIndex) + gangOfPed++; + + if (gangOfPed < NUM_GANGS) { + pedType = gangOfPed + PEDTYPE_GANG1; + preferredModel = ChooseGangOccupation(gangOfPed); + } else if (gangOfPed == NUM_GANGS) { + CVehicleModelInfo *carModelInfo = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(car->m_modelIndex)); + int i = 15; + for(; i >= 0; i--) { + // Should return random model each time + preferredModel = ChooseCivilianOccupation(zoneInfo.pedGroup); + if (preferredModel == -1) + preferredModel = defaultModel; + + if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModelInfo->m_vehicleClass)) + break; + } + if (i == -1) + preferredModel = defaultModel; + + pedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_pedType; + } + break; + } + if (!imSureThatModelIsLoaded && !((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->GetRwObject()) { + preferredModel = defaultModel; + pedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(defaultModel))->m_pedType; + } + + CPed *newPed = CPopulation::AddPed((ePedType)pedType, preferredModel, car->GetPosition()); + newPed->bUsesCollision = false; + + // what?? + if (pedType != PEDTYPE_COP) { + newPed->SetCurrentWeapon(WEAPONTYPE_COLT45); + newPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(newPed->GetWeapon()->m_eWeaponType)->m_nModelId); + } + /* + // Miami leftover + if (car->m_vehType == VEHICLE_TYPE_BIKE) { + newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, *((CBike*)car + 308h), 100.0f); + } else */ + + // FIX: Make peds comfortable while driving car/boat +#ifdef FIX_BUGS + { + newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f); + } +#else + { + newPed->m_pVehicleAnim = CAnimManager::BlendAnimation(newPed->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f); + } +#endif + + newPed->StopNonPartialAnims(); + return newPed; +} + +void +CPopulation::MoveCarsAndPedsOutOfAbandonedZones() +{ + eLevelName level; + int zone; + int frame = CTimer::GetFrameCounter() & 7; + if (frame == 1) { + int movedVehicleCount = 0; + int poolSize = CPools::GetVehiclePool()->GetSize(); + for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + + CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if (veh && veh->m_nZoneLevel == LEVEL_NONE && veh->IsCar()) { + + if(veh->m_status != STATUS_ABANDONED && veh->m_status != STATUS_WRECKED && veh->m_status != STATUS_PLAYER && + veh->m_status != STATUS_PLAYER_REMOTE) { + + CVector vehPos(veh->GetPosition()); + CPopulation::FindCollisionZoneForCoors(&vehPos, &zone, &level); + + // Level 0 is transition zones, and we don't wanna touch cars on transition zones. + if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && vehPos.z > -4.0f) { + if (veh->bIsLocked || !veh->CanBeDeleted()) { + switch (movedVehicleCount & 3) { + case 0: + veh->GetPosition() = RegenerationPoint_a; + break; + case 1: + veh->GetPosition() = RegenerationPoint_b; + break; + case 2: + veh->GetPosition() = CVector(RegenerationPoint_a.x, RegenerationPoint_b.y, RegenerationPoint_a.z); + break; + case 3: + veh->GetPosition() = CVector(RegenerationPoint_b.x, RegenerationPoint_a.y, RegenerationPoint_a.z); + break; + default: + break; + } + veh->GetPosition().z += (movedVehicleCount / 4) * 7.0f; + veh->GetForward() = RegenerationForward; + ((CAutomobile*)veh)->PlaceOnRoadProperly(); + CCarCtrl::JoinCarWithRoadSystem(veh); + CTheScripts::ClearSpaceForMissionEntity(veh->GetPosition(), veh); + ++movedVehicleCount; + } else { + CWorld::Remove(veh); + delete veh; + } + } + } + } + } + } else if (frame == 5) { + int poolSize = CPools::GetPedPool()->GetSize(); + for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + + CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex); + if (ped && ped->m_nZoneLevel == LEVEL_NONE && !ped->bInVehicle) { + + CVector pedPos(ped->GetPosition()); + CPopulation::FindCollisionZoneForCoors(&pedPos, &zone, &level); + + // Level 0 is transition zones, and we don't wanna touch peds on transition zones. + if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && pedPos.z > -4.0f) { + if (ped->CanBeDeleted()) { + CWorld::Remove(ped); + delete ped; + } else if (ped->m_nPedType != PEDTYPE_PLAYER1 && ped->m_nPedType != PEDTYPE_PLAYER2) { + ped->GetPosition() = RegenerationPoint_a; + + bool foundGround; + float groundZ = CWorld::FindGroundZFor3DCoord(ped->GetPosition().x, ped->GetPosition().y, + ped->GetPosition().z + 2.0f, &foundGround); + + if (foundGround) { + ped->GetPosition().z = 1.0f + groundZ; + //ped->GetPosition().z += 0.0f; + CTheScripts::ClearSpaceForMissionEntity(ped->GetPosition(), ped); + } + } + } + } + } + } +} + +void +CPopulation::ConvertAllObjectsToDummyObjects() +{ + int poolSize = CPools::GetObjectPool()->GetSize(); + for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + + CObject *obj = CPools::GetObjectPool()->GetSlot(poolIndex); + + if (obj) { + if (obj->CanBeDeleted()) + ConvertToDummyObject(obj); + } + } +} + +void +CPopulation::ConvertToRealObject(CDummyObject *dummy) +{ + if (!TestSafeForRealObject(dummy)) + return; + + CObject *obj = new CObject(dummy); + if (!obj) + return; + + bool makeInvisible; + CWorld::Remove(dummy); + delete dummy; + CWorld::Add(obj); + int16 mi = obj->m_modelIndex; + if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 || + mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8) + makeInvisible = true; + else + makeInvisible = false; + + if (makeInvisible) { + obj->bIsVisible = false; + } else if (obj->m_modelIndex == MI_BUOY) { + obj->bIsStatic = false; + obj->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f); + obj->m_flagD8 = true; + obj->AddToMovingList(); + } +} + +void +CPopulation::ConvertToDummyObject(CObject *obj) +{ + CDummyObject *dummy = new CDummyObject(obj); + if (!dummy) + return; + + dummy->GetMatrix() = obj->GetMatrix(); + dummy->GetMatrix().UpdateRW(); + dummy->UpdateRwFrame(); + + bool makeInvisible; + int16 mi = obj->m_modelIndex; + if (mi == MI_GLASS1 || mi == MI_GLASS2 || mi == MI_GLASS3 || mi == MI_GLASS4 || + mi == MI_GLASS5 || mi == MI_GLASS6 || mi == MI_GLASS7 || mi == MI_GLASS8) + makeInvisible = true; + else + makeInvisible = false; + + if (makeInvisible) { + dummy->bIsVisible = false; + } + + CWorld::Remove(obj); + delete obj; + CWorld::Add(dummy); +} + +bool +CPopulation::TestRoomForDummyObject(CObject *obj) +{ + int16 collidingObjs; + CWorld::FindObjectsKindaColliding(obj->GetPosition(), + CModelInfo::GetModelInfo(obj->m_modelIndex)->GetColModel()->boundingSphere.radius, + false, &collidingObjs, 2, nil, false, true, true, false, false); + + return collidingObjs == 0; +} + STARTPATCHES InjectHook(0x4F3770, &CPopulation::Initialise, PATCH_JUMP); InjectHook(0x4F5780, &CPopulation::ChooseGangOccupation, PATCH_JUMP); @@ -728,4 +1012,8 @@ STARTPATCHES InjectHook(0x4F6010, &CPopulation::FindCollisionZoneForCoors, PATCH_JUMP); InjectHook(0x4F6410, &CPopulation::PedCreationDistMultiplier, PATCH_JUMP); InjectHook(0x4F5280, &CPopulation::AddPed, PATCH_JUMP); + InjectHook(0x4F4470, &CPopulation::ConvertToRealObject, PATCH_JUMP); + InjectHook(0x4F4690, &CPopulation::TestRoomForDummyObject, PATCH_JUMP); + InjectHook(0x4F45A0, &CPopulation::ConvertToDummyObject, PATCH_JUMP); + InjectHook(0x4F4410, &CPopulation::ConvertAllObjectsToDummyObjects, PATCH_JUMP); ENDPATCHES
\ No newline at end of file diff --git a/src/peds/Population.h b/src/peds/Population.h index f22926a0..152fb7ae 100644 --- a/src/peds/Population.h +++ b/src/peds/Population.h @@ -67,7 +67,7 @@ public: static void LoadPedGroups(); static void UpdatePedCount(ePedType, bool); static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool); - static CPed *AddPedInCar(CVehicle *vehicle); + static CPed *AddPedInCar(CVehicle *car); static bool IsPointInSafeZone(CVector *coors); static void RemovePed(CPed *ent); static int32 ChooseCivilianOccupation(int32); @@ -81,5 +81,9 @@ public: static void AddToPopulation(float, float, float, float); static void ManagePopulation(void); static void MoveCarsAndPedsOutOfAbandonedZones(void); - static void ConvertToRealObject(CDummyObject* obj); + static void ConvertToRealObject(CDummyObject*); + static void ConvertToDummyObject(CObject*); + static void ConvertAllObjectsToDummyObjects(void); + static bool TestRoomForDummyObject(CObject*); + static bool TestSafeForRealObject(CDummyObject*); }; |