summaryrefslogtreecommitdiffstats
path: root/src/peds
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds')
-rw-r--r--src/peds/Ped.cpp487
-rw-r--r--src/peds/Ped.h39
-rw-r--r--src/peds/PlayerPed.cpp41
-rw-r--r--src/peds/PlayerPed.h17
4 files changed, 531 insertions, 53 deletions
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index f8b44301..d05568f6 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;
@@ -79,7 +79,7 @@ CPed::~CPed(void)
CWorld::Remove(this);
CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
if (bInVehicle && m_pMyVehicle){
- uint8 door_flag = GetVehDoorFlag(m_vehEnterType);
+ uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
if (m_pMyVehicle->pDriver == this)
m_pMyVehicle->pDriver = nil;
else {
@@ -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;
@@ -1415,7 +1416,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
ped->m_pSeekTarget = nil;
vehicle = ped->m_pMyVehicle;
- vehicle->m_nGettingOutFlags &= ~GetVehDoorFlag(ped->m_vehEnterType);
+ vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
if (vehicle->pDriver == ped) {
vehicle->RemoveDriver();
@@ -2263,7 +2264,6 @@ CPed::CanPedJumpThis(int32 unused)
{
CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
CVector pos = GetPosition();
- // wat?
CVector forwardPos(
forward.x + pos.x,
forward.y + pos.y,
@@ -2288,19 +2288,19 @@ CPed::CanSeeEntity(CEntity *entity, float threshold)
GetPosition().y);
if (neededAngle < 0.0f)
- neededAngle += 2 * PI;
- else if (neededAngle > 2 * PI)
- neededAngle -= 2 * PI;
+ neededAngle += TWOPI;
+ else if (neededAngle > TWOPI)
+ neededAngle -= TWOPI;
float ourAngle = m_fRotationCur;
if (ourAngle < 0.0f)
- ourAngle += 2 * PI;
- else if (ourAngle > 2 * PI)
- ourAngle -= 2 * PI;
+ ourAngle += TWOPI;
+ else if (ourAngle > TWOPI)
+ ourAngle -= TWOPI;
float neededTurn = Abs(neededAngle - ourAngle);
- return neededTurn < threshold || 2 * PI - threshold < neededTurn;
+ return neededTurn < threshold || TWOPI - threshold < neededTurn;
}
bool
@@ -2725,7 +2725,7 @@ CPed::QuitEnteringCar(void)
if (veh->m_nNumGettingIn != 0)
veh->m_nNumGettingIn--;
- veh->m_nGettingInFlags &= ~GetVehDoorFlag(m_vehEnterType);
+ veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType);
}
bUsesCollision = true;
@@ -2776,7 +2776,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) {
@@ -3659,7 +3659,6 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi
} else {
CDarkel::RegisterKillNotByPlayer(this, method);
}
- // WAT?
if (method == WEAPONTYPE_WATER)
bIsInTheAir = false;
@@ -3892,8 +3891,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;
@@ -4558,7 +4556,7 @@ CPed::GetLocalDirection(CVector2D &posOffset)
{
float direction;
- for (direction = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); direction < 0.0f; direction += 2 * PI);
+ for (direction = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); direction < 0.0f; direction += TWOPI);
for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4);
@@ -4961,7 +4959,21 @@ CPed::PlayHitSound(CPed *hitTo)
{
// That was very complicated to reverse for me...
// First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10).
-
+ enum {
+ S33 = SOUND_FIGHT_PUNCH_33,
+ S34 = SOUND_FIGHT_KICK_34,
+ S35 = SOUND_FIGHT_HEADBUTT_35,
+ S36 = SOUND_FIGHT_PUNCH_36,
+ S37 = SOUND_FIGHT_PUNCH_37,
+ S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
+ S39 = SOUND_FIGHT_PUNCH_39,
+ S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
+ S41 = SOUND_FIGHT_PUNCH_41,
+ S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
+ S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
+ S44 = SOUND_FIGHT_KICK_44,
+ NO_SND = SOUND_TOTAL_PED_SOUNDS
+ };
uint16 hitSoundsByFightMoves[12][10] = {
{S39,S42,S43,S43,S39,S39,S39,S39,S39,S42},
{NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
@@ -5267,6 +5279,419 @@ 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;
+
+ int money = CGeneral::GetRandomNumber() % 60;
+ if (money < 10)
+ return;
+
+ 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)
+ continue;
+
+ angleToPed = i * 1.75f;
+ pickupPos = GetPosition();
+ pickupPos.x += 1.5f * Sin(angleToPed);
+ pickupPos.y += 1.5f * Cos(angleToPed);
+ pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+
+ CVector pedPos = GetPosition();
+ pedPos.z += 0.3f;
+
+ CVector pedToPickup = pickupPos - pedPos;
+ float distance = pedToPickup.Magnitude();
+
+ // outer edge of pickup
+ distance = (distance + 0.3f) / distance;
+ CVector pickupPos2 = pedPos;
+ pickupPos2 += distance * pedToPickup;
+
+ // pickup must be on ground and line to its edge must be clear
+ if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) {
+ // otherwise try another position (but disregard second check apparently)
+ angleToPed += 3.14f;
+ pickupPos = GetPosition();
+ pickupPos.x = 1.5f * Sin(angleToPed);
+ pickupPos.y = 1.5f * Cos(angleToPed);
+ pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+ }
+ if (found)
+ CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, min(weaponAmmo, CPickups::ms_maxAmmosForWeapons[weapon]));
+ }
+ ClearWeapons();
+}
+
+void
+CPed::SetAttackTimer(uint32 time)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_attackTimer)
+ m_attackTimer = max(m_lastHitTime, CTimer::GetTimeInMilliseconds()) + time;
+}
+
+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() - HALFPI;
+
+ if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
+ 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;
+ int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);
+ if (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1;
+ int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);
+ if (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1;
+
+ 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 +5834,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);
-ENDPATCHES \ No newline at end of file
+ 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
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index dcbe247a..db19619b 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -22,23 +22,6 @@ struct CPedAudioData
int m_nMaxRandomDelayTime;
};
-// For hit sounds in fight
-enum {
- S33 = SOUND_FIGHT_PUNCH_33,
- S34 = SOUND_FIGHT_KICK_34,
- S35 = SOUND_FIGHT_HEADBUTT_35,
- S36 = SOUND_FIGHT_PUNCH_36,
- S37 = SOUND_FIGHT_PUNCH_37,
- S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
- S39 = SOUND_FIGHT_PUNCH_39,
- S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
- S41 = SOUND_FIGHT_PUNCH_41,
- S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
- S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
- S44 = SOUND_FIGHT_KICK_44,
- NO_SND = SOUND_TOTAL_PED_SOUNDS
-};
-
struct FightMove
{
AnimationId animId;
@@ -305,10 +288,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;
@@ -394,7 +377,7 @@ public:
float m_fRotationCur;
float m_fRotationDest;
float m_headingRate;
- uint16 m_vehEnterType;
+ uint16 m_vehEnterType; // TODO: this is more like a door, not a type
uint16 m_walkAroundType;
CEntity *m_pCurrentPhysSurface;
CVector m_vecOffsetFromPhysSurface;
@@ -450,7 +433,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 +521,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 +572,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 +639,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);