From 875cdd845db1255329c77c458df993f1b490e8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 2 Aug 2019 01:04:30 +0300 Subject: The Peds --- src/control/Darkel.cpp | 12 +- src/control/Pickups.cpp | 5 + src/control/Pickups.h | 4 + src/core/Wanted.h | 3 + src/peds/Ped.cpp | 469 ++++++++++++++++++++++++++++++++++++++++++++++- src/peds/Ped.h | 20 +- src/peds/PlayerPed.cpp | 41 +++++ src/peds/PlayerPed.h | 17 +- src/vehicles/Vehicle.cpp | 2 +- src/vehicles/Vehicle.h | 2 +- 10 files changed, 547 insertions(+), 28 deletions(-) diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index ad8d1176..670c10fb 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -168,7 +168,7 @@ void CDarkel::ResetOnPlayerDeath() WeaponType = WEAPONTYPE_UZI; if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_bWeaponSlot = InterruptedWeapon; + FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; } @@ -187,7 +187,7 @@ void CDarkel::ResetOnPlayerDeath() WeaponType = WEAPONTYPE_UZI; if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_bWeaponSlot = InterruptedWeapon; + FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; } @@ -234,8 +234,8 @@ void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 FindPlayerPed()->GiveWeapon(weaponType, 0); AmmoInterruptedWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal; FindPlayerPed()->GiveWeapon(weaponType, 30000); - FindPlayerPed()->m_bWeaponSlot = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_bWeaponSlot); + FindPlayerPed()->m_nSelectedWepSlot = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; + FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_nSelectedWepSlot); if (FindPlayerVehicle()) { FindPlayerPed()->m_currentWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; @@ -277,7 +277,7 @@ void CDarkel::Update() WeaponType = WEAPONTYPE_UZI; if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_bWeaponSlot = InterruptedWeapon; + FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; } @@ -306,7 +306,7 @@ void CDarkel::Update() WeaponType = WEAPONTYPE_UZI; if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_bWeaponSlot = InterruptedWeapon; + FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; } diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index c93798fe..2770a948 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -4,11 +4,16 @@ CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; +// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4) +uint16 CPickups::ms_maxAmmosForWeapons[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 }; + WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); } WRAPPER void CPickups::DoCollectableEffects(CEntity *ent) { EAXJMP(0x431C30); } WRAPPER void CPickups::DoMoneyEffects(CEntity *ent) { EAXJMP(0x431F40); } WRAPPER void CPickups::DoMineEffects(CEntity *ent) { EAXJMP(0x4321C0); } WRAPPER void CPickups::DoPickUpEffects(CEntity *ent) { EAXJMP(0x431520); } WRAPPER void CPickups::RemoveAllFloatingPickups() { EAXJMP(0x430800); } +WRAPPER int32 CPickups::GenerateNewOne(CVector, uint32, uint8, uint32) { EAXJMP(0x4304B0); } +WRAPPER int32 CPickups::GenerateNewOne_WeaponType(CVector, eWeaponType, uint8, uint32) { EAXJMP(0x430660); } WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } diff --git a/src/control/Pickups.h b/src/control/Pickups.h index b740e72e..20a779a8 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -1,4 +1,5 @@ #pragma once +#include "Weapon.h" enum ePickupType { @@ -42,8 +43,11 @@ public: static void DoMineEffects(CEntity *ent); static void DoPickUpEffects(CEntity *ent); static void RemoveAllFloatingPickups(); + static int32 GenerateNewOne(CVector, uint32, uint8, uint32); + static int32 GenerateNewOne_WeaponType(CVector, eWeaponType, uint8, uint32); static CPickup (&aPickUps)[NUMPICKUPS]; + static uint16 ms_maxAmmosForWeapons[20]; }; class CPacManPickups diff --git a/src/core/Wanted.h b/src/core/Wanted.h index 1a72f839..7cd89b7e 100644 --- a/src/core/Wanted.h +++ b/src/core/Wanted.h @@ -33,6 +33,9 @@ public: CVector m_vecPosn; bool m_bReported; bool m_bPoliceDoesntCare; + + CCrimeBeingQd() { }; + ~CCrimeBeingQd() { }; }; class CWanted diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index fc01a36d..cee3e008 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -30,9 +30,9 @@ #include "ModelIndices.h" #include "FileMgr.h" #include "TempColModels.h" +#include "Pickups.h" WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); } -WRAPPER void CPed::SetDead(void) { EAXJMP(0x4D3970); } WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); } WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); } @@ -43,13 +43,13 @@ WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); } WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); } WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); } WRAPPER void CPed::RegisterThreatWithGangPeds(CEntity*) { EAXJMP(0x4E3870); } -WRAPPER void CPed::MakeChangesForNewWeapon(int8) { EAXJMP(0x4F2560); } -WRAPPER void CPed::SetSeek(CVector, float) { EAXJMP(0x4D14B0); } WRAPPER bool CPed::Seek(void) { EAXJMP(0x4D1640); } WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); } WRAPPER void CPed::RemoveInCarAnims(void) { EAXJMP(0x4E4E20); } WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); } WRAPPER void CPed::SetDirectionToWalkAroundObject(CEntity*) { EAXJMP(0x4CCEB0); } +WRAPPER void CPed::SetRadioStation(void) { EAXJMP(0x4D7BC0); } +WRAPPER void CPed::MakeTyresMuddySectorList(CPtrList&) { EAXJMP(0x53CFD0); } bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; @@ -283,6 +283,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_type = ENTITY_TYPE_PED; bPedPhysics = true; bUseCollisionRecords = true; +// m_status = STATUS_SIMPLE; m_vecAnimMoveDelta.x = 0.0f; m_vecAnimMoveDelta.y = 0.0f; @@ -320,7 +321,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_standardTimer = 0; m_lastHitTime = 0; m_hitRecoverTimer = 0; - field_4E8 = 0; + m_duckAndCoverTimer = 0; m_moved = CVector2D(0.0f, 0.0f); m_fRotationCur = 0.0f; m_headingRate = 15.0f; @@ -420,10 +421,10 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagF2 = false; m_ped_flagF4 = false; m_ped_flagF8 = false; - m_ped_flagF10 = false; + bWillBeQuickJacked = false; m_ped_flagF20 = false; m_ped_flagF40 = false; - m_ped_flagF80 = false; + bDuckAndCover = false; m_ped_flagG1 = false; m_ped_flagG2 = true; @@ -1354,7 +1355,7 @@ CPed::BeingDraggedFromCar(void) animAssoc->blendDelta = -1000.0f; if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { - if (m_ped_flagF10) { + if (bWillBeQuickJacked) { enterAnim = ANIM_CAR_QJACKED; } else if (m_pMyVehicle->bLowVehicle) { enterAnim = ANIM_CAR_LJACKED_LHS; @@ -2776,7 +2777,7 @@ CPed::ReactToAttack(CEntity *attacker) CPed *attackerPed = (CPed*)attacker; if (bNotAllowedToDuck) { if (!attackerPed->GetWeapon()->IsTypeMelee()) { - field_4E8 = CTimer::GetTimeInMilliseconds(); + m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds(); return; } } else if (bCrouchWhenShooting || bKindaStayInSamePlace) { @@ -3892,8 +3893,7 @@ CPed::ClearWeapons(void) currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); AddWeaponModel(currentWeapon->m_nModelId); - for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) - { + for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { CWeapon &weapon = GetWeapon(i); weapon.m_eWeaponType = WEAPONTYPE_UNARMED; weapon.m_eWeaponState = WEAPONSTATE_READY; @@ -5267,6 +5267,443 @@ CPed::CollideWithPed(CPed *collideWith) } } +void +CPed::CreateDeadPedMoney(void) +{ + if (!CGame::nastyGame) + return; + + int skin = m_modelIndex; + if ((skin >= MI_COP && skin <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle) + return; + + /* + * That was the og output, which is some compiler optimization for mod 60; + * money = rand - 60 * (rand / 60 + (-2004318071i64 * (unsigned __int64)rand >> 32)); + */ + + int money = CGeneral::GetRandomNumber() % 60; + if (money >= 10) { + if (money == 43) + money = 700; + + int pickupCount = money / 40 + 1; + int moneyPerPickup = money / pickupCount; + + for(int i = 0; i < pickupCount; i++) { + float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x; + float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y; + bool found = false; + float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f; + if (found) { + CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7)); + } + } + } +} + +void +CPed::CreateDeadPedWeaponPickups(void) +{ + bool found = false; + float angleToPed; + CVector pickupPos; + + if (bInVehicle) + return; + + for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) { + + eWeaponType weapon = GetWeapon(i).m_eWeaponType; + int weaponAmmo = GetWeapon(i).m_nAmmoTotal; + if (weapon != WEAPONTYPE_UNARMED && weapon != WEAPONTYPE_DETONATOR && weaponAmmo != 0) { + + angleToPed = i * 1.75f; + pickupPos.x = 1.5f * Sin(angleToPed) + GetPosition().x; + pickupPos.y = 1.5f * Cos(angleToPed) + GetPosition().y; + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, GetPosition().z, &found) + 0.5f; + + // CVector point1(0, pickupPos.y, 0); + + CVector point2 = GetPosition(); + point2.z += 0.3f; + + CVector posDiff = pickupPos - point2; + + float distance = posDiff.Magnitude(); + + // I don't know what is this for. Related with Z-axis for sure. + float posDiffMult = (distance + 0.3f) / distance; + + CVector point1 = point2; + point1 += posDiffMult * posDiff; + + if (!found || CWorld::GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false)) { + + // Not PI, it's 3.14f. Funny. + angleToPed += 3.14f; + pickupPos.x = 1.5f * Sin(angleToPed) + GetPosition().x; + pickupPos.y = 1.5f * Cos(angleToPed) + GetPosition().y; + pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, GetPosition().z, &found) + 0.5f; + } + if (found) { + if (weaponAmmo >= CPickups::ms_maxAmmosForWeapons[weapon]) + weaponAmmo = CPickups::ms_maxAmmosForWeapons[weapon]; + + CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, weaponAmmo); + } + } + } + ClearWeapons(); +} + +void +CPed::SetAttackTimer(uint32 time) +{ + if (CTimer::GetTimeInMilliseconds() <= m_attackTimer) + return; + + if (m_lastHitTime <= CTimer::GetTimeInMilliseconds()) + m_attackTimer = time + CTimer::GetTimeInMilliseconds(); + else + m_attackTimer = time + m_lastHitTime; +} + +void +CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack) +{ + if (m_nPedState == PED_DRAG_FROM_CAR) + return; + + bUsesCollision = false; + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_nLastPedState = PED_IDLE; + SetMoveState(PEDMOVE_STILL); + m_pSeekTarget = veh; + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + m_vehEnterType = vehEnterType; + if (m_vehEnterType == CAR_DOOR_LF) { + if (veh->pDriver && veh->pDriver->IsPlayer()) + veh->m_status = STATUS_PLAYER_DISABLED; + else + veh->m_status = STATUS_ABANDONED; + } + RemoveInCarAnims(); + SetMoveState(PEDMOVE_NONE); + LineUpPedWithCar(LINE_UP_TO_CAR_START); + m_pVehicleAnim = nil; + m_nPedState = PED_DRAG_FROM_CAR; + bChangedSeat = false; + bWillBeQuickJacked = quickJack; + + CVector pos = GetPosition(); + GetMatrix().SetRotate(0.0f, 0.0f, m_fRotationCur); + GetPosition() += pos; + + Say(SOUND_PED_CAR_JACKED); + SetRadioStation(); + veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType); +} + +void +CPed::SetBuyIceCream(void) +{ + if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl()) + return; + + if (!m_carInObjective) + return; + + // Side of the Ice Cream van + m_fRotationDest = m_carInObjective->GetForward().Heading() - 0.5 * PI; + + if (Abs(m_fRotationDest - m_fRotationCur) < 0.5 * PI) { + m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000; + m_nPedState = PED_BUY_ICECREAM; + } +} + +void +CPed::SetChat(CEntity* chatWith, uint32 time) +{ + if(m_nPedState != PED_CHAT) + SetStoredState(); + + m_nPedState = PED_CHAT; + SetMoveState(PEDMOVE_STILL); + SetLookFlag(chatWith, 1); + m_standardTimer = CTimer::GetTimeInMilliseconds() + time; + m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000; +} + +void +CPed::SetDead(void) +{ + bUsesCollision = false; + m_fHealth = 0.0f; + if (m_nPedState == PED_DRIVING) + bIsVisible = false; + + m_nPedState = PED_DEAD; + m_pVehicleAnim = nil; + m_pCollidingEntity = nil; + + CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + RemoveWeaponModel(weapon->m_nModelId); + + m_currentWeapon = WEAPONTYPE_UNARMED; + CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250); + if (this != FindPlayerPed()) { + CreateDeadPedWeaponPickups(); + CreateDeadPedMoney(); + } + + // BUG: Is this count or timer?! + m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds(); + m_deadBleeding = 0; + bDoBloodyFootprints = false; + m_ped_flagI4 = false; + CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000); +} + +void +CPed::SetSeek(CEntity *seeking, float unk) +{ + if (!IsPedInControl()) + return; + + if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking) + return; + + if (!seeking) + return; + + if (m_nPedState != PED_SEEK_ENTITY) + SetStoredState(); + + m_nPedState = PED_SEEK_ENTITY; + field_318 = unk; + m_pSeekTarget = seeking; + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + SetMoveState(PEDMOVE_STILL); +} + +void +CPed::SetSeek(CVector pos, float unk) +{ + if (!IsPedInControl() + || (m_nPedState == PED_SEEK_POS && m_vecSeekVehicle.x != pos.x && m_vecSeekVehicle.y != pos.y)) + return; + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 + || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47 + || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE + || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER + || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) { + ClearPointGunAt(); + } + + if (m_nPedState != PED_SEEK_POS) + SetStoredState(); + + m_nPedState = PED_SEEK_POS; + field_318 = unk; + m_vecSeekVehicle = pos; +} + +void +CPed::DeadPedMakesTyresBloody(void) +{ + int minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f); + if (minX <= 0) + minX = 0; + + int minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f); + if (minY <= 0) + minY = 0; + + // BUG: Shouldn't it be NUMSECTORS_X (100)? + int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f); + if (maxX >= 99) + maxX = 99; + + // BUG: Shouldn't it be NUMSECTORS_Y (100)? + int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f); + if (maxY >= 99) + maxY = 99; + + CWorld::AdvanceCurrentScanCode(); + + for (int curY = minY; curY <= maxY; curY++) { + for (int curX = minX; curX <= maxX; curX++) { + CSector* sector = CWorld::GetSector(curX, curY); + MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]); + MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]); + } + } +} + +void +CPed::Die(void) +{ + // UNUSED: This is a perfectly empty function. +} + +uint8 +CPed::DoesLOSBulletHitPed(CColPoint &colPoint) +{ + RwMatrix mat; + + CPedIK::GetWorldMatrix(GetNodeFrame(PED_HEAD), &mat); + float headZ = RwMatrixGetPos(&mat)->z; + + if (m_nPedState == PED_FALL) + return 1; + + float colZ = colPoint.point.z; + if (colZ < headZ) + return 1; + + if (headZ + 0.2f <= colZ) + return 0; + + return 2; +} + +bool +CPed::DuckAndCover(void) +{ + if (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer) + return false; + + if (bKindaStayInSamePlace){ + + if (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) { + if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) { + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + } + if (!bIsAimingGun) + SetAimFlag(m_pedInObjective); + + } else { + bCrouchWhenShooting = false; + bKindaStayInSamePlace = false; + bIsDucking = false; + bDuckAndCover = false; + m_headingRate = 10.0f; + m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000); + if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) + ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--; + } + return false; + } + + bool justDucked = false; + CVehicle *foundVeh = nil; + float maxDist = 225.0f; + bIsDucking = false; + bCrouchWhenShooting = false; + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { + CVector pos = GetPosition(); + int16 lastVehicle; + CEntity* vehicles[8]; + CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + + for (int i = 0; i < lastVehicle; i++) { + CVehicle *veh = (CVehicle*) vehicles[i]; + if (veh->m_vecMoveSpeed.Magnitude() <= 0.02f + && !veh->bIsBus + && !veh->bIsVan + && !veh->bIsBig + && veh->m_numPedsUseItAsCover < 3) { + float dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr(); + if (dist < maxDist) { + maxDist = dist; + foundVeh = veh; + } + } + } + if (foundVeh) { + // Unused. + // CVector lfWheelPos, rfWheelPos; + // foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos); + // foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos); + CVector rightSide, leftSide; + + // 3 persons can use the car as cover. Found the correct position for us. + if (foundVeh->m_numPedsUseItAsCover == 2) { + rightSide = CVector(1.5f, -0.5f, 0.0f); + leftSide = CVector(-1.5f, -0.5f, 0.0f); + } else if (foundVeh->m_numPedsUseItAsCover == 1) { + rightSide = CVector(1.5f, 0.5f, 0.0f); + leftSide = CVector(-1.5f, 0.5f, 0.0f); + } else if (foundVeh->m_numPedsUseItAsCover == 0) { + rightSide = CVector(1.5f, 0.0f, 0.0f); + leftSide = CVector(-1.5f, 0.0f, 0.0f); + } + + CMatrix vehMatrix(foundVeh->GetMatrix()); + CVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition(); + + CVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition(); + + CVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide; + CVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide; + + CVector duckPos; + if (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr()) + duckPos = duckAtLeftSide; + else + duckPos = duckAtRightSide; + + if (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false) + && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) { + SetSeek(duckPos, 1.0f); + m_headingRate = 15.0f; + m_ped_flagB20 = true; + bDuckAndCover = true; + justDucked = true; + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500; + if (foundVeh->bIsLawEnforcer) + m_carInObjective = foundVeh; + + // BUG? Shouldn't we register the reference? + m_pSeekTarget = foundVeh; + ClearPointGunAt(); + } else { + m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000); + bDuckAndCover = false; + } + } else { + bDuckAndCover = false; + } + } + + if (!justDucked && !bDuckAndCover) + return false; + + if (!Seek()) + return true; + + bKindaStayInSamePlace = true; + bDuckAndCover = false; + m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) + ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++; + + SetIdle(); + SetMoveState(PEDMOVE_STILL); + SetMoveAnim(); + if (!m_pLookTarget || m_pLookTarget != m_pedInObjective) { + m_pLookTarget = m_pedInObjective; + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + } + + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000); + return false; +} + 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); } @@ -5409,4 +5846,16 @@ STARTPATCHES InjectHook(0x4D1D70, (void (CPed::*)(CEntity*, int)) &CPed::SetFlee, PATCH_JUMP); InjectHook(0x4D1C40, (void (CPed::*)(CVector2D&, int)) &CPed::SetFlee, PATCH_JUMP); InjectHook(0x4EB9A0, &CPed::CollideWithPed, PATCH_JUMP); + InjectHook(0x433490, &CPed::CreateDeadPedMoney, PATCH_JUMP); + InjectHook(0x433660, &CPed::CreateDeadPedWeaponPickups, PATCH_JUMP); + InjectHook(0x4D3970, &CPed::SetDead, PATCH_JUMP); + InjectHook(0x53CDF0, &CPed::DeadPedMakesTyresBloody, PATCH_JUMP); + InjectHook(0x4E0640, &CPed::SetBeingDraggedFromCar, PATCH_JUMP); + InjectHook(0x4D1300, &CPed::SetAttackTimer, PATCH_JUMP); + InjectHook(0x4D6950, &CPed::SetBuyIceCream, PATCH_JUMP); + InjectHook(0x4D3A60, &CPed::SetChat, PATCH_JUMP); + InjectHook(0x4D14B0, (void (CPed::*)(CVector, float)) &CPed::SetSeek, PATCH_JUMP); + InjectHook(0x4D15A0, (void (CPed::*)(CEntity*, float)) &CPed::SetSeek, PATCH_JUMP); + InjectHook(0x4EB5C0, &CPed::DoesLOSBulletHitPed, PATCH_JUMP); + InjectHook(0x4E3EC0, &CPed::DuckAndCover, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 4269136a..190f9e4c 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -305,10 +305,10 @@ public: uint8 m_ped_flagF2 : 1; uint8 m_ped_flagF4 : 1; uint8 m_ped_flagF8 : 1; - uint8 m_ped_flagF10 : 1; // set before "quickjack" + uint8 bWillBeQuickJacked : 1; uint8 m_ped_flagF20 : 1; uint8 m_ped_flagF40 : 1; - uint8 m_ped_flagF80 : 1; + uint8 bDuckAndCover : 1; uint8 m_ped_flagG1 : 1; uint8 m_ped_flagG2 : 1; @@ -450,7 +450,7 @@ public: uint32 m_hitRecoverTimer; uint32 m_objectiveTimer; uint32 m_duckTimer; - uint32 field_4E8; + uint32 m_duckAndCoverTimer; int32 m_bloodyFootprintCount; uint8 m_panicCounter; uint8 m_deadBleeding; @@ -538,9 +538,9 @@ public: void RegisterThreatWithGangPeds(CEntity*); bool TurnBody(void); void Chat(void); - void MakeChangesForNewWeapon(int8); void CheckAroundForPossibleCollisions(void); void SetSeek(CVector, float); + void SetSeek(CEntity*, float); bool MakePhonecall(void); bool FacePhone(void); CPed *CheckForDeadPeds(void); @@ -589,6 +589,17 @@ public: void RemoveInCarAnims(void); void CollideWithPed(CPed*); void SetDirectionToWalkAroundObject(CEntity*); + void CreateDeadPedMoney(void); + void CreateDeadPedWeaponPickups(void); + void SetAttackTimer(uint32); + void SetBeingDraggedFromCar(CVehicle*, uint32, bool); + void SetRadioStation(void); + void SetBuyIceCream(void); + void SetChat(CEntity*, uint32); + void DeadPedMakesTyresBloody(void); + void MakeTyresMuddySectorList(CPtrList&); + uint8 DoesLOSBulletHitPed(CColPoint &point); + bool DuckAndCover(void); // Static methods static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset); @@ -645,6 +656,7 @@ public: void SetLeader(CEntity* leader); void SetPedStats(ePedStats); bool IsGangMember(void); + void Die(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/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 24eb4a35..361a9098 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -3,6 +3,7 @@ #include "PlayerPed.h" #include "Camera.h" #include "WeaponEffects.h" +#include "ModelIndices.h" CPlayerPed::~CPlayerPed() { @@ -14,7 +15,45 @@ WRAPPER void CPlayerPed::SetupPlayerPed(int32) { EAXJMP(0x4EFB60); } WRAPPER void CPlayerPed::DeactivatePlayerPed(int32) { EAXJMP(0x4EFC00); } WRAPPER void CPlayerPed::ReactivatePlayerPed(int32) { EAXJMP(0x4EFC20); } WRAPPER void CPlayerPed::KeepAreaAroundPlayerClear(void) { EAXJMP(0x4F3460); } +WRAPPER void CPlayerPed::MakeChangesForNewWeapon(int8) { EAXJMP(0x4F2560); } +WRAPPER void CPlayerPed::SetInitialState(void) { EAXJMP(0x4EFC40); } +WRAPPER void CPlayerPed::SetMoveAnim(void) { EAXJMP(0x4F3760); } +WRAPPER void CPlayerPed::ProcessControl(void) { EAXJMP(0x4EFD90); } +CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) +{ + m_fMoveSpeed = 0.0f; + SetModelIndex(MI_PLAYER); + SetInitialState(); + + m_pWanted = new CWanted(); + m_pWanted->Initialise(); + m_pArrestingCop = nil; + m_currentWeapon = WEAPONTYPE_UNARMED; + m_nSelectedWepSlot = 0; + m_nSpeedTimer = 0; + m_bSpeedTimerFlag = 0; + m_pPointGunAt = nil; + m_nPedState = PED_IDLE; + m_fMaxStamina = 150.0f; + m_fCurrentStamina = m_fMaxStamina; + m_fStaminaProgress = 0.0f; + m_bShouldEvade = 0; + field_1367 = 0; + m_nShotDelay = 0; + field_1376 = 0.0f; + field_1380 = 0; + m_bHasLockOnTarget = false; + m_bCanBeDamaged = true; + m_fWalkAngle = 0.0f; + m_fFPSMoveHeading = 0.0f; + m_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1; + field_1413 = 0; + for (int i = 0; i < 6; i++) { + m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f); + field_1488[i] = 0; + } +} void CPlayerPed::ClearWeaponTarget() { @@ -58,10 +97,12 @@ CPlayerPed::AnnoyPlayerPed(bool itsPolice) class CPlayerPed_ : public CPlayerPed { public: + CPlayerPed* ctor(void) { return ::new (this) CPlayerPed(); } void dtor(void) { CPlayerPed::~CPlayerPed(); } }; STARTPATCHES + InjectHook(0x4EF7E0, &CPlayerPed_::ctor, PATCH_JUMP); InjectHook(0x4EFB30, &CPlayerPed_::dtor, PATCH_JUMP); InjectHook(0x4F28A0, &CPlayerPed::ClearWeaponTarget, PATCH_JUMP); InjectHook(0x4F3700, &CPlayerPed::AnnoyPlayerPed, PATCH_JUMP); diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index fa6d9d43..ecef9bef 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -12,14 +12,14 @@ public: float m_fCurrentStamina; float m_fMaxStamina; float m_fStaminaProgress; - bool m_bWeaponSlot; + uint8 m_nSelectedWepSlot; bool m_bSpeedTimerFlag; bool m_bShouldEvade; int8 field_1367; int32 m_nSpeedTimer; int32 m_nShotDelay; - float field_1376; - int8 field_1380; // set if can't attack, why? + float field_1376; // m_fAttackButtonCounter? + int8 field_1380; // bHaveTargetSelected? int8 field_1381; int8 field_1382; int8 field_1383; @@ -34,19 +34,24 @@ public: int8 field_1413; int8 field_1414; int8 field_1415; - CVector field_1416[6]; - int32 field_1488[6]; + CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree + int32 field_1488[6]; // m_pPedAtSafePos? float m_fWalkAngle; float m_fFPSMoveHeading; + CPlayerPed(); ~CPlayerPed(); void ReApplyMoveAnims(void); - void ClearWeaponTarget(); + void ClearWeaponTarget(void); void SetWantedLevel(int32 level); void SetWantedLevelNoDrop(int32 level); void KeepAreaAroundPlayerClear(void); void AnnoyPlayerPed(bool); + void MakeChangesForNewWeapon(int8); + void SetInitialState(void); + void SetMoveAnim(void); + void ProcessControl(void); static void SetupPlayerPed(int32); static void DeactivatePlayerPed(int32); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 36675c8b..aaf5926f 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -77,7 +77,7 @@ CVehicle::CVehicle(uint8 CreatedBy) field_214 = 0; bLightsOn = false; bVehicleColProcessed = false; - field_1F9 = 0; + m_numPedsUseItAsCover = 0; bIsCarParkVehicle = false; bHasAlreadyBeenRecorded = false; m_bSirenOrAlarm = 0; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index f2e7b5d0..07893782 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -169,7 +169,7 @@ public: uint8 m_veh_flagD40 : 1; uint8 m_veh_flagD80 : 1; - int8 field_1F9; + int8 m_numPedsUseItAsCover; uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default) int8 field_1FB; int8 field_1FC[4]; -- cgit v1.2.3