From 8fd63e5ca6288e0f16c63fa9f378682b31dbaf88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 25 Jul 2019 18:06:24 +0300 Subject: Ped & fixes, including peds dive into danger fix --- src/control/Phones.cpp | 6 +- src/core/Camera.cpp | 11 + src/core/Camera.h | 2 + src/math/Vector2D.h | 1 + src/peds/Ped.cpp | 871 ++++++++++++++++++++++++++++++++++++++++++------- src/peds/Ped.h | 78 ++++- src/peds/PedIK.cpp | 3 +- src/peds/PedIK.h | 2 +- src/weapons/Weapon.cpp | 37 +++ src/weapons/Weapon.h | 2 +- 10 files changed, 876 insertions(+), 137 deletions(-) diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 376e2757..499fa253 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -210,7 +210,7 @@ PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) CPed *ped = (CPed*)arg; if (assoc->blendAmount > 0.5f) - ped->m_ped_flagC10 = true; + ped->bUpdateAnimHeading = true; if (ped->m_nPedState == PED_MAKE_CALL) ped->m_nPedState = PED_IDLE; @@ -244,10 +244,10 @@ PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) CPed *ped = CPhoneInfo::pedWhoPickingUpPhone; ped->m_nMoveState = PEDMOVE_STILL; - CAnimManager::BlendAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f); + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f); if (assoc->blendAmount > 0.5f && ped) - CAnimManager::BlendAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f); + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f); CPhoneInfo::pedWhoPickingUpPhone = nil; } diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index a66d6ac9..b5ba76db 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -1304,6 +1304,17 @@ CCam::GetWeaponFirstPersonOn() return false; } +float +CCamera::Find3rdPersonQuickAimPitch(void) +{ + float clampedFrontZ = clamp(Cams[ActiveCam].Front.z, -1.0f, 1.0f); + + // float rot = atan2(clampedFrontZ, sqrt(1.0f - sq(clampedFrontZ))); + float rot = Asin(clampedFrontZ); + + return -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot); +} + STARTPATCHES InjectHook(0x42C760, (bool (CCamera::*)(const CVector ¢er, float radius, const CMatrix *mat))&CCamera::IsSphereVisible, PATCH_JUMP); InjectHook(0x46FD00, &CCamera::SetFadeColour, PATCH_JUMP); diff --git a/src/core/Camera.h b/src/core/Camera.h index 1a2aae79..3ce0d9a6 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -469,6 +469,8 @@ int m_iModeObbeCamIsInForCar; void Restore(void); void SetWidescreenOff(void); + float Find3rdPersonQuickAimPitch(void); + void dtor(void) { this->CCamera::~CCamera(); } }; static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error"); diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h index e6b04c14..caba9146 100644 --- a/src/math/Vector2D.h +++ b/src/math/Vector2D.h @@ -7,6 +7,7 @@ public: CVector2D(void) {} CVector2D(float x, float y) : x(x), y(y) {} CVector2D(const CVector &v) : x(v.x), y(v.y) {} + float Heading(void) const { return Atan2(-x, y); } float Magnitude(void) const { return Sqrt(x*x + y*y); } float MagnitudeSqr(void) const { return x*x + y*y; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 0c4e33d6..addbf782 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -29,6 +29,8 @@ #include "Darkel.h" #include "PathFind.h" #include "ModelIndices.h" +#include "FileMgr.h" +#include "TempColModels.h" WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); } WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); } @@ -47,11 +49,16 @@ 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::SetWaitState(eWaitState, void*) { EAXJMP(0x4D58D0); } +WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); } +WRAPPER void CPed::PlayHitSound(CPed*) { EAXJMP(0x4E8E20); } bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; bool &CPed::bPedCheat3 = *(bool*)0x95CD59; CColPoint &CPed::ms_tempColPoint = *(CColPoint*)0x62DB14; +uint16 &CPed::unknownFightThing = *(uint16*)0x95CC58; +FightMove (&CPed::ms_fightMoves)[24] = * (FightMove(*)[24]) * (uintptr*)0x5F9844; uint16 &CPed::distanceMultToCountPedNear = *(uint16*)0x5F8C98; @@ -338,7 +345,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_nPedState = PED_IDLE; m_nLastPedState = PED_NONE; m_nMoveState = PEDMOVE_STILL; - m_nStoredActionState = 0; + m_nStoredMoveState = PEDMOVE_NONE; m_pFire = nil; m_pPointGunAt = nil; m_pLookTarget = nil; @@ -383,7 +390,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bRespondsToThreats = true; bRenderPedInCar = true; bChangedSeat = false; - m_ped_flagC10 = false; + bUpdateAnimHeading = false; bBodyPartJustCameOff = false; m_ped_flagC40 = false; m_ped_flagC80 = false; @@ -397,12 +404,12 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagD40 = false; m_bScriptObjectiveCompleted = false; - m_ped_flagE1 = false; + bKindaStayInSamePlace = false; m_ped_flagE2 = false; bNotAllowedToDuck = false; bCrouchWhenShooting = false; bIsDucking = false; - m_ped_flagE20 = false; + bGetUpAnimStarted = false; bDoBloodyFootprints = false; m_ped_flagE80 = false; @@ -427,17 +434,17 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagH1 = false; m_ped_flagH2 = false; m_ped_flagH4 = false; - m_ped_flagH8 = false; + bClearObjective = 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; + bNoCriticalHits = false; m_ped_flagI4 = false; bHasAlreadyBeenRecorded = false; - m_ped_flagI10 = false; + bIsFell = false; #ifdef KANGAROO_CHEAT m_ped_flagI80 = false; #endif @@ -475,7 +482,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) weapon.m_nTimer = 0; } - m_lastHitState = 0; + m_lastFightMove = FIGHTMOVE_NULL; GiveWeapon(WEAPONTYPE_UNARMED, 0); m_wepAccuracy = 60; m_lastWepDam = -1; @@ -657,7 +664,7 @@ CPed::AddWeaponModel(int id) atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); RwFrameDestroy(RpAtomicGetFrame(atm)); RpAtomicSetFrame(atm, GetNodeFrame(PED_HANDR)); - RpClumpAddAtomic((RpClump*)m_rwObject, atm); + RpClumpAddAtomic(GetClump(), atm); m_wepModelID = id; } } @@ -954,10 +961,10 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) case ANIM_WEAPON_START_THROW: if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer()) { attackAssoc->blendDelta = -1000.0f; - newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROWU); + newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU); } else { attackAssoc->blendDelta = -1000.0f; - newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROW); + newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW); } newAnim->SetFinishCallback(FinishedAttackCB, ped); @@ -1006,7 +1013,7 @@ CPed::Attack(void) ourWeaponType = GetWeapon()->m_eWeaponType; ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType); ourWeaponFire = ourWeapon->m_eWeaponFire; - weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ourWeapon->m_AnimToPlay); + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay); lastReloadWasInFuture = m_ped_flagA4; reloadAnimAssoc = nil; reloadAnim = NUM_ANIMS; @@ -1019,7 +1026,7 @@ CPed::Attack(void) reloadAnim = ANIM_AK_RELOAD; if (reloadAnim != NUM_ANIMS) - reloadAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, reloadAnim); + reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim); if (bIsDucking) return; @@ -1036,12 +1043,12 @@ CPed::Attack(void) lastReloadWasInFuture = true; if (!weaponAnimAssoc) { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ourWeapon->m_Anim2ToPlay); + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay); delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire; // Long throw granade, molotov if (!weaponAnimAssoc && ourWeapon->m_bThrow) { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_WEAPON_THROWU); + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU); delayBetweenAnimAndFire = 0.2f; } @@ -1049,14 +1056,14 @@ CPed::Attack(void) if (lastReloadWasInFuture) { if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->field_1380) { if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(((CPlayerPed*)this), nil) < PED_ON_THE_FLOOR) { - weaponAnimAssoc = CAnimManager::BlendAnimation((RpClump*)m_rwObject, ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); } else { - weaponAnimAssoc = CAnimManager::BlendAnimation((RpClump*)m_rwObject, ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); } weaponAnimAssoc->SetFinishCallback(CPed::FinishedAttackCB, this); - weaponAnimAssoc->flags |= ASSOC_RUNNING; + weaponAnimAssoc->SetRun(); if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength) weaponAnimAssoc->SetCurrentTime(0.0f); @@ -1117,7 +1124,7 @@ CPed::Attack(void) if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) { // If reloading just began, start the animation if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS && !reloadAnimAssoc) { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, reloadAnim, 8.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f); ClearLookFlag(); ClearAimFlag(); m_ped_flagA4 = false; @@ -1184,13 +1191,13 @@ CPed::Attack(void) if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) { weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart); } else { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); } } else { if (weaponAnim == ourWeapon->m_Anim2ToPlay) weaponAnimAssoc->SetCurrentTime(0.1f); else - CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f); } } else { ClearAimFlag(); @@ -1276,9 +1283,9 @@ CPed::Duck(void) void CPed::ClearDuck(void) { - CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_DUCK_DOWN); + CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_DUCK_LOW); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); if (!animAssoc) { bIsDucking = false; @@ -1292,9 +1299,9 @@ CPed::ClearDuck(void) if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN) return; - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RBLOCK_CSHOOT); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); if (!animAssoc || animAssoc->blendDelta < 0.0f) { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); } } @@ -1310,9 +1317,9 @@ CPed::ClearPointGunAt(void) if (m_nPedState == PED_AIM_GUN) { RestorePreviousState(); weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weaponInfo->m_AnimToPlay); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay); if (!animAssoc || animAssoc->blendDelta < 0.0f) { - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weaponInfo->m_Anim2ToPlay); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay); } if (animAssoc) { animAssoc->flags |= ASSOC_DELETEFADEDOUT; @@ -1330,14 +1337,14 @@ CPed::BeingDraggedFromCar(void) PedLineUpPhase lineUpType; if (!m_pVehicleAnim) { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f); - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SIT); + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT); if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_LSIT); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT); if (!animAssoc) { - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SITP); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP); if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_CAR_SITPLO); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO); } } if (animAssoc) @@ -1361,7 +1368,7 @@ CPed::BeingDraggedFromCar(void) if (!dontRunAnim) - m_pVehicleAnim = CAnimManager::AddAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, enterAnim); + m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim); m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this); lineUpType = LINE_UP_TO_CAR_START; @@ -1380,9 +1387,9 @@ CPed::RestartNonPartialAnims(void) { CAnimBlendAssociation *assoc; - for (assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { if (!assoc->IsPartial()) - assoc->flags |= ASSOC_RUNNING; + assoc->SetRun(); } } @@ -1394,7 +1401,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) CPed *ped = (CPed*)arg; eWeaponType weaponType = ped->GetWeapon()->m_eWeaponType; - quickJackedAssoc = RpAnimBlendClumpGetAssociation((RpClump*) ped->m_rwObject, ANIM_CAR_QJACKED); + quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED); if (ped->m_nPedState != PED_ARRESTED) { ped->m_nLastPedState = PED_NONE; if (dragAssoc) @@ -1432,7 +1439,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) } else { dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); if (ped->CanSetPedState()) - CAnimManager::BlendAnimation((RpClump*) ped->m_rwObject, ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); } // Only uzi can be used on cars, so previous weapon was stored @@ -1444,7 +1451,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) } else { ped->AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId); } - ped->m_nStoredActionState = 0; + ped->m_nStoredMoveState = PEDMOVE_NONE; ped->m_ped_flagI4 = false; } @@ -1565,19 +1572,19 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) return; if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) { - if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SIT)) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) { SetPedPositionInCar(); return; } - if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_LSIT)) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) { SetPedPositionInCar(); return; } - if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SITP)) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) { SetPedPositionInCar(); return; } - if (RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_CAR_SITPLO)) { + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) { SetPedPositionInCar(); return; } @@ -1597,7 +1604,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (vehIsUpsideDown) { m_fRotationDest = -PI + veh->GetForward().Heading(); } else if (veh->bIsBus) { - m_fRotationDest = 0.5 * PI + veh->GetForward().Heading(); + m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); } else { m_fRotationDest = veh->GetForward().Heading(); } @@ -1605,7 +1612,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (vehIsUpsideDown) { m_fRotationDest = veh->GetForward().Heading(); } else if (veh->bIsBus) { - m_fRotationDest = -0.5 * PI + veh->GetForward().Heading(); + m_fRotationDest = -0.5f * PI + veh->GetForward().Heading(); } else { m_fRotationDest = veh->GetForward().Heading(); } @@ -1808,7 +1815,7 @@ particleProduceFootSplash(CPed *ped, CVector *pos, float size, int times) adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); CVector direction = ped->GetForward() * -0.05f; - CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumberInRange(0, 1), 200); + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200); } } @@ -1827,7 +1834,7 @@ CPed::PlayFootSteps(void) if (!bIsStanding) return; - CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject); + CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); CAnimBlendAssociation *walkRunAssoc = nil; float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f; @@ -2041,13 +2048,13 @@ void CPed::SetModelIndex(uint32 mi) { CEntity::SetModelIndex(mi); - RpAnimBlendClumpInit((RpClump*) m_rwObject); - RpAnimBlendClumpFillFrameArray((RpClump*) m_rwObject, m_pFrames); + RpAnimBlendClumpInit(GetClump()); + RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames); CPedModelInfo *modelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex); SetPedStats((ePedStats) modelInfo->m_pedStatType); m_headingRate = m_pedStats->m_headingChangeRate; m_animGroup = (AssocGroupId) modelInfo->m_animGroup; - CAnimManager::AddAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE); + CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE); // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D. (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta; @@ -2120,9 +2127,9 @@ CPed::WorkOutHeadingForMovingFirstPerson(float offset) angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown); } else { if (leftRight < 0.0f) - angle = 0.5 * PI; + angle = 0.5f * PI; else if (leftRight > 0.0f) - angle = -0.5 * PI; + angle = -0.5f * PI; } return CGeneral::LimitRadianAngle(offset + angle); @@ -2175,9 +2182,9 @@ CPed::CalculateNewVelocity(void) float pedSpeed = m_moved.Magnitude(); float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur); - if (localWalkAngle < -0.5 * PI) { + if (localWalkAngle < -0.5f * PI) { localWalkAngle += PI; - } else if (localWalkAngle > 0.5 * PI) { + } else if (localWalkAngle > 0.5f * PI) { localWalkAngle -= PI; } @@ -2187,8 +2194,8 @@ CPed::CalculateNewVelocity(void) m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed; } - CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_STANCE); - CAnimBlendAssociation* fightAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_FIGHT_IDLE); + CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); + CAnimBlendAssociation* fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) { LimbOrientation newUpperLegs; @@ -2637,7 +2644,7 @@ CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType) void CPed::ClearChat(void) { - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); if (animAssoc) { animAssoc->blendDelta = -8.0f; animAssoc->flags |= ASSOC_DELETEFADEDOUT; @@ -2698,8 +2705,8 @@ CPed::QuitEnteringCar(void) RestartNonPartialAnims(); - if (!RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_STANCE)) - CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f); + if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE)) + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); if (veh) { if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK) @@ -2762,7 +2769,7 @@ CPed::ReactToAttack(CEntity *attacker) field_4E8 = CTimer::GetTimeInMilliseconds(); return; } - } else if (bCrouchWhenShooting || m_ped_flagE1) { + } else if (bCrouchWhenShooting || bKindaStayInSamePlace) { SetDuck(CGeneral::GetRandomNumberInRange(1000,3000)); return; } @@ -2852,7 +2859,7 @@ CPed::Chat(void) } if (bIsTalking) { if (CGeneral::GetRandomNumber() < 512) { - CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT); + CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); if (chatAssoc) { chatAssoc->blendDelta = -4.0f; chatAssoc->flags |= ASSOC_FADEOUTWHENDONE; @@ -2861,13 +2868,13 @@ CPed::Chat(void) } else Say(SOUND_PED_CHAT); - } else if (!RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject, ASSOC_FLAG100)) { + } else if (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG100)) { if (CGeneral::GetRandomNumber() < 20) { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); } if (!bIsTalking) { - CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f); + CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f); float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f); chatAssoc->SetCurrentTime(chatTime); @@ -3146,12 +3153,12 @@ CPed::ClearAttackByRemovingAnim(void) return; CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weapon->m_AnimToPlay); + CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay); if (!weaponAssoc) { - weaponAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, weapon->m_Anim2ToPlay); + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay); if (!weaponAssoc && weapon->m_bThrow) - weaponAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_WEAPON_THROWU); + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU); if (!weaponAssoc) { ClearAttack(); @@ -3169,7 +3176,7 @@ CPed::StopNonPartialAnims(void) { CAnimBlendAssociation* assoc; - for (assoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { + for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { if (!assoc->IsPartial()) assoc->flags &= ~ASSOC_RUNNING; } @@ -3187,8 +3194,8 @@ CPed::SetStoredState(void) m_nMoveState = PEDMOVE_WALK; } m_nLastPedState = m_nPedState; - if (m_nMoveState >= m_nPrevActionState) - m_nPrevActionState = m_nMoveState; + if (m_nMoveState >= m_nPrevMoveState) + m_nPrevMoveState = m_nMoveState; } void @@ -3224,7 +3231,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) if (animId == NUM_ANIMS) { bIsPedDieAnimPlaying = false; } else { - CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, animId, delta); + CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta); if (speed > 0.0f) dieAssoc->speed = speed; @@ -3282,7 +3289,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi bool detectDieAnim = true; if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) { if (!IsPedHeadAbovePos(-0.3f)) { - if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, ASSOC_FLAG800)) + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800)) dieAnim = ANIM_FLOOR_HIT_F; else dieAnim = ANIM_FLOOR_HIT; @@ -3304,7 +3311,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi if (IsPedHeadAbovePos(-0.3f)) { dieAnim = NUM_ANIMS; } else { - if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, ASSOC_FLAG800)) + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800)) dieAnim = ANIM_FLOOR_HIT_F; else dieAnim = ANIM_FLOOR_HIT; @@ -3338,7 +3345,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi if (IsPedHeadAbovePos(-0.3f)) { dieAnim = NUM_ANIMS; } else { - if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, 0x800u)) + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), 0x800u)) dieAnim = ANIM_FLOOR_HIT_F; else dieAnim = ANIM_FLOOR_HIT; @@ -3374,7 +3381,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi return false; bool dontRemoveLimb; - if (IsPlayer() || m_ped_flagI2) + if (IsPlayer() || bNoCriticalHits) dontRemoveLimb = true; else { switch (method) @@ -3386,10 +3393,10 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi dontRemoveLimb = false; break; case WEAPONTYPE_SHOTGUN: - dontRemoveLimb = CGeneral::GetRandomNumberInRange(0,7); + dontRemoveLimb = CGeneral::GetRandomNumber() & 7; break; default: - dontRemoveLimb = CGeneral::GetRandomNumberInRange(0,15); + dontRemoveLimb = CGeneral::GetRandomNumber() & 15; break; } } @@ -3513,7 +3520,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi if (bCollisionProof) return false; - random = CGeneral::GetRandomNumberInRange(0, 3); + random = CGeneral::GetRandomNumber() & 3; switch (random) { case 0: if ((pedPiece != PEDPIECE_LEFTARM || random <= 1) @@ -3668,17 +3675,17 @@ CPed::ClearFall(void) void CPed::SetGetUp(void) { - if (m_nPedState == PED_GETUP && m_ped_flagE20) + if (m_nPedState == PED_GETUP && bGetUpAnimStarted) return; if (!CanSetPedState()) return; if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) { - if (m_ped_flagC10) { + if (bUpdateAnimHeading) { m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - m_fRotationCur -= 0.5*PI; - m_ped_flagC10 = false; + m_fRotationCur -= 0.5f*PI; + bUpdateAnimHeading = false; } if (m_nPedState != PED_GETUP) { SetStoredState(); @@ -3694,7 +3701,7 @@ CPed::SetGetUp(void) collidingVeh->GetMatrix(), *CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(), &ms_tempColPoint, nil, nil) > 0)) { - m_ped_flagE20 = false; + bGetUpAnimStarted = false; if (IsPlayer()) InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); else { @@ -3705,23 +3712,23 @@ CPed::SetGetUp(void) } return; } - m_ped_flagE20 = true; + bGetUpAnimStarted = true; m_pCollidingEntity = nil; m_ped_flagH1 = false; - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_SPRINT); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT); if (animAssoc) { - if (RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RUN)) { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_RUN, 8.0f); + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) { + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f); } else { - CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 8.0f); + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f); } animAssoc->flags |= ASSOC_DELETEFADEDOUT; } - if (RpAnimBlendClumpGetFirstAssociation((RpClump*) m_rwObject, ASSOC_FLAG800)) - animAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f); + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800)) + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f); else - animAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); animAssoc->SetFinishCallback(PedGetupCB,this); } else { @@ -3733,13 +3740,13 @@ CPed::SetGetUp(void) void CPed::ClearInvestigateEvent(void) { - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_ROAD_CROSS); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS); if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_XPRESS_SCRATCH); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH); if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_HBHB); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB); if (!animAssoc) - animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT); if (animAssoc) { animAssoc->blendDelta = -8.0f; animAssoc->flags |= ASSOC_DELETEFADEDOUT; @@ -3770,7 +3777,7 @@ CPed::ClearLeader(void) SetWanderPath(CGeneral::GetRandomNumberInRange(0,8)); } } else if (m_objective != OBJECTIVE_NONE) { - m_ped_flagH8 = true; + bClearObjective = true; } } @@ -3799,7 +3806,7 @@ CPed::ClearObjective(void) SetMoveState(PEDMOVE_STILL); } } else { - m_ped_flagH8 = true; + bClearObjective = true; } } @@ -3822,7 +3829,7 @@ CPed::SetWanderPath(int8 pathStateDest) uint8 nextPathState; if (IsPedInControl()) { - if (m_ped_flagE1) { + if (bKindaStayInSamePlace) { SetIdle(); return false; } else { @@ -3918,7 +3925,7 @@ CPed::RestorePreviousState(void) if(!CanSetPedState() || m_nPedState == PED_FALL) return; - if (m_nPedState == PED_GETUP && !m_ped_flagE20) + if (m_nPedState == PED_GETUP && !bGetUpAnimStarted) return; if (bInVehicle && m_pMyVehicle) { @@ -3927,7 +3934,7 @@ CPed::RestorePreviousState(void) } else { if (m_nLastPedState == PED_NONE) { if (!IsPlayer() && CharCreatedBy != MISSION_CHAR && m_objective == OBJECTIVE_NONE) { - if (SetWanderPath(CGeneral::GetRandomNumberInRange(0, 7)) != 0) + if (SetWanderPath(CGeneral::GetRandomNumber() & 7) != 0) return; } SetIdle(); @@ -3950,11 +3957,11 @@ CPed::RestorePreviousState(void) } } } - SetWanderPath(CGeneral::GetRandomNumberInRange(0, 7)); + SetWanderPath(CGeneral::GetRandomNumber() & 7); break; default: m_nPedState = m_nLastPedState; - SetMoveState((eMoveState) m_nPrevActionState); + SetMoveState((eMoveState) m_nPrevMoveState); break; } m_nLastPedState = PED_NONE; @@ -4010,15 +4017,15 @@ CPed::SetPointGunAt(CEntity *to) CAnimBlendAssociation *aimAssoc; if (bCrouchWhenShooting) - aimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, curWeapon->m_Anim2ToPlay); + aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay); else - aimAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, curWeapon->m_AnimToPlay); + aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay); if (!aimAssoc || aimAssoc->blendDelta < 0.0f) { if (bCrouchWhenShooting) - aimAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f); + aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f); else - aimAssoc = CAnimManager::AddAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, curWeapon->m_AnimToPlay); + aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay); aimAssoc->blendAmount = 0.0f; aimAssoc->blendDelta = 8.0f; @@ -4067,25 +4074,29 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) } if (neededTurn <= DEGTORAD(90.0f) || veh->m_modelIndex == MI_RCBANDIT || vehPressedHorn || animType != 0) { SetLookFlag(veh, 1); - if (CGeneral::GetRandomNumberInRange(0,1) && veh->m_modelIndex != MI_RCBANDIT && animType == 0) { + if ((CGeneral::GetRandomNumber() & 1) && veh->m_modelIndex != MI_RCBANDIT && animType == 0) { stepAnim = ANIM_IDLE_TAXI; } else { - // I didn't get these things too much. float vehDirection = CGeneral::GetRadianAngleBetweenPoints( veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, 0.0f, 0.0f); - float inversedAngleToFace = angleToFace + PI; - if (inversedAngleToFace > PI) - inversedAngleToFace -= 2*PI; + // Let's turn our back to the "reason" + angleToFace += PI; - neededTurn = inversedAngleToFace - vehDirection; - neededTurn = CGeneral::LimitRadianAngle(neededTurn); - if (neededTurn <= 0.0) - angleToFace = 0.5*PI + vehDirection; + if (angleToFace > PI) + angleToFace -= 2*PI; + + // We don't want to run towards car's direction + float dangerZone = angleToFace - vehDirection; + dangerZone = CGeneral::LimitRadianAngle(dangerZone); + + // So, add or subtract 90deg (jump to left/right) according to that + if (dangerZone <= 0.0f) + angleToFace = 0.5f*PI + vehDirection; else - angleToFace = vehDirection - 0.5*PI; + angleToFace = vehDirection - 0.5f*PI; if (animType == 2) stepAnim = ANIM_HANDSCOWER; @@ -4094,8 +4105,8 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) else stepAnim = NUM_ANIMS; } - if (!RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, stepAnim)) { - CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, stepAnim, 8.0f); + if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) { + CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f); stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT; stepAssoc->SetFinishCallback(PedEvadeCB, this); @@ -4110,6 +4121,623 @@ CPed::SetEvasiveStep(CEntity *reason, uint8 animType) } } +void +CPed::SetEvasiveDive(CPhysical* reason, uint8 onlyRandomJump) +{ + if (!IsPedInControl() || !bRespondsToThreats) + return; + + CAnimBlendAssociation* animAssoc; + float angleToFace, neededTurn; + bool handsUp = false; + + angleToFace = m_fRotationCur; + CVehicle *veh = (CVehicle*) reason; + if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer && !IsPlayer()) { + onlyRandomJump = true; + } + + if (onlyRandomJump) { + if (reason) { + // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly. + // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots. + + float vehDirection = CGeneral::GetRadianAngleBetweenPoints( + veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, + 0.0f, 0.0f); + angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection; + angleToFace = CGeneral::LimitRadianAngle(angleToFace); + } + } else { + if (IsPlayer()) { + ((CPlayerPed*)this)->m_bShouldEvade = 5; + ((CPlayerPed*)this)->m_pEvadingFrom = reason; + reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom); + return; + } + + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + reason->GetPosition().x, reason->GetPosition().y, + GetPosition().x, GetPosition().y); + angleToFace = CGeneral::LimitRadianAngle(angleToFace); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + + // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted +#ifdef FIX_BUGS + float vehDirection = CGeneral::GetRadianAngleBetweenPoints( + veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y, + 0.0f, 0.0f); + + // Let's turn our back to the "reason" + angleToFace += PI; + + if (angleToFace > PI) + angleToFace -= 2 * PI; + + // We don't want to dive towards car's direction + float dangerZone = angleToFace - vehDirection; + dangerZone = CGeneral::LimitRadianAngle(dangerZone); + + // So, add or subtract 90deg (jump to left/right) according to that + if (dangerZone > 0.0f) + angleToFace = 0.5f * PI + vehDirection; + else + angleToFace = vehDirection - 0.5f * PI; +#endif + + neededTurn = Abs(angleToFace - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = 2 * PI - neededTurn; + + if (neededTurn <= 0.5f*PI) { + if (CGeneral::GetRandomNumber() & 1) + handsUp = true; + } else { + if (CGeneral::GetRandomNumber() & 7) + return; + } + Say(SOUND_PED_EVADE); + } + + if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) { + m_fRotationCur = angleToFace; + ClearLookFlag(); + ClearAimFlag(); + SetLookFlag(reason, 1); + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP); + if (animAssoc) + return; + + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f); + animAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + animAssoc->SetFinishCallback(PedEvadeCB, this); + SetStoredState(); + m_nPedState = PED_STEP_AWAY; + } else { + m_fRotationCur = angleToFace; + ClearLookFlag(); + ClearAimFlag(); + SetStoredState(); + m_nPedState = PED_DIVE_AWAY; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f); + animAssoc->SetFinishCallback(PedEvadeCB, this); + } + + if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) { + if (veh->pDriver && veh->pDriver->IsPlayer()) { + CWanted *wanted = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted; + wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (int)this, false); + wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (int)this, false); + } + } +} + +void +CPed::SetAttack(CEntity* victim) +{ + CPed *victimPed = nil; + if (victim && victim->IsPed()) + victimPed = (CPed*)victim; + + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED); + if (animAssoc) { + animAssoc->blendDelta = -1000.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + + if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE) + return; + + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) { + m_ped_flagA4 = false; + return; + } + + if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) { + if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->field_1380) + m_ped_flagA4 = false; + else + m_ped_flagA4 = true; + + return; + } + + CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) { + if (GetWeapon()->HitsGround(this, nil, victim)) + return; + } + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { + if (IsPlayer() || + (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) { + + if (m_nPedState != PED_ATTACK) { + m_nPedState = PED_ATTACK; + m_ped_flagA4 = false; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f); + animAssoc->SetRun(); + if (animAssoc->currentTime != animAssoc->hierarchy->totalLength) + animAssoc->SetCurrentTime(0.0f); + + animAssoc->SetFinishCallback(FinishedAttackCB, this); + } + } else { + StartFightAttack(CGeneral::GetRandomNumber() & 255); + } + return; + } + + m_pSeekTarget = victim; + if (m_pSeekTarget) + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + + if (curWeapon->m_bCanAim) { + CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition(); + CEntity *foundEntity = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false); + if (foundEntity) + return; + + m_pLookTarget = victim; + if (victim) { + m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); + } + if (m_pLookTarget) { + SetAimFlag(m_pLookTarget); + } else { + SetAimFlag(m_fRotationCur); + + if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam()) + ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch(); + } + } + if (m_nPedState == PED_ATTACK) { + m_ped_flagA4 = true; + return; + } + + if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) { + if(IsPlayer()) + CPad::GetPad(0)->ResetAverageWeapon(); + + if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16FIRSTPERSON_34 + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_FIRSTPERSONPEDONPC_41 + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER + && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUN_AROUND + && CheckForPointBlankPeds(victimPed) != 0) { + ClearAimFlag(); + + // This condition is pointless, we already check it in above + // if (CheckForPointBlankPeds(victimPed) == 1 || !victimPed) + StartFightAttack(200); + } else { + if (!curWeapon->m_bCanAim) + m_pSeekTarget = nil; + + if (m_nPedState != PED_AIM_GUN) + SetStoredState(); + + m_nPedState = PED_ATTACK; + SetMoveState(PEDMOVE_NONE); + if (bCrouchWhenShooting) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f); + } else { + float animDelta = 8.0f; + if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE) + animDelta = 1000.0f; + + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT + || CheckForPedsOnGroundToAttack((CPlayerPed*)this, nil) < PED_ON_THE_FLOOR) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta); + } else { + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta); + } + } + + animAssoc->SetRun(); + if (animAssoc->currentTime != animAssoc->hierarchy->totalLength) + animAssoc->SetCurrentTime(0.0f); + + animAssoc->SetFinishCallback(FinishedAttackCB, this); + } + return; + } + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP) + SetWaitState(WAITSTATE_SURPRISE, nil); + + SetLookFlag(victim, 0); + SetLookTimer(100); +} + +void +CPed::StartFightAttack(uint8 buttonPressure) +{ + if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds()) + return; + + if (m_nPedState == PED_FIGHT) { + m_fightButtonPressure = buttonPressure; + return; + } + + if (m_nPedState != PED_AIM_GUN) + SetStoredState(); + + if (m_nWaitState != WAITSTATE_FALSE) { + m_nWaitState = WAITSTATE_FALSE; + RestoreHeadingRate(); + } + + m_nPedState = PED_FIGHT; + m_fightButtonPressure = 0; + RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); + + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -1000.0f; + } + + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); + if (!animAssoc) + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); + + if (animAssoc) { + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->blendDelta = -1000.0f; + RestoreHeadingRate(); + } + + SetMoveState(PEDMOVE_NONE); + m_nStoredMoveState = PEDMOVE_NONE; + + CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; + + CPed *pedOnGround = nil; + if (IsPlayer() && CheckForPedsOnGroundToAttack((CPlayerPed*)this, &pedOnGround) > PED_BELOW_PLAYER) { + m_lastFightMove = FIGHTMOVE_GROUNDKICK; + } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) { + m_lastFightMove = FIGHTMOVE_ROUNDHOUSE; + } else { + m_lastFightMove = FIGHTMOVE_STDPUNCH; + } + + if (pedOnGround && IsPlayer()) { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + pedOnGround->GetPosition().x, pedOnGround->GetPosition().y, + GetPosition().x, GetPosition().y); + + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + m_fRotationCur = m_fRotationDest; + m_lookTimer = 0; + SetLookFlag(pedOnGround, 1); + SetLookTimer(1500); + } + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ms_fightMoves[m_lastFightMove].animId, 4.0f); + animAssoc->SetFinishCallback(FinishFightMoveCB, this); + m_fightUnk2 = 0; + m_fightUnk1 = 0; + m_ped_flagA4 = true; + + if (IsPlayer()) + unknownFightThing = 0; +} + +void +CPed::LoadFightData(void) +{ + float startFireTime, endFireTime, comboFollowOnTime, strikeRadius; + int damage, flags; + char line[256], moveName[32], animName[32], hitLevel; + int moveId = 0; + + CAnimBlendAssociation* animAssoc; + + int bp, buflen; + int lp, linelen; + + buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r"); + + for (bp = 0; bp < buflen; ) { + // read file line by line + for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) { + line[linelen++] = work_buff[bp]; + } + bp++; + line[linelen] = '\0'; + + // skip white space + for (lp = 0; line[lp] <= ' '; lp++); + + if (lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines + line[lp] == '#') + continue; + + sscanf( + &line[lp], + "%s %f %f %f %f %c %s %d %d", + &moveName, + &startFireTime, + &endFireTime, + &comboFollowOnTime, + &strikeRadius, + &hitLevel, + &animName, + &damage, + &flags); + + if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0) + return; + + ms_fightMoves[moveId].startFireTime = startFireTime / 30.0f; + ms_fightMoves[moveId].endFireTime = endFireTime / 30.0f; + ms_fightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f; + ms_fightMoves[moveId].strikeRadius = strikeRadius; + ms_fightMoves[moveId].damage = damage; + ms_fightMoves[moveId].flags = flags; + + switch (hitLevel) { + case 'G': + ms_fightMoves[moveId].hitLevel = 1; + break; + case 'H': + ms_fightMoves[moveId].hitLevel = 4; + break; + case 'L': + ms_fightMoves[moveId].hitLevel = 2; + break; + case 'M': + ms_fightMoves[moveId].hitLevel = 3; + break; + case 'N': + ms_fightMoves[moveId].hitLevel = 0; + break; + default: + break; + } + + if (strncmp(animName, "null", 4) != 0) { + animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName); + ms_fightMoves[moveId].animId = (AnimationId)animAssoc->animId; + } else { + ms_fightMoves[moveId].animId = ANIM_WALK; + } + moveId++; + } +} + +// Actually GetLocalDirectionTo(Turn/Look) +int +CPed::GetLocalDirection(CVector2D &posOffset) +{ + float direction; + + for (direction = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); direction < 0.0f; direction += 2 * PI); + + for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4); + + // Should be 0-east, 1-north, 2-west, 3-south. Not sure about order. + return direction; +} + +bool +CPed::FightStrike(CVector &touchedNodePos) +{ + CColModel* ourCol; + CVector attackDistance; + ePedPieceTypes closestPedPiece = PEDPIECE_TORSO; + float maxDistanceToBeBeaten; + CPed *nearPed; + int unk = m_fightUnk2; + bool pedFound = false; + + if (unk == -1) + return false; + + if (unk > 0) + attackDistance = touchedNodePos - m_vecHitLastPos; + + for (int i = 0; i < m_numNearPeds; i++) { + nearPed = m_nearPeds[i]; + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) + maxDistanceToBeBeaten = nearPed->GetBoundRadius() + ms_fightMoves[m_lastFightMove].strikeRadius + 0.1f; + else + maxDistanceToBeBeaten = nearPed->GetBoundRadius() + ms_fightMoves[m_lastFightMove].strikeRadius; + + if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) { + CVector nearPedCentre; + nearPed->GetBoundCentre(nearPedCentre); + CVector potentialAttackDistance = nearPedCentre - touchedNodePos; + + // He can beat us + if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) { + ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); + if (nearPed->m_nPedState == PED_FALL + || nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE + || !nearPed->IsPedHeadAbovePos(-0.3f)) { + ourCol = &CTempColModels::ms_colModelPedGroundHit; + } + for (int j = 0; j < ourCol->numSpheres; j++) { + attackDistance = nearPed->GetPosition() - ourCol->spheres[j].center; + attackDistance -= touchedNodePos; + CColSphere *ourPieces = ourCol->spheres; + float maxDistanceToBeat = ourPieces[j].radius + ms_fightMoves[m_lastFightMove].strikeRadius; + + // We can beat him too + if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) { + pedFound = true; + closestPedPiece = (ePedPieceTypes) ourPieces[j].piece; + break; + } + } + } + } + if (pedFound) + break; + } + + if (pedFound) { + if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP) + return false; + + float oldVictimHealth = nearPed->m_fHealth; + CVector bloodPos = 0.5f * attackDistance + touchedNodePos; + int damageMult = ms_fightMoves[m_lastFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; + + CVector2D diff (GetPosition() - nearPed->GetPosition()); + int direction = nearPed->GetLocalDirection(diff); + if (IsPlayer()) { + if (((CPlayerPed*)this)->m_bAdrenalineActive) + damageMult = 20; + } else { + damageMult *= m_pedStats->m_attackStrength; + } + + // Change direction if we used kick. + if (m_lastFightMove == FIGHTMOVE_KICK) { + if (CGeneral::GetRandomNumber() & 1) { + direction++; + if (direction > 3) + direction -= 4; + } + } + nearPed->ReactToAttack(this); + + // Mostly unused. + int unk2; + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer()) + unk2 = 101; + else + unk2 = damageMult; + + nearPed->StartFightDefend(direction, ms_fightMoves[m_lastFightMove].hitLevel, unk2); + PlayHitSound(nearPed); + m_fightUnk2 = -1; + RpAnimBlendClumpGetAssociation(GetClump(), ms_fightMoves[m_lastFightMove].animId)->speed = 0.6f; + if (nearPed->m_nPedState != PED_DIE && nearPed->m_nPedState != PED_DEAD) { + nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction); + } + + if (CGame::nastyGame + && ms_fightMoves[m_lastFightMove].hitLevel > 3 + && nearPed->m_nPedState == PED_DIE + && nearPed->GetIsOnScreen()) { + + // Just for blood particle. We will restore it below. + attackDistance /= (10.0f * attackDistance.Magnitude()); + for(int i=0; i<4; i++) { + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0); + } + } + if (nearPed->m_nPedState != PED_FALL && nearPed->m_nPedState != PED_DIE && nearPed->m_nPedState != PED_DEAD) { + float curVictimHealth = nearPed->m_fHealth; + if (curVictimHealth > 0.0f + && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer() + || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f + || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer() + || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) { + + nearPed->SetFall(0, (AnimationId)(direction + 25), 0); + if (nearPed->m_nPedState == PED_FALL) + nearPed->bIsStanding = false; + } + } + if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) { + attackDistance = nearPed->GetPosition() - GetPosition(); + attackDistance.Normalise(); + attackDistance.z = 1.0f; + nearPed->bIsStanding = false; + + float moveMult; + if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) { + moveMult = min(damageMult * 0.6f, 4.0f); + } else { + if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) { + moveMult = damageMult; + } else { + moveMult = min(damageMult * 2.0f, 14.0f); + } + } + + nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance); + } + CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000); + } + + if (!m_fightUnk2) + m_fightUnk2 = 1; + + m_vecHitLastPos = *touchedNodePos; + return false; +} + +void +CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) +{ + if (!IsPedInControl() && (!evenIfNotInControl || m_nPedState == PED_DIE || m_nPedState == PED_DEAD)) + return; + + ClearLookFlag(); + ClearAimFlag(); + SetStoredState(); + m_nPedState = PED_FALL; + CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId); + + if (fallAssoc) { + fallAssoc->SetCurrentTime(0.0f); + fallAssoc->blendAmount = 0.0f; + fallAssoc->blendDelta = 8.0f; + fallAssoc->SetRun(); + } else { + fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f); + } + + if (extraTime == -1) { + m_getUpTimer = -1; + } else if (fallAssoc) { + if (IsPlayer()) { + m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength + + CTimer::GetTimeInMilliseconds() + + 500.0f; + } else { + m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength + + CTimer::GetTimeInMilliseconds() + + extraTime + + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000); + } + } else { + m_getUpTimer = extraTime + + CTimer::GetTimeInMilliseconds() + + 1000 + + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000); + } + bIsFell = true; +} + 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); } @@ -4238,4 +4866,11 @@ STARTPATCHES InjectHook(0x4C69E0, (void (CPed::*)(CEntity*)) &CPed::SetAimFlag, PATCH_JUMP); InjectHook(0x4C6960, (void (CPed::*)(float)) &CPed::SetAimFlag, PATCH_JUMP); InjectHook(0x4CFB20, &CPed::SetAmmo, PATCH_JUMP); -ENDPATCHES + InjectHook(0x4D33A0, &CPed::SetEvasiveDive, PATCH_JUMP); + InjectHook(0x4D09B0, &CPed::SetFall, PATCH_JUMP); + InjectHook(0x4E6220, &CPed::SetAttack, PATCH_JUMP); + InjectHook(0x4E7530, &CPed::StartFightAttack, PATCH_JUMP); + InjectHook(0x4E9870, &CPed::LoadFightData, PATCH_JUMP); + InjectHook(0x4E8EC0, &CPed::FightStrike, PATCH_JUMP); + InjectHook(0x4CCE20, &CPed::GetLocalDirection, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 7b8bc2ce..79ef1705 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -13,6 +13,47 @@ struct CPathNode; +struct FightMove +{ + AnimationId animId; + float startFireTime; + float endFireTime; + float comboFollowOnTime; + float strikeRadius; + uint8 hitLevel; + uint8 damage; + uint8 flags; +}; +static_assert(sizeof(FightMove) == 0x18, "FightMove: error"); + +enum PedFightMoves +{ + FIGHTMOVE_NULL, + FIGHTMOVE_STDPUNCH, + FIGHTMOVE_IDLE, + FIGHTMOVE_SHUFFLE_F, + FIGHTMOVE_KNEE, + FIGHTMOVE_HEADBUTT, + FIGHTMOVE_PUNCHJAB, + FIGHTMOVE_PUNCHHOOK, + FIGHTMOVE_KICK, + FIGHTMOVE_LONGKICK, + FIGHTMOVE_ROUNDHOUSE, + FIGHTMOVE_BODYBLOW, + FIGHTMOVE_GROUNDKICK, + FIGHTMOVE_HITFRONT, + FIGHTMOVE_HITBACK, + FIGHTMOVE_HITRIGHT, + FIGHTMOVE_HITLEFT, + FIGHTMOVE_HITBODY, + FIGHTMOVE_HITCHEST, + FIGHTMOVE_HITHEAD, + FIGHTMOVE_HITBIGSTEP, + FIGHTMOVE_HITONFLOOR, + FIGHTMOVE_HITBEHIND, + FIGHTMOVE_IDLE2NORM +}; + enum ePedPieceTypes { PEDPIECE_TORSO, @@ -209,7 +250,7 @@ public: uint8 bRespondsToThreats : 1; uint8 bRenderPedInCar : 1; uint8 bChangedSeat : 1; - uint8 m_ped_flagC10 : 1; // related with phone + uint8 bUpdateAnimHeading : 1; uint8 bBodyPartJustCameOff : 1; uint8 m_ped_flagC40 : 1; uint8 m_ped_flagC80 : 1; @@ -223,12 +264,12 @@ public: uint8 m_ped_flagD40 : 1; // reset when objective changes uint8 m_bScriptObjectiveCompleted : 1; - uint8 m_ped_flagE1 : 1; + uint8 bKindaStayInSamePlace : 1; uint8 m_ped_flagE2 : 1; uint8 bNotAllowedToDuck : 1; uint8 bCrouchWhenShooting : 1; uint8 bIsDucking : 1; // set if you don't want ped to attack - uint8 m_ped_flagE20 : 1; // getup complete? + uint8 bGetUpAnimStarted : 1; uint8 bDoBloodyFootprints : 1; uint8 m_ped_flagE80 : 1; @@ -253,17 +294,17 @@ public: uint8 m_ped_flagH1 : 1; uint8 m_ped_flagH2 : 1; uint8 m_ped_flagH4 : 1; - uint8 m_ped_flagH8 : 1; + uint8 bClearObjective : 1; uint8 m_ped_flagH10 : 1; 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; // if set, limbs won't came off + uint8 bNoCriticalHits : 1; // if set, limbs won't came off uint8 m_ped_flagI4 : 1; uint8 bHasAlreadyBeenRecorded : 1; - uint8 m_ped_flagI10 : 1; + uint8 bIsFell : 1; uint8 m_ped_flagI20 : 1; uint8 m_ped_flagI40 : 1; uint8 m_ped_flagI80 : 1; @@ -299,8 +340,8 @@ public: PedState m_nPedState; PedState m_nLastPedState; eMoveState m_nMoveState; - int32 m_nStoredActionState; - int32 m_nPrevActionState; + int32 m_nStoredMoveState; + int32 m_nPrevMoveState; eWaitState m_nWaitState; uint32 m_nWaitTimer; void *m_pPathNodesStates[8]; // seems unused @@ -363,10 +404,11 @@ public: uint8 m_wepAccuracy; CEntity *m_pPointGunAt; CVector m_vecHitLastPos; - uint32 m_lastHitState; - uint8 m_fightFlags1; - uint8 m_fightFlags2; - uint8 pad_4B2[2]; + PedFightMoves m_lastFightMove; + uint8 m_fightButtonPressure; + int8 m_fightUnk2; // TODO + uint8 m_fightUnk1; // TODO + uint8 pad_4B3; CFire* m_pFire; CEntity *m_pLookTarget; float m_fLookDirection; @@ -503,6 +545,16 @@ public: void SetAimFlag(float angle); void SetAmmo(eWeaponType weaponType, uint32 ammo); void SetEvasiveStep(CEntity*, uint8); + void SetEvasiveDive(CPhysical*, uint8); + void SetAttack(CEntity*); + void StartFightAttack(uint8); + void LoadFightData(void); + void SetWaitState(eWaitState, void*); + bool FightStrike(CVector&); + int GetLocalDirection(CVector2D&); + void StartFightDefend(uint8, uint8, uint8); + void PlayHitSound(CPed*); + void SetFall(int, AnimationId, uint8); // Static methods static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); @@ -577,6 +629,8 @@ public: static bool &bPedCheat2; static bool &bPedCheat3; static CColPoint &ms_tempColPoint; + static uint16 &unknownFightThing; // TODO + static FightMove (&ms_fightMoves)[24]; }; void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg); diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index 3d5bcfb5..768e0bf0 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -104,8 +104,7 @@ CPedIK::GetWorldMatrix(RwFrame *source, RwMatrix *destination) return destination; } -// A helper function that adjusts "limb" parameter according to limitations. Doesn't move the limb. -int8 +uint32 CPedIK::MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo) { int result = 1; diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index 5f321280..a8d9c75d 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -47,7 +47,7 @@ public: void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll); void ExtractYawAndPitchLocal(RwMatrixTag*, float*, float*); void ExtractYawAndPitchWorld(RwMatrixTag*, float*, float*); - int8 MoveLimb(LimbOrientation &a1, float a2, float a3, LimbMovementInfo &a4); + uint32 MoveLimb(LimbOrientation &a1, float a2, float a3, LimbMovementInfo &a4); bool RestoreGunPosn(void); }; static_assert(sizeof(CPedIK) == 0x28, "CPedIK: error"); diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 056c584a..f83f2271 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -3,6 +3,8 @@ #include "Weapon.h" #include "Timer.h" #include "WeaponInfo.h" +#include "Ped.h" +#include "World.h" WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); } WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940); } @@ -50,7 +52,42 @@ CWeapon::IsTypeMelee(void) return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT; } +bool +CWeapon::HitsGround(CEntity *holder, CVector *firePos, CEntity *aimingTo) +{ + if (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget) + return false; + + CWeaponInfo *ourType = CWeaponInfo::GetWeaponInfo(m_eWeaponType); + CVector adjustedOffset = ourType->m_vecFireOffset; + adjustedOffset.z += 0.6f; + + CVector point1, point2; + CEntity *foundEnt = nil; + CColPoint foundCol; + + if (firePos) + point1 = *firePos; + else + point1 = holder->GetMatrix() * adjustedOffset; + + CEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget; + point2 = aimEntity->GetPosition(); + point2.z += 0.6f; + + CWorld::ProcessLineOfSight(point1, point2, foundCol, foundEnt, true, false, false, false, false, false, false); + if (foundEnt && foundEnt->IsBuilding()) { + // That was supposed to be Magnitude, according to leftover code in assembly + float diff = (foundCol.point.z - point1.z); + if (diff < 0.0f && diff > -3.0f) + return true; + } + + return false; +} + STARTPATCHES InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP); InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP); + InjectHook(0x564890, &CWeapon::HitsGround, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 71c1f344..4916284f 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -70,7 +70,7 @@ public: void AddGunshell(CEntity*, CVector const&, CVector2D const&, float); bool IsTypeMelee(void); bool IsType2Handed(void); - static void DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end); + bool HitsGround(CEntity* holder, CVector* firePos, CEntity* aimingTo); }; static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); -- cgit v1.2.3