From ce28a6d298408513866716d00dcd16ed8ef5f285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 1 Jul 2019 00:50:40 +0300 Subject: [PATCH] More CPed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: eray orçunus --- src/animation/RpAnimBlend.h | 1 + src/control/PedStats.h | 4 +- src/entities/CivilianPed.cpp | 13 +- src/entities/CivilianPed.h | 6 +- src/entities/CutsceneObject.h | 12 +- src/entities/Entity.h | 2 +- src/entities/Ped.cpp | 434 ++++++++++++++++++++++++++++++++-- src/entities/Ped.h | 123 ++++++++-- src/entities/PedIK.cpp | 14 ++ src/entities/PedIK.h | 1 + src/entities/Physical.h | 13 +- src/weapons/Weapon.cpp | 37 ++- src/weapons/Weapon.h | 10 +- 13 files changed, 608 insertions(+), 62 deletions(-) diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h index 24c3d273..68fa03cb 100644 --- a/src/animation/RpAnimBlend.h +++ b/src/animation/RpAnimBlend.h @@ -24,6 +24,7 @@ void RpAnimBlendClumpRemoveAllAssociations(RpClump *clump); void RpAnimBlendClumpRemoveAssociations(RpClump *clump, uint32 mask); void RpAnimBlendClumpInit(RpClump *clump); bool RpAnimBlendClumpIsInitialized(RpClump *clump); +void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames); AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name); void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg); CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id); diff --git a/src/control/PedStats.h b/src/control/PedStats.h index 78414341..ce92d4da 100644 --- a/src/control/PedStats.h +++ b/src/control/PedStats.h @@ -56,8 +56,6 @@ enum class CPedStats { - static CPedStats *(&ms_apPedStats)[NUM_PEDSTATS]; - public: ePedStats m_type; char m_name[24]; @@ -71,6 +69,8 @@ public: float m_defendWeakness; int16 m_flags; + static CPedStats* (&ms_apPedStats)[NUM_PEDSTATS]; + static void Initialise(void); static void Shutdown(void); static void LoadPedStats(void); diff --git a/src/entities/CivilianPed.cpp b/src/entities/CivilianPed.cpp index cf589211..a4881e71 100644 --- a/src/entities/CivilianPed.cpp +++ b/src/entities/CivilianPed.cpp @@ -2,13 +2,18 @@ #include "patcher.h" #include "CivilianPed.h" -CCivilianPed::CCivilianPed(int pedtype, int mi) +WRAPPER void CCivilianPed::ProcessControl(void) { EAXJMP(0x4BFFE0); } + +CCivilianPed::CCivilianPed(int pedtype, int mi) : CPed(pedtype) { - ctor(pedtype, mi); + CPed::SetModelIndex(mi); + for (int i = 0; i < 10; i++) + { + m_nearPeds[i] = nil; + } } -WRAPPER CCivilianPed* CCivilianPed::ctor(int pedtype, int mi) { EAXJMP(0x4BFF30); } - STARTPATCHES + InjectHook(0x4BFF30, &CCivilianPed::ctor, PATCH_JUMP); InjectHook(0x4BFFC0, &CCivilianPed::dtor, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/entities/CivilianPed.h b/src/entities/CivilianPed.h index 4d3346d3..8d004ad7 100644 --- a/src/entities/CivilianPed.h +++ b/src/entities/CivilianPed.h @@ -6,7 +6,11 @@ class CCivilianPed : public CPed { public: CCivilianPed(int, int); - CCivilianPed* ctor(int, int); + virtual ~CCivilianPed(void) { } + + virtual void ProcessControl(void); + + CCivilianPed *ctor(int pedtype, int mi) { return ::new (this) CCivilianPed(pedtype, mi); }; void dtor(void) { this->CCivilianPed::~CCivilianPed(); } }; static_assert(sizeof(CCivilianPed) == 0x53C, "CCivilianPed: error"); diff --git a/src/entities/CutsceneObject.h b/src/entities/CutsceneObject.h index b4325f4b..9360651e 100644 --- a/src/entities/CutsceneObject.h +++ b/src/entities/CutsceneObject.h @@ -7,12 +7,12 @@ class CCutsceneObject : public CObject public: CCutsceneObject(void); - void SetModelIndex(uint32 id); - void ProcessControl(void); - void PreRender(void); - void Render(void); - bool SetupLighting(void); - void RemoveLighting(bool reset); + virtual void SetModelIndex(uint32 id); + virtual void ProcessControl(void); + virtual void PreRender(void); + virtual void Render(void); + virtual bool SetupLighting(void); + virtual void RemoveLighting(bool reset); void dtor(void) { this->CCutsceneObject::~CCutsceneObject(); } void SetModelIndex_(uint32 id) { CCutsceneObject::SetModelIndex(id); } diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 3e100879..92c4c351 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -95,7 +95,7 @@ public: CReference *m_pFirstReference; CEntity(void); - ~CEntity(void); + virtual ~CEntity(void); virtual void Add(void); virtual void Remove(void); diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 14aad60a..83852132 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -19,10 +19,31 @@ #include "CullZones.h" #include "Population.h" +WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); } +WRAPPER void CPed::KillPedWithCar(CVehicle* veh, float impulse) { EAXJMP(0x4EC430); } +WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); } +WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); } +WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } +WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); } +WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); } +WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2480); } +WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2920); } +WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); } +WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); } +WRAPPER void CPed::Teleport(CVector) { EAXJMP(0x4D3E70); } +WRAPPER void CPed::PreRender(void) { EAXJMP(0x4CFDD0); } +WRAPPER void CPed::Render(void) { EAXJMP(0x4D03F0); } +WRAPPER bool CPed::SetupLighting(void) { EAXJMP(0x4A7D30); } +WRAPPER void CPed::RemoveLighting(bool) { EAXJMP(0x4A7DC0); } +WRAPPER int32 CPed::ProcessEntityCollision(CEntity*, CColPoint*) { EAXJMP(0x4CBB30); } +WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); } + bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; bool &CPed::bPedCheat3 = *(bool*)0x95CD59; +uint16 &CPed::distanceMultToCountPedNear = *(uint16*)0x5F8C98; + CVector &CPed::offsetToOpenRegularCarDoor = *(CVector*)0x62E030; CVector &CPed::offsetToOpenLowCarDoor = *(CVector*)0x62E03C; CVector &CPed::offsetToOpenVanDoor = *(CVector*)0x62E048; @@ -66,7 +87,8 @@ CPed::~CPed(void) DMAudio.DestroyEntity(m_audioEntityId); } -void CPed::FlagToDestroyWhenNextProcessed(void) +void +CPed::FlagToDestroyWhenNextProcessed(void) { bRemoveFromWorld = true; if (!bInVehicle || !m_pMyVehicle) @@ -87,17 +109,6 @@ void CPed::FlagToDestroyWhenNextProcessed(void) m_pVehicleAnim = nil; } -WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); } -WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); } -WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); } -WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); } -WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } -WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); } -WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); } -WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); } -WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); } -WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); } - static char ObjectiveText[34][28] = { "No Obj", "Wait on Foot", @@ -253,6 +264,243 @@ static char WaitStateText[21][16] = { "Finish Flee", }; +CPed::CPed(uint32 pedType) : m_pedIK(this) +{ + m_type = ENTITY_TYPE_PED; + bPedPhysics = true; + bUseCollisionRecords = true; + + m_vecAnimMoveDelta.x = 0.0; + m_vecAnimMoveDelta.y = 0.0; + m_fHealth = 100.0f; + m_fArmour = 0.0f; + m_nPedType = pedType; + field_520 = 0; + m_talkTimer = 0; + m_talkTypeLast = 167; + m_talkType = 167; + m_objective = 0; + m_prevObjective = 0; + m_nCreatedBy = 1; + field_180 = 0; + m_field_16C = nil; + field_170 = 0; + bInVehicle = 0; + m_pMyVehicle = nil; + m_pVehicleAnim = nil; + m_vecOffsetSeek.x = 0.0; + m_vecOffsetSeek.y = 0.0; + m_vecOffsetSeek.z = 0.0; + m_pedFormation = 0; + m_lastThreatTimer = 0; + m_nPedStateTimer = 0; + m_actionX = 0; + m_actionY = 0; + m_phoneTalkTimer = 0; + m_stateUnused = 0; + m_leaveCarTimer = 0; + m_getUpTimer = 0; + m_attackTimer = 0; + m_timerUnused = 0; + m_lookTimer = 0; + m_standardTimer = 0; + m_lastHitTime = 0; + m_hitRecoverTimer = 0; + field_4E8 = 0; + m_movedX = 0; + m_movedY = 0; + m_fRotationCur = 0.0f; + m_headingRate = 15.0f; + m_fRotationDest = 0.0f; + m_vehEnterType = VEHICLE_ENTER_FRONT_LEFT; + m_walkAroundType = 0; + m_pCurrentPhysSurface = nil; + m_vecOffsetFromPhysSurface = CVector(0.0f, 0.0f, 0.0f); + m_pSeekTarget = nil; + m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_wepSkills = 0; + field_318 = 1.0f; + field_31C = 0; + m_phoneId = -1; + m_lastAccident = 0; + m_fleeFrom = nil; + m_fleeFromPosX = 0; + m_fleeFromPosY = 0; + m_fleeTimer = 0; + m_vecSeekPosEx = CVector(0.0f, 0.0f, 0.0f); + m_seekExAngle = 0.0f; + m_nWaitState = 0; + m_nWaitTimer = 0; + m_pCollidingEntity = nil; + m_nPedState = PED_IDLE; + m_nLastPedState = PED_NONE; + m_nMoveState = 1; + m_nStoredActionState = 0; + m_pFire = nil; + m_pPointGunAt = nil; + m_pLookTarget = 0; + m_fLookDirection = 0.0f; + m_pCurSurface = 0; + m_targetUnused = nil; + m_nPathNodes = 0; + m_nCurPathNode = 0; + m_nPathState = 0; + m_pNextPathNode = nil; + m_pLastPathNode = nil; + m_routeLastPoint = -1; + m_routePoints = 0; + m_routePos = 0; + m_routeType = 0; + m_bodyPartBleeding = -1; + + m_fMass = 70.0f; + m_fTurnMass = 100.0f; + m_fAirResistance = 0.4f / m_fMass; + m_fElasticity = 0.05f; + + bIsStanding = false; + m_ped_flagA2 = false; + m_ped_flagA4 = false; + bIsPointingGunAt = false; + bIsLooking = false; + m_ped_flagA20 = false; + bIsRestoringLook = false; + bIsAimingGun = false; + + bIsRestoringGun = false; + bCanPointGunAtTarget = false; + m_ped_flagB4 = false; + m_ped_flagB8 = false; + m_ped_flagB10 = false; + m_ped_flagB20 = false; + m_ped_flagB40 = false; + m_ped_flagB80 = false; + + m_ped_flagC1 = false; + m_ped_flagC2 = true; + m_ped_flagC4 = true; + m_ped_flagC8 = false; + m_ped_flagC10 = false; + m_ped_flagC20 = false; + m_ped_flagC40 = false; + m_ped_flagC80 = false; + + m_ped_flagD1 = false; + m_ped_flagD2 = false; + m_ped_flagD4 = false; + m_ped_flagD8 = false; + m_ped_flagD10 = false; + m_ped_flagD20 = false; + m_ped_flagD40 = false; + m_ped_flagD80 = false; + + m_ped_flagE1 = false; + m_ped_flagE2 = false; + m_ped_flagE4 = false; + m_ped_flagE8 = false; + bCantFireBecauseCrouched = false; + m_ped_flagE20 = false; + bDoBloodyFootprints = false; + m_ped_flagE80 = false; + + m_ped_flagF1 = false; + m_ped_flagF2 = false; + m_ped_flagF4 = false; + m_ped_flagF8 = false; + m_ped_flagF10 = false; + m_ped_flagF20 = false; + m_ped_flagF40 = false; + m_ped_flagF80 = false; + + m_ped_flagG1 = false; + m_ped_flagG2 = true; + m_ped_flagG4 = false; + m_ped_flagG8 = false; + m_ped_flagG10 = false; + m_ped_flagG20 = false; + m_ped_flagG40 = false; + m_ped_flagG80 = false; + + m_ped_flagH1 = false; + m_ped_flagH2 = false; + m_ped_flagH4 = false; + m_ped_flagH8 = false; + m_ped_flagH10 = false; + m_ped_flagH20 = false; + m_ped_flagH40 = false; + m_ped_flagH80 = false; + + m_ped_flagI1 = false; + m_ped_flagI2 = false; + m_ped_flagI4 = false; + bRecordedForReplay = false; + m_ped_flagI10 = false; + + if ((CGeneral::GetRandomNumber() & 3) == 0) + m_ped_flagD1 = true; + + m_audioEntityId = DMAudio.CreateEntity(0, this); + DMAudio.SetEntityStatus(m_audioEntityId, 1); + m_fearFlags = CPedType::GetThreats(m_nPedType); + m_threatEntity = nil; + m_eventOrThread = CVector2D(0.0f, 0.0f); + m_pEventEntity = nil; + m_fAngleToEvent = 0.0f; + m_numNearPeds = 0; + + for (int i = 0; i < 10; i++) + { + m_nearPeds[i] = nil; + if (i < 8) { + m_pPathNodesStates[i] = nil; + } + } + m_maxWeaponTypeAllowed = 0; + m_currentWeapon = 0; + m_storedWeapon = NO_STORED_WEAPON; + + for(int i = 0; i < NUM_PED_WEAPONTYPES; i++) + { + GetWeapon(i)->m_eWeaponType = WEAPONTYPE_UNARMED; + GetWeapon(i)->m_eWeaponState = WEAPONSTATE_READY; + GetWeapon(i)->m_nAmmoInClip = 0; + GetWeapon(i)->m_nAmmoTotal = 0; + GetWeapon(i)->m_nTimer = 0; + } + + m_lastHitState = 0; + GiveWeapon(WEAPONTYPE_UNARMED, 0); + m_wepAccuracy = 60; + m_lastWepDam = -1; + m_collPoly.valid = false; + m_fCollisionSpeed = 0.0f; + m_wepModelID = -1; + CPopulation::UpdatePedCount(m_nPedType, false); +} + +void +CPed::GiveWeapon(eWeaponType weaponType, int ammo) +{ + CWeapon *weapon = GetWeapon(weaponType); + if (HasWeapon(weaponType)) + { + if (ammo > 99999) + weapon->m_nAmmoTotal = 99999; + else + weapon->m_nAmmoTotal = ammo; + + weapon->Reload(); + } + else + { + weapon->Initialise(weaponType, ammo); + // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous. + m_maxWeaponTypeAllowed++; + } + if (weapon->m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO) + weapon->m_eWeaponState = WEAPONSTATE_READY; +} + static RwObject* RemoveAllModelCB(RwObject *object, void *data) { @@ -787,7 +1035,7 @@ CPed::Attack(void) if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) { if (weaponAnimAssoc->speed < 1.0f) - weaponAnimAssoc->speed = 1.0; + weaponAnimAssoc->speed = 1.0f; } else { firePos = ourWeapon->m_vecFireOffset; @@ -871,7 +1119,7 @@ CPed::Attack(void) } animLoopEnd = ourWeapon->m_fAnimLoopEnd; if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay) - animLoopEnd = 0.56f; + animLoopEnd = 3.4f/6.0f; weaponAnimTime = weaponAnimAssoc->currentTime; @@ -986,8 +1234,8 @@ CPed::SelectGunIfArmed(void) for (int i = 0; i < m_maxWeaponTypeAllowed; i++) { - if (m_weapons[i].m_nAmmoTotal > 0) { - weaponType = m_weapons[i].m_eWeaponType; + if (GetWeapon(i)->m_nAmmoTotal > 0) { + weaponType = GetWeapon(i)->m_eWeaponType; if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) { SetCurrentWeapon(weaponType); @@ -1659,6 +1907,154 @@ CPed::PlayFootSteps(void) } } +bool +CPed::IsPointerValid(void) +{ + int8 pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8; + if (pedIndex < 0 || pedIndex >= NUMPEDS) + return false; + + if (m_entryInfoList.first || FindPlayerPed() == this) + return true; + + return false; +} + +// Binary insertion sort +void +CPed::SortPeds(CPed** list, int min, int max) +{ + if (min >= max) + return; + + CVector leftDiff, rightDiff; + CVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition(); + float middleDist = middleDiff.Magnitude(); + + int left = max; + int right; + for(right = min; right <= left; ) + { + // Those 1.0s are to make sure loop always run for first time. + for (float rightDist = middleDist-1.0f; middleDist > rightDist; right++) + { + rightDiff = GetPosition() - list[right]->GetPosition(); + rightDist = rightDiff.Magnitude(); + } + right--; + + for (float leftDist = middleDist+1.0f; middleDist < leftDist; left--) + { + leftDiff = GetPosition() - list[left]->GetPosition(); + leftDist = leftDiff.Magnitude(); + } + left++; + + if (right <= left) + { + CPed *ped = list[right]; + list[right] = list[left]; + list[left] = ped; + right++; + left--; + } + } + SortPeds(list, min, left); + SortPeds(list, right, max); +} + +void +CPed::BuildPedLists(void) +{ + static CPed* unsortedNearPeds[10]; + static uint16 nextNearPedSlot; + + if ((CTimer::GetFrameCounter() + m_randomSeed) & 15) { + + for(int i = 0; i < 10; ) { + if (m_nearPeds[i]) { + if (m_nearPeds[i]->IsPointerValid()) { + float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D(); + if (distSqr < 900.0f) { + i++; + continue; + } + } + + // If we arrive here, the ped we're checking isn't "near", so we should remove it. + for (int j = i; j < 9; j++) { + m_nearPeds[j] = m_nearPeds[j + 1]; + m_nearPeds[j + 1] = nil; + } + // Above loop won't work when it's 9, so we need to empty slot 9. + m_nearPeds[9] = nil; + m_numNearPeds--; + } else + i++; + } + } else { + CVector centre = CEntity::GetBoundCentre(); + CRect rect( + (centre.x - 20.0f) * 0.025f + 50.0f, + (centre.y - 20.0f) * 0.025f + 50.0f, + (centre.x + 20.0f) * 0.025f + 50.0f, + (centre.y + 20.0f) * 0.025f + 50.0f); + + nextNearPedSlot = 0; + for(int y = rect.top; y <= rect.bottom; y++) + { + for(int x = rect.left; x <= rect.right; x++) + { + for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) + { + CPed *ped = (CPed*)pedPtrNode->item; + if (ped != this && !ped->bInVehicle) + { + float dist = (ped->GetPosition() - GetPosition()).Magnitude2D(); + if (distanceMultToCountPedNear * 30.0f > dist) + { + unsortedNearPeds[nextNearPedSlot] = ped; + nextNearPedSlot++; + } + } + } + } + } + unsortedNearPeds[nextNearPedSlot] = nil; + SortPeds(unsortedNearPeds, 0, nextNearPedSlot - 1); + for (m_numNearPeds = 0; m_numNearPeds < 10; m_numNearPeds++) + { + CPed *ped = unsortedNearPeds[m_numNearPeds]; + if (!ped) + break; + + m_nearPeds[m_numNearPeds] = ped; + } + for (int pedToClear = m_numNearPeds; pedToClear < 10; pedToClear++) + m_nearPeds[pedToClear] = nil; + } +} + +void +CPed::SetPedStats(ePedStats pedStat) +{ + m_pedStats = CPedStats::ms_apPedStats[pedStat]; +} + +void +CPed::SetModelIndex(uint32 mi) +{ + CEntity::SetModelIndex(mi); + RpAnimBlendClumpInit((RpClump*) m_rwObject); + RpAnimBlendClumpFillFrameArray((RpClump*) m_rwObject, m_pFrames); + CPedModelInfo *modelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex); + SetPedStats(static_cast(modelInfo->m_pedStatType)); + m_headingRate = m_pedStats->m_headingChangeRate; + m_animGroup = static_cast(modelInfo->m_animGroup); + CAnimManager::AddAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE); + (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta; +} + 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); } @@ -1684,6 +2080,7 @@ WRAPPER void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4 WRAPPER void CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6550); } STARTPATCHES + InjectHook(0x4C41C0, &CPed::ctor, PATCH_JUMP); InjectHook(0x4C50D0, &CPed::dtor, PATCH_JUMP); InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP); InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP); @@ -1714,4 +2111,9 @@ STARTPATCHES InjectHook(0x4E1A30, (void (*)(CVector*, CVehicle*, uint32)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); InjectHook(0x4DF940, &CPed::LineUpPedWithCar, PATCH_JUMP); InjectHook(0x4CC6C0, &CPed::PlayFootSteps, PATCH_JUMP); + InjectHook(0x4C5350, &CPed::BuildPedLists, PATCH_JUMP); + InjectHook(0x4CF9B0, &CPed::GiveWeapon, PATCH_JUMP); + InjectHook(0x4C5330, &CPed::SetPedStats, PATCH_JUMP); + InjectHook(0x4C52A0, &CPed::SetModelIndex_, PATCH_JUMP); + InjectHook(0x4D6570, &CPed::FlagToDestroyWhenNextProcessed_, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Ped.h b/src/entities/Ped.h index 8f4939fc..741004a2 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -121,6 +121,7 @@ public: uint8 m_ped_flagA20 : 1; // "look" method? - probably missing in SA uint8 bIsRestoringLook : 1; uint8 bIsAimingGun : 1; + uint8 bIsRestoringGun : 1; uint8 bCanPointGunAtTarget : 1; uint8 m_ped_flagB4 : 1; @@ -129,6 +130,7 @@ public: uint8 m_ped_flagB20 : 1; uint8 m_ped_flagB40 : 1; uint8 m_ped_flagB80 : 1; + uint8 m_ped_flagC1 : 1; uint8 m_ped_flagC2 : 1; uint8 m_ped_flagC4 : 1; @@ -137,6 +139,7 @@ public: uint8 m_ped_flagC20 : 1; // just left some body part? uint8 m_ped_flagC40 : 1; uint8 m_ped_flagC80 : 1; + uint8 m_ped_flagD1 : 1; uint8 m_ped_flagD2 : 1; uint8 m_ped_flagD4 : 1; @@ -145,6 +148,7 @@ public: uint8 m_ped_flagD20 : 1; uint8 m_ped_flagD40 : 1; uint8 m_ped_flagD80 : 1; + uint8 m_ped_flagE1 : 1; uint8 m_ped_flagE2 : 1; uint8 m_ped_flagE4 : 1; @@ -153,6 +157,7 @@ public: uint8 m_ped_flagE20 : 1; uint8 bDoBloodyFootprints : 1; uint8 m_ped_flagE80 : 1; + uint8 m_ped_flagF1 : 1; uint8 m_ped_flagF2 : 1; uint8 m_ped_flagF4 : 1; @@ -161,6 +166,7 @@ public: uint8 m_ped_flagF20 : 1; uint8 m_ped_flagF40 : 1; uint8 m_ped_flagF80 : 1; + uint8 m_ped_flagG1 : 1; uint8 m_ped_flagG2 : 1; uint8 m_ped_flagG4 : 1; @@ -169,6 +175,7 @@ public: uint8 m_ped_flagG20 : 1; uint8 m_ped_flagG40 : 1; uint8 m_ped_flagG80 : 1; + uint8 m_ped_flagH1 : 1; uint8 m_ped_flagH2 : 1; uint8 m_ped_flagH4 : 1; @@ -177,6 +184,7 @@ public: uint8 m_ped_flagH20 : 1; uint8 m_ped_flagH40 : 1; uint8 m_ped_flagH80 : 1; + uint8 m_ped_flagI1 : 1; uint8 m_ped_flagI2 : 1; uint8 m_ped_flagI4 : 1; @@ -187,10 +195,22 @@ public: uint8 m_ped_flagI80 : 1; uint8 stuff10[3]; uint8 m_nCreatedBy; - uint8 stuff14[11]; - CPed *m_field_16C; - uint8 stuff12[44]; - int32 m_pEventEntity; + uint8 field_161; + uint8 pad_162[2]; + uint32 m_objective; + uint32 m_prevObjective; + CPed* m_field_16C; + uint32 field_170; + uint32 field_174; + uint32 field_178; + uint32 field_17C; + uint32 field_180; + uint32 m_pedFormation; + uint32 m_fearFlags; + CEntity *m_threatEntity; + CVector2D m_eventOrThread; + uint32 m_eventType; + CEntity* m_pEventEntity; float m_fAngleToEvent; AnimBlendFrameData *m_pFrames[PED_NODE_MAX]; AssocGroupId m_animGroup; @@ -198,7 +218,8 @@ public: CVector2D m_vecAnimMoveDelta; CVector m_vecOffsetSeek; CPedIK m_pedIK; - uint8 stuff1[8]; + float m_actionX; + float m_actionY; uint32 m_nPedStateTimer; PedState m_nPedState; PedState m_nLastPedState; @@ -206,10 +227,9 @@ public: int32 m_nStoredActionState; int32 m_nPrevActionState; int32 m_nWaitState; - int32 m_nWaitTimer; -private: - uint32 stuff0[28]; -public: + uint32 m_nWaitTimer; + void *m_pPathNodesStates[8]; + CVector2D m_stPathNodeStates[10]; uint16 m_nPathNodes; uint8 m_nCurPathNode; int8 m_nPathState; @@ -220,7 +240,14 @@ public: CPathNode *m_pLastPathNode; float m_fHealth; float m_fArmour; - uint8 stuff2[20]; + int16 m_routeLastPoint; + uint16 m_routePoints; + uint16 m_routePos; + uint16 m_routeType; + uint16 m_routeCurDir; + uint16 field_2D2; + float m_movedX; + float m_movedY; float m_fRotationCur; float m_fRotationDest; uint32 m_headingRate; @@ -229,24 +256,43 @@ public: CEntity *m_pCurrentPhysSurface; CVector m_vecOffsetFromPhysSurface; CEntity *m_pCurSurface; - uint8 stuff3[12]; + CVector m_vecSeekVehicle; CEntity *m_pSeekTarget; CVehicle *m_pMyVehicle; bool bInVehicle; - uint8 stuff4[23]; + uint8 pad_315[3]; + uint32 field_318; + uint8 field_31C; + uint8 field_31D; + int16 m_phoneId; + uint32 m_lookingForPhone; + uint32 m_phoneTalkTimer; + void *m_lastAccident; int32 m_nPedType; CPedStats *m_pedStats; - uint8 stuff5[24]; + float m_fleeFromPosX; + float m_fleeFromPosY; + CEntity *m_fleeFrom; + uint32 m_fleeTimer; + uint32 field_344; + uint32 m_lastThreatTimer; CEntity *m_pCollidingEntity; - uint8 stuff6[12]; + uint8 m_stateUnused; + uint8 pad_351[3]; + uint32 m_timerUnused; + CEntity *m_targetUnused; CWeapon m_weapons[NUM_PED_WEAPONTYPES]; eWeaponType m_storedWeapon; uint8 m_currentWeapon; // eWeaponType uint8 m_maxWeaponTypeAllowed; // eWeaponType - uint8 stuff[2]; - int32 m_pPointGunAt; + uint8 m_wepSkills; + uint8 m_wepAccuracy; + CEntity *m_pPointGunAt; CVector m_vecHitLastPos; - uint8 stuff8[8]; + uint32 m_lastHitState; + uint8 m_fightFlags1; + uint8 m_fightFlags2; + uint8 pad_4B2[2]; CFire* m_pFire; CEntity *m_pLookTarget; float m_fLookDirection; @@ -260,23 +306,43 @@ public: uint32 m_hitRecoverTimer; uint32 field_4E0; uint32 m_duckTimer; - uint8 stuff13[4]; + uint32 field_4E8; int32 m_bloodyFootprintCount; uint8 stuff9[2]; - uint8 m_bodyPartBleeding; // PedNode + int8 m_bodyPartBleeding; // PedNode uint8 m_field_4F3; CPed *m_nearPeds[10]; uint16 m_numNearPeds; - uint8 stuff11[30]; + int8 m_lastWepDam; + uint8 pad_51F; + uint8 field_520; + uint8 pad_521[3]; + uint32 m_talkTimer; + uint16 m_talkTypeLast; + uint16 m_talkType; + CVector m_vecSeekPosEx; + float m_seekExAngle; static void *operator new(size_t); static void *operator new(size_t, int); static void operator delete(void*, size_t); static void operator delete(void*, int); - ~CPed(void); - void FlagToDestroyWhenNextProcessed(void); + CPed(uint32 pedType); + virtual ~CPed(void); + virtual void SetModelIndex(uint32 mi); + virtual void ProcessControl(void); + virtual void Teleport(CVector); + virtual void PreRender(void); + virtual void Render(void); + virtual bool SetupLighting(void); + virtual void RemoveLighting(bool); + virtual void FlagToDestroyWhenNextProcessed(void); + virtual int32 ProcessEntityCollision(CEntity*, CColPoint*); + virtual void SetMoveAnim(void); + + CPed* ctor(uint32 pedType) { return ::new (this) CPed(pedType); } void dtor(void) { this->CPed::~CPed(); } bool IsPlayer(void); @@ -313,6 +379,11 @@ public: void SetPedPositionInCar(void); void PlayFootSteps(void); void QuitEnteringCar(void); + bool IsPointerValid(void); + void SortPeds(CPed**, int, int); + void BuildPedLists(void); + void GiveWeapon(eWeaponType weaponType, int ammo); + void SetPedStats(ePedStats); static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); static void GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult); static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType); @@ -347,8 +418,16 @@ public: bool HasWeapon(eWeaponType weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } + CWeapon* GetWeapon(uint32 weaponType) { return &m_weapons[weaponType]; } RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; } + // to make patching virtual functions possible + void SetModelIndex_(uint32 mi) { CPed::SetModelIndex(mi); } + void FlagToDestroyWhenNextProcessed_(void) { CPed::FlagToDestroyWhenNextProcessed(); } + + // set by 0482:set_threat_reaction_range_multiplier opcode + static uint16 &distanceMultToCountPedNear; + static CVector &offsetToOpenRegularCarDoor; static CVector &offsetToOpenLowCarDoor; static CVector &offsetToOpenVanDoor; diff --git a/src/entities/PedIK.cpp b/src/entities/PedIK.cpp index ebc17097..9d688ff9 100644 --- a/src/entities/PedIK.cpp +++ b/src/entities/PedIK.cpp @@ -6,6 +6,20 @@ WRAPPER bool CPedIK::PointGunInDirection(float phi, float theta) { EAXJMP(0x4ED9B0); } WRAPPER bool CPedIK::PointGunAtPosition(CVector *position) { EAXJMP(0x4ED920); } +CPedIK::CPedIK(CPed *ped) +{ + m_ped = ped; + m_flags = 0; + m_headOrient.phi = 0.0f; + m_headOrient.theta = 0.0f; + m_torsoOrient.phi = 0.0f; + m_torsoOrient.theta = 0.0f; + m_upperArmOrient.phi = 0.0f; + m_upperArmOrient.theta = 0.0f; + m_lowerArmOrient.phi = 0.0f; + m_lowerArmOrient.theta = 0.0f; +} + void CPedIK::GetComponentPosition(RwV3d *pos, PedNode node) { diff --git a/src/entities/PedIK.h b/src/entities/PedIK.h index 68e4014a..7c798dc2 100644 --- a/src/entities/PedIK.h +++ b/src/entities/PedIK.h @@ -27,6 +27,7 @@ public: LimbOrientation m_lowerArmOrient; int32 m_flags; + CPedIK(CPed *ped); bool PointGunInDirection(float phi, float theta); bool PointGunAtPosition(CVector *position); void GetComponentPosition(RwV3d *pos, PedNode node); diff --git a/src/entities/Physical.h b/src/entities/Physical.h index 25bc1185..7776da92 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -65,12 +65,13 @@ public: ~CPhysical(void); // from CEntity - void Add(void); - void Remove(void); - CRect GetBoundRect(void); - void ProcessControl(void); - + virtual void Add(void); + virtual void Remove(void); + virtual CRect GetBoundRect(void); + virtual void ProcessControl(void); virtual int32 ProcessEntityCollision(CEntity *ent, CColPoint *point); + virtual void ProcessShift(void); + virtual void ProcessCollision(void); void RemoveAndAdd(void); void AddToMovingList(void); @@ -130,8 +131,6 @@ public: bool ProcessCollisionSectorList(CPtrList *lists); bool CheckCollision(void); bool CheckCollision_SimpleCar(void); - void ProcessShift(void); - void ProcessCollision(void); // to make patching virtual functions possible void dtor(void) { this->CPhysical::~CPhysical(); } diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index fea09245..0c48db6b 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1,6 +1,41 @@ #include "common.h" #include "patcher.h" #include "Weapon.h" +#include "Timer.h" +#include "WeaponInfo.h" WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); } -WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); } \ No newline at end of file +WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); } + +void +CWeapon::Initialise(eWeaponType type, int ammo) +{ + m_eWeaponType = type; + m_eWeaponState = WEAPONSTATE_READY; + if (ammo > 99999) + m_nAmmoTotal = 99999; + else + m_nAmmoTotal = ammo; + m_nAmmoInClip = 0; + Reload(); + m_nTimer = 0; +} + +void +CWeapon::Reload(void) +{ + if (m_nAmmoTotal == 0) + return; + + CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); + + if (m_nAmmoTotal >= info->m_nAmountofAmmunition) + m_nAmmoInClip = info->m_nAmountofAmmunition; + else + m_nAmmoInClip = m_nAmmoTotal; +} + +STARTPATCHES + InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP); + InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index aebcb2c6..7327e1f9 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -45,11 +45,17 @@ class CWeapon public: eWeaponType m_eWeaponType; eWeaponState m_eWeaponState; - int32 m_nAmmoInClip; - int32 m_nAmmoTotal; + uint32 m_nAmmoInClip; + uint32 m_nAmmoTotal; int32 m_nTimer; bool m_bAddRotOffset; + CWeapon() { + m_bAddRotOffset = false; + } + + void Initialise(eWeaponType type, int ammo); + void Reload(void); bool Fire(CEntity*, CVector*); void AddGunshell(CEntity*, CVector const&, CVector2D const&, float); };