From d75b9b82571834248a2337473307ffece8a73023 Mon Sep 17 00:00:00 2001 From: erorcun Date: Thu, 23 Jan 2020 23:21:50 +0300 Subject: [PATCH] CPlayerPed continues (#294) --- README.md | 1 + src/core/Camera.cpp | 15 ++ src/core/Camera.h | 2 + src/core/PlayerInfo.cpp | 20 +- src/peds/CivilianPed.cpp | 42 +--- src/peds/Ped.cpp | 41 +--- src/peds/Ped.h | 18 ++ src/peds/PlayerPed.cpp | 413 ++++++++++++++++++++++++++++++++++- src/peds/PlayerPed.h | 11 +- src/render/WeaponEffects.cpp | 15 +- src/render/WeaponEffects.h | 13 +- 11 files changed, 503 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index b03c3ce2..cb1b7187 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ CPedPath CPlayerPed CRoadBlocks CRunningScript - being worked on +CShotInfo CStats CSpecialFX CTrafficLights diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 1aee4edb..a8295763 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -1379,6 +1379,21 @@ CCamera::SetWideScreenOff(void) m_bWantsToSwitchWidescreenOff = m_WideScreenOn; } +void +CCamera::SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom) +{ + PlayerWeaponMode.Mode = mode; + PlayerWeaponMode.MaxZoom = maxZoom; + PlayerWeaponMode.MinZoom = minZoom; + PlayerWeaponMode.Duration = 0.0f; +} + +void +CCamera::UpdateAimingCoors(CVector const &coors) +{ + m_cvecAimingTargetCoors = coors; +} + 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 81eaa84f..8f0e62d4 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -494,6 +494,8 @@ int m_iModeObbeCamIsInForCar; void SetCameraDirectlyBehindForFollowPed_CamOnAString(void); void SetZoomValueFollowPedScript(int16); void SetZoomValueCamStringScript(int16); + void SetNewPlayerWeaponMode(int16, int16, int16); + void UpdateAimingCoors(CVector const &); void dtor(void) { this->CCamera::~CCamera(); } }; diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index d9030250..a01c1398 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -212,9 +212,9 @@ CPlayerInfo::IsRestartingAfterArrest() return m_WBState == WBSTATE_BUSTED; } -// lastClosestness is passed to other calls of this function +// lastCloseness is passed to other calls of this function void -CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastClosestness, CVehicle **closestCarOutput) +CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput) { // This dist used for determining the angle to face CVector2D dist(carToTest->GetPosition() - player->GetPosition()); @@ -229,9 +229,9 @@ CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoun // This dist used for evaluating cars' distances, weird... // Accounts inverted needed turn (or needed turn in long way) and car dist. - float closestness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist); - if (closestness > *lastClosestness) { - *lastClosestness = closestness; + float closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist); + if (closeness > *lastCloseness) { + *lastCloseness = closeness; *closestCarOutput = (CVehicle*)carToTest; } } @@ -312,7 +312,7 @@ INITSAVEBUF } void -CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastClosestness, CVehicle** closestCarOutput) +CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput) { for (CPtrNode* node = carList.first; node; node = node->next) { CVehicle *car = (CVehicle*)node->item; @@ -328,7 +328,7 @@ CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, if (Abs(ped->GetPosition().z - carCentre.z) < 2.0f) { float dist = (ped->GetPosition() - carCentre).Magnitude2D(); if (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) { - EvaluateCarPosition(car, ped, dist, lastClosestness, closestCarOutput); + EvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput); } } } @@ -434,7 +434,7 @@ CPlayerInfo::Process(void) // Enter vehicle if (CPad::GetPad(0)->ExitVehicleJustDown()) { bool weAreOnBoat = false; - float lastClosestness = 0.0f; + float lastCloseness = 0.0f; CVehicle *carBelow = nil; CEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface; if (surfaceBelow && surfaceBelow->IsVehicle()) { @@ -472,9 +472,9 @@ CPlayerInfo::Process(void) for (int curX = minXSector; curX <= maxXSector; curX++) { CSector *sector = CWorld::GetSector(curX, curY); FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed, - minX, minY, maxX, maxY, &lastClosestness, &carBelow); + minX, minY, maxX, maxY, &lastCloseness, &carBelow); FindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed, - minX, minY, maxX, maxY, &lastClosestness, &carBelow); + minX, minY, maxX, maxY, &lastCloseness, &carBelow); } } } diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 6fce25e8..9eeeeccd 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -60,20 +60,13 @@ CCivilianPed::CivilianAI(void) if (!threatPed->IsPlayer() || !RunToReportCrime(CRIME_POSSESSION_GUN)) { if (threatDistSqr < sq(10.0f)) { Say(SOUND_PED_FLEE_SPRINT); - SetFlee(m_threatEntity, 10000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_threatEntity, 10000); } else { - SetFlee(m_threatEntity->GetPosition(), 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - SetMoveState(PEDMOVE_WALK); + SetFindPathAndFlee(m_threatEntity->GetPosition(), 5000, true); } } } else if (m_objective != OBJECTIVE_NONE || GetWeapon()->IsTypeMelee()) { - SetFlee(m_threatEntity, 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_threatEntity, 5000); if (threatDistSqr < sq(20.0f)) { SetMoveState(PEDMOVE_RUN); Say(SOUND_PED_FLEE_SPRINT); @@ -81,9 +74,7 @@ CCivilianPed::CivilianAI(void) SetMoveState(PEDMOVE_WALK); } } else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops) { - SetFlee(m_threatEntity, 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_threatEntity, 5000); if (threatDistSqr < sq(10.0f)) { SetMoveState(PEDMOVE_RUN); } else { @@ -95,15 +86,11 @@ CCivilianPed::CivilianAI(void) } else { if (threatDistSqr < sq(10.0f)) { Say(SOUND_PED_FLEE_SPRINT); - SetFlee(m_threatEntity, 10000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_threatEntity, 10000); SetMoveState(PEDMOVE_SPRINT); } else { Say(SOUND_PED_FLEE_SPRINT); - SetFlee(m_threatEntity, 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_threatEntity, 5000); SetMoveState(PEDMOVE_RUN); } } @@ -113,9 +100,7 @@ CCivilianPed::CivilianAI(void) float eventDistSqr = (m_pEventEntity->GetPosition() - GetPosition()).MagnitudeSqr2D(); if (IsGangMember() && m_nPedType == ((CPed*)m_pEventEntity)->m_nPedType) { if (eventDistSqr < sq(5.0f)) { - SetFlee(m_pEventEntity, 2000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_pEventEntity, 2000); SetMoveState(PEDMOVE_RUN); } } else if (IsGangMember() || eventDistSqr > sq(5.0f)) { @@ -150,9 +135,7 @@ CCivilianPed::CivilianAI(void) if(!eligibleToReport || !RunToReportCrime(crime)) #endif { - SetFlee(m_pEventEntity, 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_pEventEntity, 5000); SetMoveState(PEDMOVE_RUN); } } @@ -188,19 +171,14 @@ CCivilianPed::CivilianAI(void) if (threatPed->GetWeapon()->IsTypeMelee() || !GetWeapon()->IsTypeMelee()) { if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops) { if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { - SetFlee(m_threatEntity, 10000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_threatEntity, 10000); } } else { SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity); } } } else { - SetFlee(m_threatEntity, 10000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - SetMoveState(PEDMOVE_WALK); + SetFindPathAndFlee(m_threatEntity, 10000, true); } } } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7b96fc46..f42ee0c8 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1068,7 +1068,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) if (attackAssoc) { switch (attackAssoc->animId) { case ANIM_WEAPON_START_THROW: - if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer()) { + if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) { attackAssoc->blendDelta = -1000.0f; newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU); } else { @@ -1141,7 +1141,7 @@ CPed::Attack(void) return; if (reloadAnimAssoc) { - if (!IsPlayer() || ((CPlayerPed*)this)->field_1380) + if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) ClearAttack(); return; @@ -1162,7 +1162,7 @@ CPed::Attack(void) if (!weaponAnimAssoc) { if (attackShouldContinue) { - if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->field_1380) { + if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) { if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f); } @@ -1178,7 +1178,7 @@ CPed::Attack(void) if (IsPlayer()) { ((CPlayerPed*)this)->field_1376 = 0.0f; - ((CPlayerPed*)this)->field_1380 = false; + ((CPlayerPed*)this)->m_bHaveTargetSelected = false; } } } else @@ -4641,7 +4641,7 @@ CPed::SetAttack(CEntity *victim) } if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) { - if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->field_1380) + if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected) bIsAttacking = false; else bIsAttacking = true; @@ -5720,15 +5720,8 @@ CPed::CollideWithPed(CPed *collideWith) SetLookTimer(800); } } else { - bool doWeRun = true; - if (m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT) - doWeRun = false; - - SetFlee(collideWith, 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - if (!doWeRun) - SetMoveState(PEDMOVE_WALK); + bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; + SetFindPathAndFlee(collideWith, 5000, !isRunning); } } @@ -12982,9 +12975,7 @@ CPed::ProcessObjective(void) else time = 6000; - SetFlee(m_pedInObjective, time); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; + SetFindPathAndFlee(m_pedInObjective, time); } break; } @@ -13506,10 +13497,7 @@ CPed::ProcessObjective(void) if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) { ClearObjective(); - SetFlee(m_pedInObjective, 15000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - SetMoveState(PEDMOVE_WALK); + SetFindPathAndFlee(m_pedInObjective, 15000, true); return; } float distWithTargetScSqr = distWithTarget.MagnitudeSqr(); @@ -13536,10 +13524,7 @@ CPed::ProcessObjective(void) ClearObjective(); if (m_pedInObjective->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT || m_pedInObjective->m_pedInObjective != this) { - SetFlee(m_pedInObjective, 15000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - SetMoveState(PEDMOVE_WALK); + SetFindPathAndFlee(m_pedInObjective, 15000, true); m_nLastPedState = PED_WANDER_PATH; } else { SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective); @@ -13783,11 +13768,7 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj) #endif if (CharCreatedBy != MISSION_CHAR && obj->m_modelIndex == MI_PHONEBOOTH1) { bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; - SetFlee(obj, 5000); - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - if (!isRunning) - SetMoveState(PEDMOVE_WALK); + SetFindPathAndFlee(obj, 5000, !isRunning); return; } diff --git a/src/peds/Ped.h b/src/peds/Ped.h index f8a063f3..b421bc83 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -792,6 +792,24 @@ public: void ReplaceWeaponWhenExitingVehicle(void); void RemoveWeaponWhenEnteringVehicle(void); bool IsNotInWreckedVehicle(); + // My additions, because there were many, many instances of that. + inline void SetFindPathAndFlee(CEntity *fleeFrom, int time, bool walk = false) + { + SetFlee(fleeFrom, time); + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + if (walk) + SetMoveState(PEDMOVE_WALK); + } + + inline void SetFindPathAndFlee(CVector2D const &from, int time, bool walk = false) + { + SetFlee(from, time); + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + if (walk) + SetMoveState(PEDMOVE_WALK); + } // set by 0482:set_threat_reaction_range_multiplier opcode static uint16 &nThreatReactionRangeMultiplier; diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 8892fc2a..ff48ca4d 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -9,13 +9,13 @@ #include "General.h" #include "Pools.h" #include "Darkel.h" +#include "CarCtrl.h" CPlayerPed::~CPlayerPed() { delete m_pWanted; } -WRAPPER void CPlayerPed::KeepAreaAroundPlayerClear(void) { EAXJMP(0x4F3460); } WRAPPER void CPlayerPed::ProcessControl(void) { EAXJMP(0x4EFD90); } CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) @@ -40,7 +40,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) field_1367 = 0; m_nShotDelay = 0; field_1376 = 0.0f; - field_1380 = 0; + m_bHaveTargetSelected = false; m_bHasLockOnTarget = false; m_bCanBeDamaged = true; m_fWalkAngle = 0.0f; @@ -58,7 +58,7 @@ void CPlayerPed::ClearWeaponTarget() if (m_nPedType == PEDTYPE_PLAYER1) { m_pPointGunAt = nil; TheCamera.ClearPlayerWeaponMode(); - CWeaponEffects::ClearCrosshair(); + CWeaponEffects::ClearCrossHair(); } ClearPointGunAt(); } @@ -651,12 +651,12 @@ CPlayerPed::PlayerControlFighter(CPad *padUsed) { float leftRight = padUsed->GetPedWalkLeftRight(); float upDown = padUsed->GetPedWalkUpDown(); - float displacement = sqrt(upDown * upDown + leftRight * leftRight); + float padMove = Sqrt(upDown * upDown + leftRight * leftRight); - if (displacement > 0.0f) { + if (padMove > 0.0f) { m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation; - m_takeAStepAfterAttack = displacement > 120.0f; - if (padUsed->GetSprint() && displacement > 60.0f) + m_takeAStepAfterAttack = padMove > 120.0f; + if (padUsed->GetSprint() && padMove > 60.0f) bIsAttacking = false; } @@ -671,6 +671,401 @@ CPlayerPed::PlayerControlFighter(CPad *padUsed) } } +void +CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) +{ + float leftRight = padUsed->GetPedWalkLeftRight(); + float upDown = padUsed->GetPedWalkUpDown(); + float padMove = Sqrt(upDown * upDown + leftRight * leftRight); + float padMoveInGameUnit = padMove / 60.0f; + if (padMoveInGameUnit > 0.0f) { + m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation); + m_fMoveSpeed = min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed); + } else { + m_fMoveSpeed = 0.0f; + } + + if (m_nPedState == PED_JUMP) { + if (bIsInTheAir) { + if (bUsesCollision && !bHitSteepSlope && + (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f) + && m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) { + + float angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O + float angleCos = Cos(m_fRotationCur); + ApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f); + } + } else if (bIsLanding) { + m_fMoveSpeed = 0.0f; + } + } + if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy) + && padUsed->GetSprint()) { + m_nMoveState = PEDMOVE_SPRINT; + } + if (m_nPedState != PED_FIGHT) + SetRealMoveAnim(); + + if (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bHeavy) + && padUsed->JumpJustDown() && m_nPedState != PED_JUMP) { + ClearAttack(); + ClearWeaponTarget(); + if (m_bShouldEvade && m_pEvadingFrom) { + SetEvasiveDive((CPhysical*)m_pEvadingFrom, 1); + m_bShouldEvade = false; + m_pEvadingFrom = nil; + } else { + SetJump(); + } + } +} + +void +CPlayerPed::KeepAreaAroundPlayerClear(void) +{ + BuildPedLists(); + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed->CharCreatedBy == RANDOM_CHAR && !nearPed->DyingOrDead()) { + if (nearPed->GetIsOnScreen()) { + if (nearPed->m_objective == OBJECTIVE_NONE) { + nearPed->SetFindPathAndFlee(this, 5000, true); + } else { + if (nearPed->m_nPedState == PED_ENTER_CAR || nearPed->m_nPedState == PED_CARJACK) + nearPed->QuitEnteringCar(); + + nearPed->ClearObjective(); + } + } else { + nearPed->FlagToDestroyWhenNextProcessed(); + } + } + } + CVector playerPos = (InVehicle() ? m_pMyVehicle->GetPosition() : GetPosition()); + + 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->VehicleCreatedBy != MISSION_VEHICLE) { + if (veh->m_status != STATUS_PLAYER && veh->m_status != STATUS_PLAYER_DISABLED) { + if ((veh->GetPosition() - playerPos).MagnitudeSqr() > 25.0f) { + veh->AutoPilot.m_nTempAction = TEMPACT_WAIT; + veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 5000; + } else { + if (DotProduct2D(playerPos - veh->GetPosition(), veh->GetForward()) > 0.0f) + veh->AutoPilot.m_nTempAction = TEMPACT_REVERSE; + else + veh->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD; + + veh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; + } + CCarCtrl::PossiblyRemoveVehicle(veh); + } + } + } +} + +void +CPlayerPed::EvaluateNeighbouringTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool lookToLeft) +{ + CVector distVec = candidate->GetPosition() - GetPosition(); + if (distVec.Magnitude2D() <= distLimit) { + if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) { +#ifdef VC_PED_PORTS + float angleBetweenUs = CGeneral::GetATanOfXY(candidate->GetPosition().x - TheCamera.GetPosition().x, + candidate->GetPosition().y - TheCamera.GetPosition().y); +#else + float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y); +#endif + angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset); + float closeness; + if (lookToLeft) { + closeness = angleBetweenUs > 0.0f ? -Abs(angleBetweenUs) : -100000.0f; + } else { + closeness = angleBetweenUs > 0.0f ? -100000.0f : -Abs(angleBetweenUs); + } + + if (closeness > *lastCloseness) { + *targetPtr = candidate; + *lastCloseness = closeness; + } + } + } +} + +void +CPlayerPed::EvaluateTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool priority) +{ + CVector distVec = candidate->GetPosition() - GetPosition(); + float dist = distVec.Magnitude2D(); + if (dist <= distLimit) { + if (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) { + float angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y); + angleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset); + + float closeness = -dist - 5.0f * Abs(angleBetweenUs); + if (priority) { + closeness += 5.0f; + } + + if (closeness > *lastCloseness) { + *targetPtr = candidate; + *lastCloseness = closeness; + } + } + } +} + +bool +CPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft) +{ + CEntity *nextTarget = nil; + float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange; + // nextTarget = nil; + float lastCloseness = -10000.0f; + // unused + // CGeneral::GetATanOfXY(GetForward().x, GetForward().y); + CVector distVec = previousTarget->GetPosition() - GetPosition(); + float referenceBeta = CGeneral::GetATanOfXY(distVec.x, distVec.y); + + for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) { + CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h); + if (pedToCheck) { + if (pedToCheck != FindPlayerPed() && pedToCheck != previousTarget) { + if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle + && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) { + + EvaluateNeighbouringTarget(pedToCheck, &nextTarget, &lastCloseness, + weaponRange, referenceBeta, lookToLeft); + } + } + } + } + for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) { + CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]); + if (obj) + EvaluateNeighbouringTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, lookToLeft); + } + if (!nextTarget) + return false; + + m_pPointGunAt = nextTarget; + if (nextTarget) + nextTarget->RegisterReference((CEntity**)&m_pPointGunAt); + SetPointGunAt(nextTarget); + return true; +} + +bool +CPlayerPed::FindWeaponLockOnTarget(void) +{ + CEntity *nextTarget = nil; + float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange; + + if (m_pPointGunAt) { + CVector distVec = m_pPointGunAt->GetPosition() - GetPosition(); + if (distVec.Magnitude2D() > weaponRange) { + m_pPointGunAt = nil; + return false; + } else { + return true; + } + } + + // nextTarget = nil; + float lastCloseness = -10000.0f; + float referenceBeta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y); + for (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) { + CPed *pedToCheck = CPools::GetPedPool()->GetSlot(h); + if (pedToCheck) { + if (pedToCheck != FindPlayerPed()) { + if (!pedToCheck->DyingOrDead() && !pedToCheck->bInVehicle + && pedToCheck->m_leader != FindPlayerPed() && OurPedCanSeeThisOne(pedToCheck)) { + + EvaluateTarget(pedToCheck, &nextTarget, &lastCloseness, + weaponRange, referenceBeta, IsThisPedAttackingPlayer(pedToCheck)); + } + } + } + } + for (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) { + CObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]); + if (obj) + EvaluateTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, false); + } + if (!nextTarget) + return false; + + m_pPointGunAt = nextTarget; + if (nextTarget) + nextTarget->RegisterReference((CEntity**)&m_pPointGunAt); + SetPointGunAt(nextTarget); + return true; +} + +void +CPlayerPed::ProcessAnimGroups(void) +{ + AssocGroupId groupToSet; + if ((m_fWalkAngle <= -DEGTORAD(50.0f) || m_fWalkAngle >= DEGTORAD(50.0f)) + && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() + && CanStrafeOrMouseControl()) { + + if (m_fWalkAngle >= -DEGTORAD(130.0f) && m_fWalkAngle <= DEGTORAD(130.0f)) { + if (m_fWalkAngle > 0.0f) { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) + groupToSet = ASSOCGRP_ROCKETLEFT; + else + groupToSet = ASSOCGRP_PLAYERLEFT; + } else { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) + groupToSet = ASSOCGRP_ROCKETRIGHT; + else + groupToSet = ASSOCGRP_PLAYERRIGHT; + } + } else { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) + groupToSet = ASSOCGRP_ROCKETBACK; + else + groupToSet = ASSOCGRP_PLAYERBACK; + } + } else { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) { + groupToSet = ASSOCGRP_PLAYERROCKET; + } else { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT) { + groupToSet = ASSOCGRP_PLAYERBBBAT; + } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) { + if (!GetWeapon()->IsType2Handed()) { + groupToSet = ASSOCGRP_PLAYER; + } else { + groupToSet = ASSOCGRP_PLAYER2ARMED; + } + } else { + groupToSet = ASSOCGRP_PLAYER1ARMED; + } + } + } + + if (m_animGroup != groupToSet) { + m_animGroup = groupToSet; + ReApplyMoveAnims(); + } +} + +void +CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) +{ + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + if (m_bHasLockOnTarget && !m_pPointGunAt) { + TheCamera.ClearPlayerWeaponMode(); + CWeaponEffects::ClearCrossHair(); + ClearPointGunAt(); + } + if (!m_pFire) { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || + GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_M16) { + if (padUsed->TargetJustDown()) { + SetStoredState(); + m_nPedState = PED_SNIPER_MODE; + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) + TheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0); + else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE) + TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SNIPER, 0, 0); + else + TheCamera.SetNewPlayerWeaponMode(CCam::MODE_M16_1STPERSON, 0, 0); + + m_fMoveSpeed = 0.0f; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 1000.0f); + } + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE + || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON) + return; + } + } + + if (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) { + if (m_nSelectedWepSlot == m_currentWeapon) { + if (m_pPointGunAt) { + SetAttack(m_pPointGunAt); + } else if (m_currentWeapon != WEAPONTYPE_UNARMED) { + if (m_nPedState == PED_ATTACK) { + if (padUsed->WeaponJustDown()) { + m_bHaveTargetSelected = true; + } else if (!m_bHaveTargetSelected) { + field_1376 += CTimer::GetTimeStepNonClipped(); + } + } else { + field_1376 = 0.0f; + m_bHaveTargetSelected = false; + } + SetAttack(nil); + } else if (padUsed->WeaponJustDown()) { + if (m_fMoveSpeed < 1.0f) + StartFightAttack(padUsed->GetWeapon()); + else + SetAttack(nil); + } + } + } else { + m_pedIK.m_flags &= ~CPedIK::LOOKING; + if (m_nPedState == PED_ATTACK) { + m_bHaveTargetSelected = true; + bIsAttacking = false; + } + } + if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) { + if (m_pPointGunAt) { + // what?? + if (!m_pPointGunAt + || CCamera::m_bUseMouse3rdPerson || m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->bInVehicle) { + ClearWeaponTarget(); + return; + } + if (CPlayerPed::DoesTargetHaveToBeBroken(m_pPointGunAt->GetPosition(), GetWeapon())) { + ClearWeaponTarget(); + return; + } + if (m_pPointGunAt) { + if (padUsed->ShiftTargetLeftJustDown()) + FindNextWeaponLockOnTarget(m_pPointGunAt, true); + if (padUsed->ShiftTargetRightJustDown()) + FindNextWeaponLockOnTarget(m_pPointGunAt, false); + } + TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0); + TheCamera.UpdateAimingCoors(GetPosition()); + } else if (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson) { + if (padUsed->TargetJustDown()) + FindWeaponLockOnTarget(); + } + } else if (m_pPointGunAt) { + ClearWeaponTarget(); + } + + if (m_pPointGunAt) { +#ifndef VC_PED_PORTS + CVector markPos = m_pPointGunAt->GetPosition(); +#else + CVector markPos; + if (m_pPointGunAt->IsPed()) { + ((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition((RwV3d*)markPos, PED_MID); + } else { + markPos = m_pPointGunAt->GetPosition(); + } +#endif + if (bCanPointGunAtTarget) { + CWeaponEffects::MarkTarget(markPos, 64, 0, 0, 255, 0.8f); + } else { + CWeaponEffects::MarkTarget(markPos, 64, 32, 0, 255, 0.8f); + } + } + m_bHasLockOnTarget = m_pPointGunAt != nil; +} + class CPlayerPed_ : public CPlayerPed { public: @@ -699,4 +1094,8 @@ STARTPATCHES InjectHook(0x4F1CF0, &CPlayerPed::PlayerControlSniper, PATCH_JUMP); InjectHook(0x4F2310, &CPlayerPed::ProcessWeaponSwitch, PATCH_JUMP); InjectHook(0x4F1DF0, &CPlayerPed::PlayerControlM16, PATCH_JUMP); + InjectHook(0x4F3460, &CPlayerPed::KeepAreaAroundPlayerClear, PATCH_JUMP); + InjectHook(0x4F1970, &CPlayerPed::PlayerControl1stPersonRunAround, PATCH_JUMP); + InjectHook(0x4F1EF0, &CPlayerPed::ProcessPlayerWeapon, PATCH_JUMP); + InjectHook(0x4F2640, &CPlayerPed::ProcessAnimGroups, PATCH_JUMP); ENDPATCHES diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index 81d996be..0bba7ed3 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -20,11 +20,11 @@ public: int32 m_nSpeedTimer; int32 m_nShotDelay; float field_1376; // m_fAttackButtonCounter? - int8 field_1380; // bHaveTargetSelected? + bool m_bHaveTargetSelected; // may have better name int8 field_1381; int8 field_1382; int8 field_1383; - CEntity *m_pEvadingFrom; + CEntity *m_pEvadingFrom; // is this CPhysical? int32 m_nTargettableObjects[4]; bool m_bAdrenalineActive; bool m_bHasLockOnTarget; @@ -68,6 +68,13 @@ public: void PlayerControlFighter(CPad*); void ProcessWeaponSwitch(CPad*); void MakeObjectTargettable(int32); + void PlayerControl1stPersonRunAround(CPad *padUsed); + void EvaluateNeighbouringTarget(CEntity*, CEntity**, float*, float, float, bool); + void EvaluateTarget(CEntity*, CEntity**, float*, float, float, bool); + bool FindNextWeaponLockOnTarget(CEntity*, bool); + bool FindWeaponLockOnTarget(void); + void ProcessAnimGroups(void); + void ProcessPlayerWeapon(CPad*); static void SetupPlayerPed(int32); static void DeactivatePlayerPed(int32); diff --git a/src/render/WeaponEffects.cpp b/src/render/WeaponEffects.cpp index e062da07..11fb3d2e 100644 --- a/src/render/WeaponEffects.cpp +++ b/src/render/WeaponEffects.cpp @@ -6,7 +6,20 @@ WRAPPER void CWeaponEffects::Render(void) { EAXJMP(0x564D70); } CWeaponEffects &gCrossHair = *(CWeaponEffects*)0x6503BC; -void CWeaponEffects::ClearCrosshair() +void +CWeaponEffects::ClearCrossHair() { gCrossHair.m_bCrosshair = false; } + +void +CWeaponEffects::MarkTarget(CVector pos, uint8 red, uint8 green, uint8 blue, uint8 alpha, float size) +{ + gCrossHair.m_bCrosshair = true; + gCrossHair.m_vecPos = pos; + gCrossHair.m_red = red; + gCrossHair.m_green = green; + gCrossHair.m_blue = blue; + gCrossHair.m_alpha = alpha; + gCrossHair.m_size = size; +} diff --git a/src/render/WeaponEffects.h b/src/render/WeaponEffects.h index 7176c26d..6edcd60b 100644 --- a/src/render/WeaponEffects.h +++ b/src/render/WeaponEffects.h @@ -6,16 +6,17 @@ public: bool m_bCrosshair; int8 gap_1[3]; CVector m_vecPos; - int8 field_16; - int8 field_17; - int8 field_18; - int8 field_19; - float field_20; + uint8 m_red; + uint8 m_green; + uint8 m_blue; + uint8 m_alpha; + float m_size; int32 field_24; RwTexture *m_pTexture; RwRaster *m_pRaster; public: static void Render(void); - static void ClearCrosshair(); + static void ClearCrossHair(); + static void MarkTarget(CVector, uint8, uint8, uint8, uint8, float); };