2019-05-19 15:28:10 -04:00
# include "common.h"
2020-04-17 09:31:11 -04:00
2019-07-03 12:34:42 -04:00
# include "main.h"
2019-05-19 15:28:10 -04:00
# include "Pools.h"
2019-06-16 14:39:48 -04:00
# include "Particle.h"
2019-06-20 07:22:44 -04:00
# include "RpAnimBlend.h"
2020-04-23 16:25:18 -04:00
# include "Bones.h"
2019-06-16 17:12:14 -04:00
# include "Ped.h"
2020-03-28 10:47:52 -04:00
# include "AnimBlendAssociation.h"
# include "Fire.h"
# include "DMAudio.h"
2019-06-17 05:48:42 -04:00
# include "General.h"
2019-06-21 14:16:51 -04:00
# include "VisibilityPlugins.h"
2019-06-24 10:57:54 -04:00
# include "HandlingMgr.h"
# include "Replay.h"
2020-03-28 10:47:52 -04:00
# include "Radar.h"
2019-06-24 10:57:54 -04:00
# include "PedPlacement.h"
2019-06-28 12:19:00 -04:00
# include "Shadows.h"
# include "Weather.h"
2019-07-07 07:09:11 -04:00
# include "ZoneCull.h"
2019-06-30 06:59:55 -04:00
# include "Population.h"
2019-07-03 12:34:42 -04:00
# include "Pad.h"
2019-07-10 02:06:43 -04:00
# include "Phones.h"
2019-08-07 20:21:38 -04:00
# include "TrafficLights.h"
2019-09-03 12:53:04 -04:00
# include "CopPed.h"
2019-09-13 15:04:55 -04:00
# include "Script.h"
# include "CarCtrl.h"
2019-09-16 13:32:58 -04:00
# include "Garages.h"
# include "WaterLevel.h"
2019-10-13 00:05:08 -04:00
# include "Timecycle.h"
# include "ParticleObject.h"
# include "Floater.h"
2020-06-03 21:31:04 -04:00
# include "Range2D.h"
2021-01-16 08:44:59 -05:00
# include "Wanted.h"
2019-05-19 15:28:10 -04:00
2019-08-11 17:35:32 -04:00
CPed * gapTempPedList [ 50 ] ;
uint16 gnNumTempPedList ;
2020-05-25 14:36:18 -04:00
static CColPoint aTempPedColPts [ MAX_COLLISION_POINTS ] ;
2019-07-28 13:39:39 -04:00
2019-06-15 11:53:25 -04:00
2020-04-15 12:19:45 -04:00
uint16 CPed : : nThreatReactionRangeMultiplier = 1 ;
uint16 CPed : : nEnterCarRangeMultiplier = 1 ;
2019-06-30 17:50:40 -04:00
2020-04-15 12:19:45 -04:00
bool CPed : : bNastyLimbsCheat ;
bool CPed : : bPedCheat2 ;
bool CPed : : bPedCheat3 ;
2019-09-16 13:32:58 -04:00
CVector2D CPed : : ms_vec2DFleePosition ;
2019-06-24 10:57:54 -04:00
2019-06-02 11:13:56 -04:00
void * CPed : : operator new ( size_t sz ) { return CPools : : GetPedPool ( ) - > New ( ) ; }
2019-06-30 06:59:55 -04:00
void * CPed : : operator new ( size_t sz , int handle ) { return CPools : : GetPedPool ( ) - > New ( handle ) ; }
2019-06-02 11:13:56 -04:00
void CPed : : operator delete ( void * p , size_t sz ) { CPools : : GetPedPool ( ) - > Delete ( ( CPed * ) p ) ; }
2019-06-30 09:20:11 -04:00
void CPed : : operator delete ( void * p , int handle ) { CPools : : GetPedPool ( ) - > Delete ( ( CPed * ) p ) ; }
2019-05-19 15:28:10 -04:00
2020-07-01 08:28:43 -04:00
# ifdef DEBUGMENU
2019-11-04 18:04:26 -05:00
bool CPed : : bPopHeadsOnHeadshot = false ;
2019-11-24 21:25:10 -05:00
# endif
2019-06-30 17:50:40 -04:00
CPed : : CPed ( uint32 pedType ) : m_pedIK ( this )
{
m_type = ENTITY_TYPE_PED ;
bPedPhysics = true ;
bUseCollisionRecords = true ;
2019-07-15 08:11:40 -04:00
m_vecAnimMoveDelta . x = 0.0f ;
m_vecAnimMoveDelta . y = 0.0f ;
2019-06-30 17:50:40 -04:00
m_fHealth = 100.0f ;
m_fArmour = 0.0f ;
m_nPedType = pedType ;
2019-07-29 08:01:44 -04:00
m_lastSoundStart = 0 ;
m_soundStart = 0 ;
2020-05-15 22:06:51 -04:00
m_lastQueuedSound = SOUND_NO_SOUND ;
m_queuedSound = SOUND_NO_SOUND ;
2019-07-03 12:34:42 -04:00
m_objective = OBJECTIVE_NONE ;
m_prevObjective = OBJECTIVE_NONE ;
2020-06-06 06:31:09 -04:00
# ifdef FIX_BUGS
m_objectiveTimer = 0 ;
# endif
2019-07-05 08:23:39 -04:00
CharCreatedBy = RANDOM_CHAR ;
2019-07-03 12:34:42 -04:00
m_leader = nil ;
m_pedInObjective = nil ;
m_carInObjective = nil ;
2019-07-29 08:01:44 -04:00
bInVehicle = false ;
2019-06-30 17:50:40 -04:00
m_pMyVehicle = nil ;
m_pVehicleAnim = nil ;
2019-07-15 08:11:40 -04:00
m_vecOffsetSeek . x = 0.0f ;
m_vecOffsetSeek . y = 0.0f ;
m_vecOffsetSeek . z = 0.0f ;
2019-10-06 18:13:18 -04:00
m_pedFormation = FORMATION_UNDEFINED ;
2019-08-10 11:15:22 -04:00
m_collidingThingTimer = 0 ;
2019-06-30 17:50:40 -04:00
m_nPedStateTimer = 0 ;
2020-09-09 20:14:50 -04:00
m_actionX = 0.0f ;
m_actionY = 0.0f ;
2019-06-30 17:50:40 -04:00
m_phoneTalkTimer = 0 ;
m_stateUnused = 0 ;
m_leaveCarTimer = 0 ;
m_getUpTimer = 0 ;
m_attackTimer = 0 ;
m_timerUnused = 0 ;
m_lookTimer = 0 ;
2021-01-13 07:41:24 -05:00
m_chatTimer = 0 ;
2019-09-03 12:53:04 -04:00
m_shootTimer = 0 ;
2021-01-13 07:41:24 -05:00
m_carJackTimer = 0 ;
2019-08-01 18:04:30 -04:00
m_duckAndCoverTimer = 0 ;
2019-07-03 12:34:42 -04:00
m_moved = CVector2D ( 0.0f , 0.0f ) ;
2019-06-30 17:50:40 -04:00
m_fRotationCur = 0.0f ;
m_headingRate = 15.0f ;
m_fRotationDest = 0.0f ;
2021-01-13 07:01:11 -05:00
m_vehDoor = CAR_DOOR_LF ;
2019-06-30 17:50:40 -04:00
m_walkAroundType = 0 ;
m_pCurrentPhysSurface = nil ;
m_vecOffsetFromPhysSurface = CVector ( 0.0f , 0.0f , 0.0f ) ;
m_pSeekTarget = nil ;
2019-08-10 11:15:22 -04:00
m_vecSeekPos = CVector ( 0.0f , 0.0f , 0.0f ) ;
2019-06-30 17:50:40 -04:00
m_wepSkills = 0 ;
2019-08-10 11:15:22 -04:00
m_distanceToCountSeekDone = 1.0f ;
2019-07-29 08:01:44 -04:00
bRunningToPhone = false ;
2019-06-30 17:50:40 -04:00
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 ) ;
2019-09-26 17:01:50 -04:00
m_distanceToCountSeekDoneEx = 0.0f ;
2019-07-05 18:44:49 -04:00
m_nWaitState = WAITSTATE_FALSE ;
2019-06-30 17:50:40 -04:00
m_nWaitTimer = 0 ;
m_pCollidingEntity = nil ;
m_nPedState = PED_IDLE ;
m_nLastPedState = PED_NONE ;
2019-07-03 12:34:42 -04:00
m_nMoveState = PEDMOVE_STILL ;
2020-06-06 09:36:26 -04:00
# ifdef FIX_BUGS
m_nPrevMoveState = PEDMOVE_NONE ;
# endif
2019-07-25 11:06:24 -04:00
m_nStoredMoveState = PEDMOVE_NONE ;
2019-06-30 17:50:40 -04:00
m_pFire = nil ;
m_pPointGunAt = nil ;
2019-07-03 12:34:42 -04:00
m_pLookTarget = nil ;
2019-06-30 17:50:40 -04:00
m_fLookDirection = 0.0f ;
2019-07-03 12:34:42 -04:00
m_pCurSurface = nil ;
2019-10-06 17:39:25 -04:00
m_wanderRangeBounds = nil ;
2019-06-30 17:50:40 -04:00
m_nPathNodes = 0 ;
m_nCurPathNode = 0 ;
2019-11-19 17:15:45 -05:00
m_nPathDir = 0 ;
2019-06-30 17:50:40 -04:00
m_pLastPathNode = nil ;
2019-08-10 11:15:22 -04:00
m_pNextPathNode = nil ;
2019-06-30 17:50:40 -04:00
m_routeLastPoint = - 1 ;
2019-08-12 18:30:31 -04:00
m_routeStartPoint = 0 ;
m_routePointsPassed = 0 ;
2019-06-30 17:50:40 -04:00
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 ;
2020-04-30 11:13:38 -04:00
bWasStanding = false ;
2019-08-05 09:07:10 -04:00
bIsAttacking = false ;
2019-06-30 17:50:40 -04:00
bIsPointingGunAt = false ;
bIsLooking = false ;
2019-08-22 18:44:38 -04:00
bKeepTryingToLook = false ;
2019-06-30 17:50:40 -04:00
bIsRestoringLook = false ;
bIsAimingGun = false ;
bIsRestoringGun = false ;
bCanPointGunAtTarget = false ;
2019-07-05 18:44:49 -04:00
bIsTalking = false ;
bIsInTheAir = false ;
bIsLanding = false ;
2019-08-10 11:15:22 -04:00
bIsRunning = false ;
2019-09-03 12:53:04 -04:00
bHitSomethingLastFrame = false ;
2019-10-26 11:41:04 -04:00
bVehEnterDoorIsBlocked = false ;
2019-06-30 17:50:40 -04:00
2019-10-26 11:41:04 -04:00
bCanPedEnterSeekedCar = false ;
2019-07-05 18:44:49 -04:00
bRespondsToThreats = true ;
2019-07-17 22:26:46 -04:00
bRenderPedInCar = true ;
bChangedSeat = false ;
2019-07-25 11:06:24 -04:00
bUpdateAnimHeading = false ;
2019-07-17 22:26:46 -04:00
bBodyPartJustCameOff = false ;
2019-12-31 18:35:54 -05:00
bIsShooting = false ;
2019-08-22 18:44:38 -04:00
bFindNewNodeAfterStateRestore = false ;
2019-06-30 17:50:40 -04:00
2020-03-01 19:03:39 -05:00
bGonnaInvestigateEvent = false ;
2019-09-29 12:44:51 -04:00
bPedIsBleeding = false ;
bStopAndShoot = false ;
2019-07-17 22:26:46 -04:00
bIsPedDieAnimPlaying = false ;
2019-08-17 08:44:25 -04:00
bUsePedNodeSeek = false ;
2019-09-29 12:44:51 -04:00
bObjectiveCompleted = false ;
2019-07-25 16:34:29 -04:00
bScriptObjectiveCompleted = false ;
2019-06-30 17:50:40 -04:00
2019-07-25 11:06:24 -04:00
bKindaStayInSamePlace = false ;
2020-03-28 10:47:52 -04:00
bBeingChasedByPolice = false ;
2019-07-05 18:44:49 -04:00
bNotAllowedToDuck = false ;
bCrouchWhenShooting = false ;
bIsDucking = false ;
2019-07-25 11:06:24 -04:00
bGetUpAnimStarted = false ;
2019-06-30 17:50:40 -04:00
bDoBloodyFootprints = false ;
2019-09-13 15:04:55 -04:00
bFleeAfterExitingCar = false ;
2019-06-30 17:50:40 -04:00
2019-09-03 12:53:04 -04:00
bWanderPathAfterExitingCar = false ;
2019-12-31 18:35:54 -05:00
bIsLeader = false ;
bDontDragMeOutCar = false ;
2019-06-30 17:50:40 -04:00
m_ped_flagF8 = false ;
2019-08-01 18:04:30 -04:00
bWillBeQuickJacked = false ;
2019-09-05 15:59:44 -04:00
bCancelEnteringCar = false ;
2019-09-29 12:44:51 -04:00
bObstacleShowedUpDuringKillObjective = false ;
2019-08-01 18:04:30 -04:00
bDuckAndCover = false ;
2019-06-30 17:50:40 -04:00
2019-10-02 21:02:02 -04:00
bStillOnValidPoly = false ;
2019-12-31 18:35:54 -05:00
bAllowMedicsToReviveMe = true ;
2019-12-26 17:15:27 -05:00
bResetWalkAnims = false ;
2019-09-03 12:53:04 -04:00
bStartWanderPathOnFoot = false ;
2019-10-02 21:02:02 -04:00
bOnBoat = false ;
2019-09-12 08:35:05 -04:00
bBusJacked = false ;
2019-09-13 15:04:55 -04:00
bGonnaKillTheCarJacker = false ;
2019-09-03 12:53:04 -04:00
bFadeOut = false ;
2019-06-30 17:50:40 -04:00
2020-03-01 19:03:39 -05:00
bKnockedUpIntoAir = false ;
2019-10-02 21:02:02 -04:00
bHitSteepSlope = false ;
2019-12-31 18:35:54 -05:00
bCullExtraFarAway = false ;
2019-07-25 11:06:24 -04:00
bClearObjective = false ;
2019-12-09 18:02:02 -05:00
bTryingToReachDryLand = false ;
2019-09-12 08:35:05 -04:00
bCollidedWithMyVehicle = false ;
2019-09-16 13:32:58 -04:00
bRichFromMugging = false ;
2019-12-31 18:35:54 -05:00
bChrisCriminal = false ;
2019-06-30 17:50:40 -04:00
2019-08-17 08:44:25 -04:00
bShakeFist = false ;
2019-07-25 11:06:24 -04:00
bNoCriticalHits = false ;
2020-03-01 19:03:39 -05:00
bVehExitWillBeInstant = false ;
2019-07-09 03:57:44 -04:00
bHasAlreadyBeenRecorded = false ;
2019-08-22 18:44:38 -04:00
bFallenDown = false ;
2019-07-01 15:46:44 -04:00
# ifdef KANGAROO_CHEAT
m_ped_flagI80 = false ;
# endif
2019-10-05 14:50:02 -04:00
# ifdef VC_PED_PORTS
2020-03-01 19:03:39 -05:00
bSomeVCflag1 = false ;
2019-10-05 14:50:02 -04:00
# endif
2019-06-30 17:50:40 -04:00
2020-09-09 20:14:50 -04:00
if ( CGeneral : : GetRandomNumber ( ) & 3 )
bHasACamera = false ;
else
2019-09-13 15:04:55 -04:00
bHasACamera = true ;
2019-06-30 17:50:40 -04:00
2019-08-14 21:43:00 -04:00
m_audioEntityId = DMAudio . CreateEntity ( AUDIOTYPE_PHYSICAL , this ) ;
2020-12-25 01:59:32 -05:00
DMAudio . SetEntityStatus ( m_audioEntityId , true ) ;
2019-06-30 17:50:40 -04:00
m_fearFlags = CPedType : : GetThreats ( m_nPedType ) ;
m_threatEntity = nil ;
2019-07-29 08:01:44 -04:00
m_eventOrThreat = CVector2D ( 0.0f , 0.0f ) ;
2019-06-30 17:50:40 -04:00
m_pEventEntity = nil ;
m_fAngleToEvent = 0.0f ;
m_numNearPeds = 0 ;
2019-11-09 10:17:54 -05:00
for ( int i = 0 ; i < ARRAY_SIZE ( m_nearPeds ) ; i + + ) {
2019-06-30 17:50:40 -04:00
m_nearPeds [ i ] = nil ;
2019-11-09 10:17:54 -05:00
if ( i < ARRAY_SIZE ( m_pPathNodesStates ) ) {
2019-06-30 17:50:40 -04:00
m_pPathNodesStates [ i ] = nil ;
}
}
2019-07-29 08:01:44 -04:00
m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED ;
m_currentWeapon = WEAPONTYPE_UNARMED ;
2019-07-04 16:31:21 -04:00
m_storedWeapon = WEAPONTYPE_UNIDENTIFIED ;
2019-06-30 17:50:40 -04:00
2019-09-16 13:32:58 -04:00
for ( int i = 0 ; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS ; i + + ) {
2019-07-01 15:46:44 -04:00
CWeapon & weapon = GetWeapon ( i ) ;
weapon . m_eWeaponType = WEAPONTYPE_UNARMED ;
weapon . m_eWeaponState = WEAPONSTATE_READY ;
weapon . m_nAmmoInClip = 0 ;
weapon . m_nAmmoTotal = 0 ;
weapon . m_nTimer = 0 ;
2019-06-30 17:50:40 -04:00
}
2020-07-20 15:47:41 -04:00
m_curFightMove = FIGHTMOVE_NULL ;
2019-06-30 17:50:40 -04:00
GiveWeapon ( WEAPONTYPE_UNARMED , 0 ) ;
m_wepAccuracy = 60 ;
m_lastWepDam = - 1 ;
m_collPoly . valid = false ;
m_fCollisionSpeed = 0.0f ;
m_wepModelID = - 1 ;
2020-04-23 16:25:18 -04:00
# ifdef PED_SKIN
m_pWeaponModel = nil ;
# endif
2020-02-15 21:15:58 -05:00
CPopulation : : UpdatePedCount ( ( ePedType ) m_nPedType , false ) ;
2019-06-30 17:50:40 -04:00
}
2020-11-19 14:12:20 -05:00
CPed : : ~ CPed ( void )
2019-06-30 17:50:40 -04:00
{
2020-11-19 14:12:20 -05:00
CWorld : : Remove ( this ) ;
CRadar : : ClearBlipForEntity ( BLIP_CHAR , CPools : : GetPedPool ( ) - > GetIndex ( this ) ) ;
if ( InVehicle ( ) ) {
2021-01-13 07:01:11 -05:00
uint8 door_flag = GetCarDoorFlag ( m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
if ( m_pMyVehicle - > pDriver = = this )
m_pMyVehicle - > pDriver = nil ;
else {
// FIX: Passenger counter now decreasing after removing ourself from vehicle.
m_pMyVehicle - > RemovePassenger ( this ) ;
}
if ( m_nPedState = = PED_EXIT_CAR | | m_nPedState = = PED_DRAG_FROM_CAR )
m_pMyVehicle - > m_nGettingOutFlags & = ~ door_flag ;
bInVehicle = false ;
m_pMyVehicle = nil ;
} else if ( EnteringCar ( ) ) {
QuitEnteringCar ( ) ;
2019-06-30 17:50:40 -04:00
}
2020-11-19 14:12:20 -05:00
if ( m_pFire )
m_pFire - > Extinguish ( ) ;
CPopulation : : UpdatePedCount ( ( ePedType ) m_nPedType , true ) ;
DMAudio . DestroyEntity ( m_audioEntityId ) ;
2019-06-30 17:50:40 -04:00
}
2020-11-19 14:12:20 -05:00
void
CPed : : Initialise ( void )
2019-06-21 14:16:51 -04:00
{
2020-11-19 14:12:20 -05:00
debug ( " Initialising CPed... \n " ) ;
CPedType : : Initialise ( ) ;
LoadFightData ( ) ;
SetAnimOffsetForEnterOrExitVehicle ( ) ;
debug ( " CPed ready \n " ) ;
2019-06-21 14:16:51 -04:00
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetModelIndex ( uint32 mi )
2019-06-20 07:22:44 -04:00
{
2020-11-19 14:12:20 -05:00
CEntity : : SetModelIndex ( mi ) ;
RpAnimBlendClumpInit ( GetClump ( ) ) ;
RpAnimBlendClumpFillFrameArray ( GetClump ( ) , m_pFrames ) ;
CPedModelInfo * modelInfo = ( CPedModelInfo * ) CModelInfo : : GetModelInfo ( GetModelIndex ( ) ) ;
SetPedStats ( modelInfo - > m_pedStatType ) ;
m_headingRate = m_pedStats - > m_headingChangeRate ;
m_animGroup = ( AssocGroupId ) modelInfo - > m_animGroup ;
CAnimManager : : AddAnimation ( GetClump ( ) , m_animGroup , ANIM_IDLE_STANCE ) ;
2019-06-20 07:22:44 -04:00
2021-01-13 07:06:31 -05:00
( * RPANIMBLENDCLUMPDATA ( m_rwObject ) ) - > velocity2d = & m_vecAnimMoveDelta ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
# ifdef PED_SKIN
if ( modelInfo - > GetHitColModel ( ) = = nil )
modelInfo - > CreateHitColModelSkinned ( GetClump ( ) ) ;
# endif
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetPedStats ( ePedStats pedStat )
{
m_pedStats = CPedStats : : ms_apPedStats [ pedStat ] ;
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : BuildPedLists ( void )
{
if ( ( ( CTimer : : GetFrameCounter ( ) + m_randomSeed ) % 16 ) = = 0 ) {
CVector centre = CEntity : : GetBoundCentre ( ) ;
CRect rect ( centre . x - 20.0f ,
centre . y - 20.0f ,
centre . x + 20.0f ,
centre . y + 20.0f ) ;
int xstart = CWorld : : GetSectorIndexX ( rect . left ) ;
int ystart = CWorld : : GetSectorIndexY ( rect . top ) ;
int xend = CWorld : : GetSectorIndexX ( rect . right ) ;
int yend = CWorld : : GetSectorIndexY ( rect . bottom ) ;
gnNumTempPedList = 0 ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
for ( int y = ystart ; y < = yend ; y + + ) {
for ( int x = xstart ; x < = xend ; 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 ( nThreatReactionRangeMultiplier * 30.0f > dist ) {
gapTempPedList [ gnNumTempPedList ] = ped ;
gnNumTempPedList + + ;
assert ( gnNumTempPedList < ARRAY_SIZE ( gapTempPedList ) ) ;
}
2019-06-20 07:22:44 -04:00
}
}
}
}
2020-11-19 14:12:20 -05:00
gapTempPedList [ gnNumTempPedList ] = nil ;
SortPeds ( gapTempPedList , 0 , gnNumTempPedList - 1 ) ;
for ( m_numNearPeds = 0 ; m_numNearPeds < ARRAY_SIZE ( m_nearPeds ) ; m_numNearPeds + + ) {
CPed * ped = gapTempPedList [ m_numNearPeds ] ;
if ( ! ped )
break ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
m_nearPeds [ m_numNearPeds ] = ped ;
}
for ( int pedToClear = m_numNearPeds ; pedToClear < ARRAY_SIZE ( m_nearPeds ) ; pedToClear + + )
m_nearPeds [ pedToClear ] = nil ;
2019-06-20 07:22:44 -04:00
} else {
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < ARRAY_SIZE ( m_nearPeds ) ; ) {
bool removePed = false ;
if ( m_nearPeds [ i ] ) {
if ( m_nearPeds [ i ] - > IsPointerValid ( ) ) {
float distSqr = ( GetPosition ( ) - m_nearPeds [ i ] - > GetPosition ( ) ) . MagnitudeSqr2D ( ) ;
if ( distSqr > 900.0f )
removePed = true ;
} else
removePed = true ;
}
if ( removePed ) {
// If we arrive here, the ped we're checking isn't "near", so we should remove it.
for ( int j = i ; j < ARRAY_SIZE ( m_nearPeds ) - 1 ; j + + ) {
m_nearPeds [ j ] = m_nearPeds [ j + 1 ] ;
m_nearPeds [ j + 1 ] = nil ;
}
// Above loop won't work on last slot, so we need to empty it.
m_nearPeds [ ARRAY_SIZE ( m_nearPeds ) - 1 ] = nil ;
m_numNearPeds - - ;
} else
i + + ;
}
2019-06-20 07:22:44 -04:00
}
2019-06-19 08:06:13 -04:00
}
2019-05-28 02:39:36 -04:00
bool
2020-11-19 14:12:20 -05:00
CPed : : OurPedCanSeeThisOne ( CEntity * target )
2019-05-28 02:39:36 -04:00
{
2020-11-19 14:12:20 -05:00
CColPoint colpoint ;
CEntity * ent ;
2019-06-14 08:33:08 -04:00
2020-11-19 14:12:20 -05:00
CVector2D dist = CVector2D ( target - > GetPosition ( ) ) - CVector2D ( GetPosition ( ) ) ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
// Check if target is behind ped
if ( DotProduct2D ( dist , CVector2D ( GetForward ( ) ) ) < 0.0f )
return false ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
// Check if target is too far away
if ( dist . Magnitude ( ) > = 40.0f )
2020-03-30 22:54:19 -04:00
return false ;
2020-11-19 14:12:20 -05:00
// Check line of sight from head
CVector headPos = this - > GetPosition ( ) ;
headPos . z + = 1.0f ;
return ! CWorld : : ProcessLineOfSight ( headPos , target - > GetPosition ( ) , colpoint , ent , true , false , false , false , false , false ) ;
2019-07-03 12:34:42 -04:00
}
2020-11-19 14:12:20 -05:00
// Some kind of binary sort
2019-06-14 08:33:08 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : SortPeds ( CPed * * list , int min , int max )
2019-06-14 08:33:08 -04:00
{
2020-11-19 14:12:20 -05:00
if ( min > = max )
return ;
2019-06-14 08:33:08 -04:00
2020-11-19 14:12:20 -05:00
CVector leftDiff , rightDiff ;
CVector middleDiff = GetPosition ( ) - list [ ( max + min ) / 2 ] - > GetPosition ( ) ;
float middleDist = middleDiff . Magnitude ( ) ;
2020-07-02 09:01:42 -04:00
2020-11-19 14:12:20 -05:00
int left = max ;
int right = min ;
while ( right < = left ) {
float rightDist , leftDist ;
do {
rightDiff = GetPosition ( ) - list [ right ] - > GetPosition ( ) ;
rightDist = rightDiff . Magnitude ( ) ;
} while ( middleDist > rightDist & & + + right ) ;
do {
leftDiff = GetPosition ( ) - list [ left ] - > GetPosition ( ) ;
leftDist = leftDiff . Magnitude ( ) ;
} while ( middleDist < leftDist & & left - - ) ;
if ( right < = left ) {
CPed * ped = list [ right ] ;
list [ right ] = list [ left ] ;
list [ left ] = ped ;
right + + ;
left - - ;
2020-04-23 16:25:18 -04:00
}
2019-06-14 08:33:08 -04:00
}
2020-11-19 14:12:20 -05:00
SortPeds ( list , min , left ) ;
SortPeds ( list , right , max ) ;
2019-06-14 08:33:08 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetMoveState ( eMoveState state )
2019-06-14 08:33:08 -04:00
{
2020-11-19 14:12:20 -05:00
m_nMoveState = state ;
2019-06-15 11:53:25 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetMoveAnim ( void )
2019-06-15 11:53:25 -04:00
{
2020-11-19 14:12:20 -05:00
if ( m_nStoredMoveState = = m_nMoveState | | ! IsPedInControl ( ) )
return ;
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nMoveState = = PEDMOVE_NONE ) {
m_nStoredMoveState = PEDMOVE_NONE ;
return ;
}
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
AssocGroupId animGroupToUse ;
if ( m_leader & & m_leader - > IsPlayer ( ) )
animGroupToUse = ASSOCGRP_PLAYER ;
else
animGroupToUse = m_animGroup ;
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * animAssoc = RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) , ASSOC_BLOCK ) ;
if ( ! animAssoc ) {
CAnimBlendAssociation * fightIdleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FIGHT_IDLE ) ;
animAssoc = fightIdleAssoc ;
if ( fightIdleAssoc & & m_nPedState = = PED_FIGHT )
return ;
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
if ( fightIdleAssoc ) {
CAnimBlendAssociation * idleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_STANCE ) ;
if ( ! idleAssoc | | idleAssoc - > blendDelta < = 0.0f ) {
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_IDLE_STANCE , 8.0f ) ;
2019-06-15 11:53:25 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
if ( ! animAssoc ) {
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_TIRED ) ;
if ( animAssoc )
if ( m_nWaitState = = WAITSTATE_STUCK | | m_nWaitState = = WAITSTATE_FINISH_FLEE )
return ;
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
if ( animAssoc ) {
CAnimBlendAssociation * idleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_STANCE ) ;
if ( ! idleAssoc | | idleAssoc - > blendDelta < = 0.0f ) {
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_IDLE_STANCE , 4.0f ) ;
2019-06-15 11:53:25 -04:00
}
}
}
2020-11-19 14:12:20 -05:00
if ( ! animAssoc ) {
m_nStoredMoveState = m_nMoveState ;
if ( m_nMoveState = = PEDMOVE_WALK | | m_nMoveState = = PEDMOVE_RUN | | m_nMoveState = = PEDMOVE_SPRINT ) {
for ( CAnimBlendAssociation * assoc = RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) , ASSOC_PARTIAL ) ;
assoc ; assoc = RpAnimBlendGetNextAssociation ( assoc , ASSOC_PARTIAL ) ) {
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
if ( ! ( assoc - > flags & ASSOC_FADEOUTWHENDONE ) ) {
assoc - > blendDelta = - 2.0f ;
assoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
}
2019-10-01 16:33:00 -04:00
2020-11-19 14:12:20 -05:00
ClearAimFlag ( ) ;
ClearLookFlag ( ) ;
}
2019-10-01 16:33:00 -04:00
2020-11-19 14:12:20 -05:00
switch ( m_nMoveState ) {
case PEDMOVE_STILL :
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_IDLE_STANCE , 4.0f ) ;
break ;
case PEDMOVE_WALK :
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_WALK , 1.0f ) ;
break ;
case PEDMOVE_RUN :
if ( m_nPedState = = PED_FLEE_ENTITY ) {
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_RUN , 3.0f ) ;
} else {
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_RUN , 1.0f ) ;
}
break ;
case PEDMOVE_SPRINT :
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , animGroupToUse , ANIM_SPRINT , 1.0f ) ;
break ;
default :
break ;
}
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
if ( animAssoc ) {
if ( m_leader ) {
CAnimBlendAssociation * walkAssoc = RpAnimBlendClumpGetAssociation ( m_leader - > GetClump ( ) , ANIM_WALK ) ;
if ( ! walkAssoc )
walkAssoc = RpAnimBlendClumpGetAssociation ( m_leader - > GetClump ( ) , ANIM_RUN ) ;
2019-06-15 11:53:25 -04:00
2020-11-19 14:12:20 -05:00
if ( ! walkAssoc )
walkAssoc = RpAnimBlendClumpGetAssociation ( m_leader - > GetClump ( ) , ANIM_SPRINT ) ;
if ( walkAssoc ) {
animAssoc - > speed = walkAssoc - > speed ;
} else {
if ( CharCreatedBy = = MISSION_CHAR )
animAssoc - > speed = 1.0f ;
else
animAssoc - > speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX ;
2019-06-15 11:53:25 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
if ( CharCreatedBy = = MISSION_CHAR )
animAssoc - > speed = 1.0f ;
else
animAssoc - > speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX ;
2019-06-15 11:53:25 -04:00
}
}
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : StopNonPartialAnims ( void )
2019-06-15 11:53:25 -04:00
{
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * assoc ;
2019-06-14 08:33:08 -04:00
2020-11-19 14:12:20 -05:00
for ( assoc = RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) ) ; assoc ; assoc = RpAnimBlendGetNextAssociation ( assoc ) ) {
if ( ! assoc - > IsPartial ( ) )
assoc - > flags & = ~ ASSOC_RUNNING ;
2019-06-15 11:53:25 -04:00
}
}
2019-06-16 14:39:48 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : RestartNonPartialAnims ( void )
2019-06-16 14:39:48 -04:00
{
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * assoc ;
for ( assoc = RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) ) ; assoc ; assoc = RpAnimBlendGetNextAssociation ( assoc ) ) {
if ( ! assoc - > IsPartial ( ) )
assoc - > SetRun ( ) ;
2019-06-16 14:39:48 -04:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetStoredState ( void )
2019-06-16 14:39:48 -04:00
{
2020-11-19 14:12:20 -05:00
if ( m_nLastPedState ! = PED_NONE | | ! CanPedReturnToState ( ) )
return ;
2019-06-16 14:39:48 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_WANDER_PATH ) {
bFindNewNodeAfterStateRestore = true ;
if ( m_nMoveState = = PEDMOVE_NONE | | m_nMoveState = = PEDMOVE_STILL )
m_nMoveState = PEDMOVE_WALK ;
}
# ifdef VC_PED_PORTS
if ( m_nPedState ! = PED_IDLE )
# endif
{
m_nLastPedState = m_nPedState ;
if ( m_nMoveState > = m_nPrevMoveState )
m_nPrevMoveState = m_nMoveState ;
}
2019-06-16 14:39:48 -04:00
}
2019-06-15 11:53:25 -04:00
2019-06-17 05:48:42 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : RestorePreviousState ( void )
2019-06-19 08:06:13 -04:00
{
2020-11-19 14:12:20 -05:00
if ( ! CanSetPedState ( ) | | m_nPedState = = PED_FALL )
2019-06-19 08:06:13 -04:00
return ;
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_GETUP & & ! bGetUpAnimStarted )
return ;
2019-06-19 08:06:13 -04:00
2020-11-19 14:12:20 -05:00
if ( InVehicle ( ) ) {
2020-12-14 22:11:02 -05:00
SetPedState ( PED_DRIVING ) ;
2020-11-19 14:12:20 -05:00
m_nLastPedState = PED_NONE ;
} else {
if ( m_nLastPedState = = PED_NONE ) {
if ( ! IsPlayer ( ) & & CharCreatedBy ! = MISSION_CHAR & & m_objective = = OBJECTIVE_NONE ) {
if ( SetWanderPath ( CGeneral : : GetRandomNumber ( ) & 7 ) ! = 0 )
return ;
}
SetIdle ( ) ;
return ;
}
2019-06-17 05:48:42 -04:00
2020-11-19 14:12:20 -05:00
switch ( m_nLastPedState ) {
case PED_IDLE :
SetIdle ( ) ;
break ;
case PED_WANDER_PATH :
2020-12-14 22:11:02 -05:00
SetPedState ( PED_WANDER_PATH ) ;
2020-11-19 14:12:20 -05:00
bIsRunning = false ;
if ( bFindNewNodeAfterStateRestore ) {
if ( m_pNextPathNode ) {
CVector diff = m_pNextPathNode - > GetPosition ( ) - GetPosition ( ) ;
if ( diff . MagnitudeSqr ( ) < sq ( 7.0f ) ) {
SetMoveState ( PEDMOVE_WALK ) ;
break ;
2019-06-17 05:48:42 -04:00
}
}
}
2020-11-19 14:12:20 -05:00
SetWanderPath ( CGeneral : : GetRandomNumber ( ) & 7 ) ;
break ;
default :
2020-12-14 22:11:02 -05:00
SetPedState ( m_nLastPedState ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( ( eMoveState ) m_nPrevMoveState ) ;
break ;
2019-06-17 05:48:42 -04:00
}
2020-11-19 14:12:20 -05:00
m_nLastPedState = PED_NONE ;
2019-06-17 05:48:42 -04:00
}
}
2020-11-19 14:12:20 -05:00
uint32
CPed : : ScanForThreats ( void )
2019-06-20 07:22:44 -04:00
{
2020-11-19 14:12:20 -05:00
int fearFlags = m_fearFlags ;
CVector ourPos = GetPosition ( ) ;
float closestPedDist = 60.0f ;
CVector2D explosionPos = GetPosition ( ) ;
if ( fearFlags & PED_FLAG_EXPLOSION & & CheckForExplosions ( explosionPos ) ) {
m_eventOrThreat = explosionPos ;
return PED_FLAG_EXPLOSION ;
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
CPed * shooter = nil ;
if ( ( fearFlags & PED_FLAG_GUN ) & & ( shooter = CheckForGunShots ( ) ) & & ( m_nPedType ! = shooter - > m_nPedType | | m_nPedType = = PEDTYPE_CIVMALE | | m_nPedType = = PEDTYPE_CIVFEMALE ) ) {
if ( ! IsGangMember ( ) ) {
m_threatEntity = shooter ;
m_threatEntity - > RegisterReference ( ( CEntity * * ) & m_threatEntity ) ;
return PED_FLAG_GUN ;
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( CPedType : : GetFlag ( shooter - > m_nPedType ) & fearFlags ) {
m_threatEntity = shooter ;
m_threatEntity - > RegisterReference ( ( CEntity * * ) & m_threatEntity ) ;
return CPedType : : GetFlag ( shooter - > m_nPedType ) ;
2019-06-20 07:22:44 -04:00
}
}
2020-12-27 09:05:37 -05:00
CPed * deadPed ;
2020-11-19 14:12:20 -05:00
if ( fearFlags & PED_FLAG_DEADPEDS & & CharCreatedBy ! = MISSION_CHAR
2020-12-27 09:05:37 -05:00
& & ( deadPed = CheckForDeadPeds ( ) ) ! = nil & & ( deadPed - > GetPosition ( ) - ourPos ) . MagnitudeSqr ( ) < sq ( 20.0f )
# ifdef FIX_BUGS
& & ! deadPed - > bIsInWater
# endif
) {
2020-11-19 14:12:20 -05:00
m_pEventEntity = deadPed ;
m_pEventEntity - > RegisterReference ( ( CEntity * * ) & m_pEventEntity ) ;
return PED_FLAG_DEADPEDS ;
} else {
2020-12-27 09:05:37 -05:00
uint32 flagsOfNearPed = 0 ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
CPed * pedToFearFrom = nil ;
# ifndef VC_PED_PORTS
for ( int i = 0 ; i < m_numNearPeds ; i + + ) {
if ( CharCreatedBy ! = RANDOM_CHAR | | m_nearPeds [ i ] - > CharCreatedBy ! = MISSION_CHAR | | m_nearPeds [ i ] - > IsPlayer ( ) ) {
CPed * nearPed = m_nearPeds [ i ] ;
2019-06-25 04:40:54 -04:00
2020-11-19 14:12:20 -05:00
// BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance.
// Fixed at the bottom of the function.
2020-12-27 09:05:37 -05:00
flagsOfNearPed = CPedType : : GetFlag ( nearPed - > m_nPedType ) ;
2019-06-25 04:40:54 -04:00
2020-12-27 09:05:37 -05:00
if ( flagsOfNearPed & fearFlags ) {
2020-11-19 14:12:20 -05:00
if ( nearPed - > m_fHealth > 0.0f & & OurPedCanSeeThisOne ( m_nearPeds [ i ] ) ) {
// FIX: Taken from VC
# ifdef FIX_BUGS
float nearPedDistSqr = ( nearPed - > GetPosition ( ) - ourPos ) . MagnitudeSqr2D ( ) ;
# else
float nearPedDistSqr = ( CVector2D ( ourPos ) - explosionPos ) . MagnitudeSqr ( ) ;
# endif
if ( sq ( closestPedDist ) > nearPedDistSqr ) {
closestPedDist = Sqrt ( nearPedDistSqr ) ;
pedToFearFrom = m_nearPeds [ i ] ;
}
}
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
# else
bool weSawOurEnemy = false ;
bool weMaySeeOurEnemy = false ;
float closestEnemyDist = 60.0f ;
if ( ( CTimer : : GetFrameCounter ( ) + ( uint8 ) m_randomSeed + 16 ) & 4 ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < m_numNearPeds ; + + i ) {
if ( CharCreatedBy = = RANDOM_CHAR & & m_nearPeds [ i ] - > CharCreatedBy = = MISSION_CHAR & & ! m_nearPeds [ i ] - > IsPlayer ( ) ) {
continue ;
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
// BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function.
2020-12-27 09:05:37 -05:00
flagsOfNearPed = CPedType : : GetFlag ( m_nearPeds [ i ] - > m_nPedType ) ;
2019-06-20 07:22:44 -04:00
2020-12-27 09:05:37 -05:00
if ( flagsOfNearPed & fearFlags ) {
2020-11-19 14:12:20 -05:00
if ( m_nearPeds [ i ] - > m_fHealth > 0.0f ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
// VC also has ability to include objects to line of sight check here (via last bit of flagsL)
if ( OurPedCanSeeThisOne ( m_nearPeds [ i ] ) ) {
if ( m_nearPeds [ i ] - > m_nPedState = = PED_ATTACK ) {
if ( m_nearPeds [ i ] - > m_pedInObjective = = this ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
float enemyDistSqr = ( m_nearPeds [ i ] - > GetPosition ( ) - ourPos ) . MagnitudeSqr2D ( ) ;
if ( sq ( closestEnemyDist ) > enemyDistSqr ) {
float enemyDist = Sqrt ( enemyDistSqr ) ;
weSawOurEnemy = true ;
closestPedDist = enemyDist ;
closestEnemyDist = enemyDist ;
pedToFearFrom = m_nearPeds [ i ] ;
}
}
} else {
float nearPedDistSqr = ( m_nearPeds [ i ] - > GetPosition ( ) - ourPos ) . MagnitudeSqr2D ( ) ;
if ( sq ( closestPedDist ) > nearPedDistSqr & & ! weSawOurEnemy ) {
closestPedDist = Sqrt ( nearPedDistSqr ) ;
pedToFearFrom = m_nearPeds [ i ] ;
}
}
} else if ( ! weSawOurEnemy ) {
CPed * nearPed = m_nearPeds [ i ] ;
if ( nearPed - > m_nPedState = = PED_ATTACK ) {
CColPoint foundCol ;
CEntity * foundEnt ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
// We don't see him yet but he's behind a ped, vehicle or object
// VC also has ability to include objects to line of sight check here (via last bit of flagsL)
if ( ! CWorld : : ProcessLineOfSight ( ourPos , nearPed - > GetPosition ( ) , foundCol , foundEnt ,
true , false , false , false , false , false , false ) ) {
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( nearPed - > m_pedInObjective = = this ) {
float enemyDistSqr = ( m_nearPeds [ i ] - > GetPosition ( ) - ourPos ) . MagnitudeSqr2D ( ) ;
if ( sq ( closestEnemyDist ) > enemyDistSqr ) {
float enemyDist = Sqrt ( enemyDistSqr ) ;
weMaySeeOurEnemy = true ;
closestPedDist = enemyDist ;
closestEnemyDist = enemyDist ;
pedToFearFrom = m_nearPeds [ i ] ;
}
} else if ( ! nearPed - > GetWeapon ( ) - > IsTypeMelee ( ) & & ! weMaySeeOurEnemy ) {
float nearPedDistSqr = ( m_nearPeds [ i ] - > GetPosition ( ) - ourPos ) . MagnitudeSqr2D ( ) ;
if ( sq ( closestPedDist ) > nearPedDistSqr ) {
weMaySeeOurEnemy = true ;
closestPedDist = Sqrt ( nearPedDistSqr ) ;
pedToFearFrom = m_nearPeds [ i ] ;
}
}
}
}
}
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
}
# endif
int16 lastVehicle ;
CEntity * vehicles [ 8 ] ;
CWorld : : FindObjectsInRange ( ourPos , 20.0f , true , & lastVehicle , 6 , vehicles , false , true , false , false , false ) ;
CVehicle * foundVeh = nil ;
for ( int i = 0 ; i < lastVehicle ; i + + ) {
CVehicle * nearVeh = ( CVehicle * ) vehicles [ i ] ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
CPed * driver = nearVeh - > pDriver ;
if ( driver ) {
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
// BUG: Same bug as above. Fixed at the bottom of function.
2020-12-27 09:05:37 -05:00
flagsOfNearPed = CPedType : : GetFlag ( driver - > m_nPedType ) ;
if ( flagsOfNearPed & fearFlags ) {
2020-11-19 14:12:20 -05:00
if ( driver - > m_fHealth > 0.0f & & OurPedCanSeeThisOne ( nearVeh - > pDriver ) ) {
// FIX: Taken from VC
# ifdef FIX_BUGS
float driverDistSqr = ( driver - > GetPosition ( ) - ourPos ) . MagnitudeSqr2D ( ) ;
# else
float driverDistSqr = ( CVector2D ( ourPos ) - explosionPos ) . MagnitudeSqr ( ) ;
# endif
if ( sq ( closestPedDist ) > driverDistSqr ) {
closestPedDist = Sqrt ( driverDistSqr ) ;
pedToFearFrom = nearVeh - > pDriver ;
}
2019-07-17 22:26:46 -04:00
}
}
2020-11-19 14:12:20 -05:00
}
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
m_threatEntity = pedToFearFrom ;
if ( m_threatEntity )
m_threatEntity - > RegisterReference ( ( CEntity * * ) & m_threatEntity ) ;
2019-06-28 12:19:00 -04:00
2020-11-19 14:12:20 -05:00
# ifdef FIX_BUGS
if ( pedToFearFrom )
2020-12-27 09:05:37 -05:00
flagsOfNearPed = CPedType : : GetFlag ( ( ( CPed * ) m_threatEntity ) - > m_nPedType ) ;
2019-07-17 22:26:46 -04:00
else
2020-12-27 09:05:37 -05:00
flagsOfNearPed = 0 ;
2020-11-19 14:12:20 -05:00
# endif
2019-06-20 07:22:44 -04:00
2020-12-27 09:05:37 -05:00
return flagsOfNearPed ;
2020-11-19 14:12:20 -05:00
}
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetLookFlag ( float direction , bool keepTryingToLook )
{
if ( m_lookTimer < CTimer : : GetTimeInMilliseconds ( ) ) {
bIsLooking = true ;
bIsRestoringLook = false ;
m_pLookTarget = nil ;
m_fLookDirection = direction ;
m_lookTimer = 0 ;
bKeepTryingToLook = keepTryingToLook ;
if ( m_nPedState ! = PED_DRIVING ) {
m_pedIK . m_flags & = ~ CPedIK : : LOOKAROUND_HEAD_ONLY ;
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetLookFlag ( CEntity * target , bool keepTryingToLook )
{
if ( m_lookTimer < CTimer : : GetTimeInMilliseconds ( ) ) {
bIsLooking = true ;
bIsRestoringLook = false ;
m_pLookTarget = target ;
m_pLookTarget - > RegisterReference ( ( CEntity * * ) & m_pLookTarget ) ;
m_fLookDirection = 999999.0f ;
m_lookTimer = 0 ;
bKeepTryingToLook = keepTryingToLook ;
if ( m_nPedState ! = PED_DRIVING ) {
m_pedIK . m_flags & = ~ CPedIK : : LOOKAROUND_HEAD_ONLY ;
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : ClearLookFlag ( void ) {
if ( bIsLooking ) {
bIsLooking = false ;
bIsRestoringLook = true ;
bShakeFist = false ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
m_pedIK . m_flags & = ~ CPedIK : : LOOKAROUND_HEAD_ONLY ;
if ( IsPlayer ( ) )
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 2000 ;
else
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 4000 ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_LOOK_HEADING | | m_nPedState = = PED_LOOK_ENTITY ) {
ClearLook ( ) ;
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
void
FinishFuckUCB ( CAnimBlendAssociation * animAssoc , void * arg )
{
CPed * ped = ( CPed * ) arg ;
if ( animAssoc - > animId = = ANIM_FUCKU & & ped - > GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_UNARMED )
ped - > RemoveWeaponModel ( 0 ) ;
}
void
CPed : : MoveHeadToLook ( void )
{
CVector lookPos ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( m_lookTimer & & CTimer : : GetTimeInMilliseconds ( ) > m_lookTimer ) {
ClearLookFlag ( ) ;
} else if ( m_nPedState = = PED_DRIVING ) {
m_pedIK . m_flags | = CPedIK : : LOOKAROUND_HEAD_ONLY ;
2019-07-17 22:26:46 -04:00
}
2019-06-21 14:16:51 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pLookTarget ) {
if ( ! bShakeFist & & GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_UNARMED ) {
CAnimBlendAssociation * fuckUAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FUCKU ) ;
if ( fuckUAssoc ) {
float animTime = fuckUAssoc - > currentTime ;
if ( animTime > 4.0f / 30.0f & & animTime - fuckUAssoc - > timeStep > 4.0f / 30.0f ) {
bool lookingToCop = false ;
if ( m_pLookTarget - > GetModelIndex ( ) = = MI_POLICE
| | m_pLookTarget - > IsPed ( ) & & ( ( CPed * ) m_pLookTarget ) - > m_nPedType = = PEDTYPE_COP ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
lookingToCop = true ;
}
2019-06-21 14:16:51 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) & & ( m_pedStats - > m_temper > = 52 | | lookingToCop ) ) {
AddWeaponModel ( MI_FINGERS ) ;
( ( CPlayerPed * ) this ) - > AnnoyPlayerPed ( true ) ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
} else if ( ( CGeneral : : GetRandomNumber ( ) & 3 ) = = 0 ) {
AddWeaponModel ( MI_FINGERS ) ;
}
}
}
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pLookTarget - > IsPed ( ) ) {
2020-12-17 19:57:54 -05:00
( ( CPed * ) m_pLookTarget ) - > m_pedIK . GetComponentPosition ( lookPos , PED_MID ) ;
2020-11-19 14:12:20 -05:00
} else {
lookPos = m_pLookTarget - > GetPosition ( ) ;
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ! m_pedIK . LookAtPosition ( lookPos ) ) {
if ( ! bKeepTryingToLook ) {
ClearLookFlag ( ) ;
2019-09-20 15:40:33 -04:00
}
2020-11-19 14:12:20 -05:00
return ;
2019-09-20 15:40:33 -04:00
}
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( ! bShakeFist | | bIsAimingGun | | bIsRestoringGun )
return ;
if ( m_lookTimer - CTimer : : GetTimeInMilliseconds ( ) > = 1000 )
return ;
bool notRocketLauncher = false ;
bool notTwoHanded = false ;
AnimationId animToPlay = NUM_ANIMS ;
if ( ! GetWeapon ( ) - > IsType2Handed ( ) )
notTwoHanded = true ;
if ( notTwoHanded & & GetWeapon ( ) - > m_eWeaponType ! = WEAPONTYPE_ROCKETLAUNCHER )
notRocketLauncher = true ;
if ( IsPlayer ( ) & & notRocketLauncher ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pLookTarget - > IsPed ( ) ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pedStats - > m_temper > = 49 & & ( ( CPed * ) m_pLookTarget ) - > m_nPedType ! = PEDTYPE_COP ) {
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
// FIX: Unreachable and meaningless condition
# ifndef FIX_BUGS
if ( m_pedStats - > m_temper < 47 )
# endif
animToPlay = ANIM_FIGHT_PPUNCH ;
2019-06-20 07:22:44 -04:00
} else {
2020-11-19 14:12:20 -05:00
animToPlay = ANIM_FUCKU ;
2019-06-20 07:22:44 -04:00
}
2020-11-19 14:12:20 -05:00
} else if ( m_pedStats - > m_temper > 49 | | m_pLookTarget - > GetModelIndex ( ) = = MI_POLICE ) {
animToPlay = ANIM_FUCKU ;
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
} else if ( notRocketLauncher & & ( CGeneral : : GetRandomNumber ( ) & 1 ) ) {
animToPlay = ANIM_FUCKU ;
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( animToPlay ! = NUM_ANIMS ) {
CAnimBlendAssociation * newAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , animToPlay , 4.0f ) ;
2019-06-20 07:22:44 -04:00
2020-11-19 14:12:20 -05:00
if ( newAssoc ) {
newAssoc - > flags | = ASSOC_FADEOUTWHENDONE ;
newAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
if ( newAssoc - > animId = = ANIM_FUCKU )
newAssoc - > SetDeleteCallback ( FinishFuckUCB , this ) ;
2019-06-20 07:22:44 -04:00
}
}
2020-11-19 14:12:20 -05:00
bShakeFist = false ;
return ;
} else if ( 999999.0f = = m_fLookDirection ) {
ClearLookFlag ( ) ;
} else if ( ! m_pedIK . LookInDirection ( m_fLookDirection , 0.0f ) ) {
if ( ! bKeepTryingToLook )
ClearLookFlag ( ) ;
2019-06-20 07:22:44 -04:00
}
2019-06-21 14:16:51 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : RestoreHeadPosition ( void )
2019-06-21 14:16:51 -04:00
{
2020-11-19 14:12:20 -05:00
if ( m_pedIK . RestoreLookAt ( ) ) {
bIsRestoringLook = false ;
2019-06-21 14:16:51 -04:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetAimFlag ( float angle )
2019-06-21 14:16:51 -04:00
{
2020-11-19 14:12:20 -05:00
bIsAimingGun = true ;
bIsRestoringGun = false ;
m_fLookDirection = angle ;
m_lookTimer = 0 ;
m_pLookTarget = nil ;
m_pSeekTarget = nil ;
2020-12-26 07:21:45 -05:00
if ( CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) - > IsFlagSet ( WEAPONFLAG_CANAIM_WITHARM ) )
2020-11-19 14:12:20 -05:00
m_pedIK . m_flags | = CPedIK : : AIMS_WITH_ARM ;
else
m_pedIK . m_flags & = ~ CPedIK : : AIMS_WITH_ARM ;
2019-06-21 14:16:51 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetAimFlag ( CEntity * to )
2019-06-21 14:16:51 -04:00
{
2020-11-19 14:12:20 -05:00
bIsAimingGun = true ;
bIsRestoringGun = false ;
m_pLookTarget = to ;
m_pLookTarget - > RegisterReference ( ( CEntity * * ) & m_pLookTarget ) ;
m_pSeekTarget = to ;
m_pSeekTarget - > RegisterReference ( ( CEntity * * ) & m_pSeekTarget ) ;
m_lookTimer = 0 ;
2019-06-21 14:16:51 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : ClearAimFlag ( void )
2019-06-21 14:16:51 -04:00
{
2020-11-19 14:12:20 -05:00
if ( bIsAimingGun ) {
bIsAimingGun = false ;
bIsRestoringGun = true ;
m_pedIK . m_flags & = ~ CPedIK : : AIMS_WITH_ARM ;
# if defined VC_PED_PORTS || defined FIX_BUGS
m_lookTimer = 0 ;
# endif
2019-07-17 22:26:46 -04:00
}
2019-06-21 14:16:51 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) )
( ( CPlayerPed * ) this ) - > m_fFPSMoveHeading = 0.0f ;
2019-06-21 14:16:51 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : AimGun ( void )
2019-06-21 14:16:51 -04:00
{
2020-11-19 14:12:20 -05:00
CVector vector ;
2019-06-21 14:16:51 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pSeekTarget ) {
if ( m_pSeekTarget - > IsPed ( ) ) {
( ( CPed * ) m_pSeekTarget ) - > m_pedIK . GetComponentPosition ( vector , PED_MID ) ;
} else {
vector = m_pSeekTarget - > GetPosition ( ) ;
2019-06-21 14:16:51 -04:00
}
2020-11-19 14:12:20 -05:00
Say ( SOUND_PED_ATTACK ) ;
2019-06-21 14:16:51 -04:00
2020-11-19 14:12:20 -05:00
bCanPointGunAtTarget = m_pedIK . PointGunAtPosition ( vector ) ;
if ( m_pLookTarget ! = m_pSeekTarget ) {
SetLookFlag ( m_pSeekTarget , true ) ;
2019-06-24 10:57:54 -04:00
}
} else {
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) ) {
bCanPointGunAtTarget = m_pedIK . PointGunInDirection ( m_fLookDirection , ( ( CPlayerPed * ) this ) - > m_fFPSMoveHeading ) ;
} else {
bCanPointGunAtTarget = m_pedIK . PointGunInDirection ( m_fLookDirection , 0.0f ) ;
2019-09-26 17:01:50 -04:00
}
}
2019-06-24 10:57:54 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : RestoreGunPosition ( void )
2019-06-24 10:57:54 -04:00
{
2020-11-19 14:12:20 -05:00
if ( bIsLooking ) {
m_pedIK . m_flags & = ~ CPedIK : : LOOKAROUND_HEAD_ONLY ;
bIsRestoringGun = false ;
} else if ( m_pedIK . RestoreGunPosn ( ) ) {
bIsRestoringGun = false ;
} else {
if ( IsPlayer ( ) )
( ( CPlayerPed * ) this ) - > m_fFPSMoveHeading = 0.0f ;
2019-06-24 10:57:54 -04:00
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : ScanForInterestingStuff ( void )
2019-06-24 10:57:54 -04:00
{
2020-11-19 14:12:20 -05:00
if ( ! IsPedInControl ( ) )
return ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective ! = OBJECTIVE_NONE )
return ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( CharCreatedBy = = MISSION_CHAR )
return ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
LookForSexyPeds ( ) ;
LookForSexyCars ( ) ;
if ( LookForInterestingNodes ( ) )
return ;
2019-06-24 10:57:54 -04:00
2021-01-13 07:41:24 -05:00
if ( m_nPedType = = PEDTYPE_CRIMINAL & & m_carJackTimer < CTimer : : GetTimeInMilliseconds ( ) ) {
// Find a car to steal or a ped to mug if we haven't already decided to steal a car
2020-11-19 14:12:20 -05:00
if ( CGeneral : : GetRandomNumber ( ) % 100 < 10 ) {
int mostExpensiveVehAround = - 1 ;
int bestMonetaryValue = 0 ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
CVector pos = GetPosition ( ) ;
int16 lastVehicle ;
CEntity * vehicles [ 8 ] ;
CWorld : : FindObjectsInRange ( pos , 10.0f , true , & lastVehicle , 6 , vehicles , false , true , false , false , false ) ;
2020-04-17 00:01:54 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < lastVehicle ; i + + ) {
CVehicle * veh = ( CVehicle * ) vehicles [ i ] ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( veh - > VehicleCreatedBy ! = MISSION_VEHICLE ) {
if ( veh - > m_vecMoveSpeed . Magnitude ( ) < = 0.1f & & veh - > IsVehicleNormal ( )
& & veh - > IsCar ( ) & & bestMonetaryValue < veh - > pHandling - > nMonetaryValue ) {
mostExpensiveVehAround = i ;
bestMonetaryValue = veh - > pHandling - > nMonetaryValue ;
}
}
}
if ( bestMonetaryValue > 2000 & & mostExpensiveVehAround ! = - 1 & & vehicles [ mostExpensiveVehAround ] ) {
SetObjective ( OBJECTIVE_ENTER_CAR_AS_DRIVER , vehicles [ mostExpensiveVehAround ] ) ;
2021-01-13 07:41:24 -05:00
m_carJackTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
2020-11-19 14:12:20 -05:00
return ;
}
2021-01-13 07:41:24 -05:00
m_carJackTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
2020-11-19 14:12:20 -05:00
} else if ( m_objective ! = OBJECTIVE_MUG_CHAR & & ! ( CGeneral : : GetRandomNumber ( ) & 7 ) ) {
CPed * charToMug = nil ;
for ( int i = 0 ; i < m_numNearPeds ; + + i ) {
CPed * nearPed = m_nearPeds [ i ] ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ( nearPed - > GetPosition ( ) - GetPosition ( ) ) . MagnitudeSqr ( ) > sq ( 7.0f ) )
break ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( ( nearPed - > m_nPedType = = PEDTYPE_CIVFEMALE | | nearPed - > m_nPedType = = PEDTYPE_CIVMALE
| | nearPed - > m_nPedType = = PEDTYPE_CRIMINAL | | nearPed - > m_nPedType = = PEDTYPE_UNUSED1
| | nearPed - > m_nPedType = = PEDTYPE_PROSTITUTE )
& & nearPed - > CharCreatedBy ! = MISSION_CHAR
& & nearPed - > IsPedShootable ( )
& & nearPed - > m_objective ! = OBJECTIVE_MUG_CHAR ) {
charToMug = nearPed ;
break ;
}
}
if ( charToMug )
SetObjective ( OBJECTIVE_MUG_CHAR , charToMug ) ;
2021-01-13 07:41:24 -05:00
m_carJackTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
2019-06-24 10:57:54 -04:00
}
}
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_WANDER_PATH ) {
# ifndef VC_PED_PORTS
2021-01-13 07:41:24 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) > m_chatTimer ) {
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
// += 2 is weird
for ( int i = 0 ; i < m_numNearPeds ; i + = 2 ) {
if ( m_nearPeds [ i ] - > m_nPedState = = PED_WANDER_PATH & & WillChat ( m_nearPeds [ i ] ) ) {
if ( CGeneral : : GetRandomNumberInRange ( 0 , 100 ) > = 100 )
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 30000 ;
2020-11-19 14:12:20 -05:00
else {
if ( ( GetPosition ( ) - m_nearPeds [ i ] - > GetPosition ( ) ) . Magnitude ( ) > = 1.8f ) {
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 30000 ;
2020-11-19 14:12:20 -05:00
} else if ( CanSeeEntity ( m_nearPeds [ i ] ) ) {
int time = CGeneral : : GetRandomNumber ( ) % 4000 + 10000 ;
SetChat ( m_nearPeds [ i ] , time ) ;
m_nearPeds [ i ] - > SetChat ( this , time ) ;
return ;
}
}
}
}
}
# else
if ( CGeneral : : GetRandomNumberInRange ( 0.0f , 1.0f ) < 0.5f ) {
2021-01-13 07:41:24 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) > m_chatTimer ) {
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < m_numNearPeds ; i + + ) {
if ( m_nearPeds [ i ] & & m_nearPeds [ i ] - > m_nPedState = = PED_WANDER_PATH ) {
if ( ( GetPosition ( ) - m_nearPeds [ i ] - > GetPosition ( ) ) . Magnitude ( ) < 1.8f
& & CanSeeEntity ( m_nearPeds [ i ] )
& & m_nearPeds [ i ] - > CanSeeEntity ( this )
& & WillChat ( m_nearPeds [ i ] ) ) {
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
int time = CGeneral : : GetRandomNumber ( ) % 4000 + 10000 ;
SetChat ( m_nearPeds [ i ] , time ) ;
m_nearPeds [ i ] - > SetChat ( this , time ) ;
return ;
}
}
}
}
} else {
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 200 ;
2020-11-19 14:12:20 -05:00
}
# endif
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
// Parts below aren't there in VC, they're in somewhere else.
if ( ! CGame : : noProstitutes & & m_nPedType = = PEDTYPE_PROSTITUTE & & CharCreatedBy ! = MISSION_CHAR
& & m_objectiveTimer < CTimer : : GetTimeInMilliseconds ( ) & & ! CTheScripts : : IsPlayerOnAMission ( ) ) {
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
CVector pos = GetPosition ( ) ;
int16 lastVehicle ;
CEntity * vehicles [ 8 ] ;
CWorld : : FindObjectsInRange ( pos , CHECK_NEARBY_THINGS_MAX_DIST , true , & lastVehicle , 6 , vehicles , false , true , false , false , false ) ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < lastVehicle ; i + + ) {
CVehicle * veh = ( CVehicle * ) vehicles [ i ] ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( veh - > IsVehicleNormal ( ) ) {
if ( veh - > IsCar ( ) ) {
if ( ( GetPosition ( ) - veh - > GetPosition ( ) ) . Magnitude ( ) < 5.0f & & veh - > IsRoomForPedToLeaveCar ( CAR_DOOR_LF , nil ) ) {
SetObjective ( OBJECTIVE_SOLICIT_VEHICLE , veh ) ;
Say ( SOUND_PED_SOLICIT ) ;
return ;
}
}
}
2019-06-24 10:57:54 -04:00
}
}
2020-11-19 14:12:20 -05:00
if ( m_nPedType = = PEDTYPE_CIVMALE | | m_nPedType = = PEDTYPE_CIVFEMALE ) {
CVector pos = GetPosition ( ) ;
int16 lastVehicle ;
CEntity * vehicles [ 8 ] ;
CWorld : : FindObjectsInRange ( pos , CHECK_NEARBY_THINGS_MAX_DIST , true , & lastVehicle , 6 , vehicles , false , true , false , false , false ) ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < lastVehicle ; i + + ) {
CVehicle * veh = ( CVehicle * ) vehicles [ i ] ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( veh - > GetModelIndex ( ) = = MI_MRWHOOP ) {
if ( veh - > GetStatus ( ) ! = STATUS_ABANDONED & & veh - > GetStatus ( ) ! = STATUS_WRECKED ) {
if ( ( GetPosition ( ) - veh - > GetPosition ( ) ) . Magnitude ( ) < 5.0f ) {
SetObjective ( OBJECTIVE_BUY_ICE_CREAM , veh ) ;
return ;
}
}
}
}
}
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
bool
CPed : : WillChat ( CPed * stranger )
2019-06-24 10:57:54 -04:00
{
2020-11-19 14:12:20 -05:00
if ( m_pNextPathNode & & m_pLastPathNode ) {
if ( m_pNextPathNode ! = m_pLastPathNode & & ThePaths . TestCrossesRoad ( m_pNextPathNode , m_pLastPathNode ) ) {
return false ;
2019-06-24 10:57:54 -04:00
}
}
2020-11-19 14:12:20 -05:00
if ( m_nSurfaceTouched = = SURFACE_TARMAC )
return false ;
if ( stranger = = this )
return false ;
if ( m_nPedType = = stranger - > m_nPedType )
return true ;
if ( m_nPedType = = PEDTYPE_CRIMINAL )
return false ;
if ( ( IsGangMember ( ) | | stranger - > IsGangMember ( ) ) & & m_nPedType ! = stranger - > m_nPedType )
return false ;
return true ;
}
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : CalculateNewVelocity ( void )
{
if ( IsPedInControl ( ) ) {
float headAmount = DEGTORAD ( m_headingRate ) * CTimer : : GetTimeStep ( ) ;
m_fRotationCur = CGeneral : : LimitRadianAngle ( m_fRotationCur ) ;
float limitedRotDest = CGeneral : : LimitRadianAngle ( m_fRotationDest ) ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( m_fRotationCur - PI > limitedRotDest ) {
limitedRotDest + = 2 * PI ;
} else if ( PI + m_fRotationCur < limitedRotDest ) {
limitedRotDest - = 2 * PI ;
2019-06-24 10:57:54 -04:00
}
2019-07-29 08:01:44 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) & & m_nPedState = = PED_ATTACK )
headAmount / = 4.0f ;
float neededTurn = limitedRotDest - m_fRotationCur ;
if ( neededTurn < = headAmount ) {
if ( neededTurn > ( - headAmount ) )
m_fRotationCur + = neededTurn ;
else
m_fRotationCur - = headAmount ;
2019-07-29 08:01:44 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_fRotationCur + = headAmount ;
2019-07-29 08:01:44 -04:00
}
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
CVector2D forward ( Sin ( m_fRotationCur ) , Cos ( m_fRotationCur ) ) ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
m_moved . x = CrossProduct2D ( m_vecAnimMoveDelta , forward ) ; // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y;
m_moved . y = DotProduct2D ( m_vecAnimMoveDelta , forward ) ; // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur));
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeStep ( ) > = 0.01f ) {
m_moved = m_moved * ( 1 / CTimer : : GetTimeStep ( ) ) ;
2019-06-24 10:57:54 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_moved = m_moved * ( 1 / 100.0f ) ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ( ! TheCamera . Cams [ TheCamera . ActiveCam ] . GetWeaponFirstPersonOn ( ) & & ! TheCamera . Cams [ 0 ] . Using3rdPersonMouseCam ( ) )
| | FindPlayerPed ( ) ! = this | | ! CanStrafeOrMouseControl ( ) )
return ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
float walkAngle = WorkOutHeadingForMovingFirstPerson ( m_fRotationCur ) ;
float pedSpeed = m_moved . Magnitude ( ) ;
float localWalkAngle = CGeneral : : LimitRadianAngle ( walkAngle - m_fRotationCur ) ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( localWalkAngle < - 0.5f * PI ) {
localWalkAngle + = PI ;
} else if ( localWalkAngle > 0.5f * PI ) {
localWalkAngle - = PI ;
}
2019-06-25 04:40:54 -04:00
2020-11-19 14:12:20 -05:00
// Interestingly this part is responsible for diagonal walking.
if ( localWalkAngle > - DEGTORAD ( 50.0f ) & & localWalkAngle < DEGTORAD ( 50.0f ) ) {
TheCamera . Cams [ TheCamera . ActiveCam ] . m_fPlayerVelocity = pedSpeed ;
m_moved = CVector2D ( - Sin ( walkAngle ) , Cos ( walkAngle ) ) * pedSpeed ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * idleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_STANCE ) ;
CAnimBlendAssociation * fightAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FIGHT_IDLE ) ;
2019-09-26 17:01:50 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
if ( ( ! idleAssoc | | idleAssoc - > blendAmount < 0.5f ) & & ! fightAssoc & & ! bIsDucking ) {
# else
if ( ( ! idleAssoc | | idleAssoc - > blendAmount < 0.5f ) & & ! fightAssoc ) {
2019-09-26 17:01:50 -04:00
# endif
2020-11-19 14:12:20 -05:00
LimbOrientation newUpperLegs ;
newUpperLegs . yaw = localWalkAngle ;
if ( newUpperLegs . yaw < - DEGTORAD ( 100.0f ) ) {
newUpperLegs . yaw + = PI ;
} else if ( newUpperLegs . yaw > DEGTORAD ( 100.0f ) ) {
newUpperLegs . yaw - = PI ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
if ( newUpperLegs . yaw > - DEGTORAD ( 50.0f ) & & newUpperLegs . yaw < DEGTORAD ( 50.0f ) ) {
# ifdef PED_SKIN
if ( IsClumpSkinned ( GetClump ( ) ) ) {
/*
// this looks shit
newUpperLegs . pitch = 0.0f ;
RwV3d axis = { - 1.0f , 0.0f , 0.0f } ;
RtQuatRotate ( & m_pFrames [ PED_UPPERLEGL ] - > hanimFrame - > q , & axis , RADTODEG ( newUpperLegs . yaw ) , rwCOMBINEPRECONCAT ) ;
RtQuatRotate ( & m_pFrames [ PED_UPPERLEGR ] - > hanimFrame - > q , & axis , RADTODEG ( newUpperLegs . yaw ) , rwCOMBINEPRECONCAT ) ;
*/
newUpperLegs . pitch = 0.1f ;
RwV3d Xaxis = { 1.0f , 0.0f , 0.0f } ;
RwV3d Zaxis = { 0.0f , 0.0f , 1.0f } ;
RtQuatRotate ( & m_pFrames [ PED_UPPERLEGL ] - > hanimFrame - > q , & Zaxis , RADTODEG ( newUpperLegs . pitch ) , rwCOMBINEPOSTCONCAT ) ;
RtQuatRotate ( & m_pFrames [ PED_UPPERLEGL ] - > hanimFrame - > q , & Xaxis , RADTODEG ( newUpperLegs . yaw ) , rwCOMBINEPOSTCONCAT ) ;
RtQuatRotate ( & m_pFrames [ PED_UPPERLEGR ] - > hanimFrame - > q , & Zaxis , RADTODEG ( newUpperLegs . pitch ) , rwCOMBINEPOSTCONCAT ) ;
RtQuatRotate ( & m_pFrames [ PED_UPPERLEGR ] - > hanimFrame - > q , & Xaxis , RADTODEG ( newUpperLegs . yaw ) , rwCOMBINEPOSTCONCAT ) ;
bDontAcceptIKLookAts = true ;
} else
2019-09-26 17:01:50 -04:00
# endif
2020-11-19 14:12:20 -05:00
{
newUpperLegs . pitch = 0.0f ;
m_pedIK . RotateTorso ( m_pFrames [ PED_UPPERLEGL ] , & newUpperLegs , false ) ;
m_pedIK . RotateTorso ( m_pFrames [ PED_UPPERLEGR ] , & newUpperLegs , false ) ;
2019-06-24 10:57:54 -04:00
}
}
}
2020-11-19 14:12:20 -05:00
}
float
CPed : : WorkOutHeadingForMovingFirstPerson ( float offset )
{
if ( ! IsPlayer ( ) )
return 0.0f ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
CPad * pad0 = CPad : : GetPad ( 0 ) ;
float leftRight = pad0 - > GetPedWalkLeftRight ( ) ;
float upDown = pad0 - > GetPedWalkUpDown ( ) ;
float & angle = ( ( CPlayerPed * ) this ) - > m_fWalkAngle ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( upDown ! = 0.0f ) {
angle = CGeneral : : GetRadianAngleBetweenPoints ( 0.0f , 0.0f , - leftRight , upDown ) ;
2019-06-24 10:57:54 -04:00
} else {
2020-11-19 14:12:20 -05:00
if ( leftRight < 0.0f )
angle = 0.5f * PI ;
else if ( leftRight > 0.0f )
angle = - 0.5f * PI ;
}
return CGeneral : : LimitRadianAngle ( offset + angle ) ;
}
void
CPed : : UpdatePosition ( void )
{
if ( CReplay : : IsPlayingBack ( ) | | ! bIsStanding )
return ;
CVector2D velocityChange ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
SetHeading ( m_fRotationCur ) ;
if ( m_pCurrentPhysSurface ) {
CVector2D velocityOfSurface ;
if ( ! IsPlayer ( ) & & m_pCurrentPhysSurface - > IsVehicle ( ) & & ( ( CVehicle * ) m_pCurrentPhysSurface ) - > IsBoat ( ) ) {
// It seems R* didn't like m_vecOffsetFromPhysSurface for boats
CVector offsetToSurface = GetPosition ( ) - m_pCurrentPhysSurface - > GetPosition ( ) ;
offsetToSurface . z - = FEET_OFFSET ;
CVector surfaceMoveVelocity = m_pCurrentPhysSurface - > m_vecMoveSpeed ;
CVector surfaceTurnVelocity = CrossProduct ( m_pCurrentPhysSurface - > m_vecTurnSpeed , offsetToSurface ) ;
// Also we use that weird formula instead of friction if it's boat
float slideMult = - m_pCurrentPhysSurface - > m_vecTurnSpeed . MagnitudeSqr ( ) ;
velocityOfSurface = slideMult * offsetToSurface * CTimer : : GetTimeStep ( ) + ( surfaceTurnVelocity + surfaceMoveVelocity ) ;
m_vecMoveSpeed . z = slideMult * offsetToSurface . z * CTimer : : GetTimeStep ( ) + ( surfaceTurnVelocity . z + surfaceMoveVelocity . z ) ;
} else {
velocityOfSurface = m_pCurrentPhysSurface - > GetSpeed ( m_vecOffsetFromPhysSurface ) ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
// Reminder: m_moved is displacement from walking/running.
velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed ;
m_fRotationCur + = m_pCurrentPhysSurface - > m_vecTurnSpeed . z * CTimer : : GetTimeStep ( ) ;
m_fRotationDest + = m_pCurrentPhysSurface - > m_vecTurnSpeed . z * CTimer : : GetTimeStep ( ) ;
} else if ( m_nSurfaceTouched = = SURFACE_STEEP_CLIFF & & ( m_vecDamageNormal . x ! = 0.0f | | m_vecDamageNormal . y ! = 0.0f ) ) {
// Ped got damaged by steep slope
m_vecMoveSpeed = CVector ( 0.0f , 0.0f , - 0.001f ) ;
// some kind of
CVector2D reactionForce = m_vecDamageNormal ;
reactionForce . Normalise ( ) ;
2020-02-02 08:51:33 -05:00
2020-11-19 14:12:20 -05:00
velocityChange = 0.02f * reactionForce + m_moved ;
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
float reactionAndVelocityDotProd = DotProduct2D ( reactionForce , velocityChange ) ;
// they're in same direction
if ( reactionAndVelocityDotProd < 0.0f ) {
velocityChange - = reactionAndVelocityDotProd * reactionForce ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
velocityChange = m_moved - m_vecMoveSpeed ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
// Take time step into account
if ( m_pCurrentPhysSurface ) {
float speedChange = velocityChange . Magnitude ( ) ;
float changeMult = speedChange ;
if ( m_nPedState = = PED_DIE & & m_pCurrentPhysSurface - > IsVehicle ( ) ) {
changeMult = 0.002f * CTimer : : GetTimeStep ( ) ;
} else if ( ! ( m_pCurrentPhysSurface - > IsVehicle ( ) & & ( ( CVehicle * ) m_pCurrentPhysSurface ) - > IsBoat ( ) ) ) {
changeMult = 0.01f * CTimer : : GetTimeStep ( ) ;
}
2019-06-24 10:57:54 -04:00
2020-11-19 14:12:20 -05:00
if ( speedChange > changeMult ) {
velocityChange = velocityChange * ( changeMult / speedChange ) ;
}
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
m_vecMoveSpeed . x + = velocityChange . x ;
m_vecMoveSpeed . y + = velocityChange . y ;
}
void
CPed : : CalculateNewOrientation ( void )
{
if ( CReplay : : IsPlayingBack ( ) | | ! IsPedInControl ( ) )
return ;
2019-06-25 04:40:54 -04:00
2020-11-19 14:12:20 -05:00
SetHeading ( m_fRotationCur ) ;
2019-06-24 10:57:54 -04:00
}
2020-11-19 14:12:20 -05:00
void
CPed : : ClearAll ( void )
2019-06-28 12:19:00 -04:00
{
2020-11-19 14:12:20 -05:00
if ( ! IsPedInControl ( ) & & m_nPedState ! = PED_DEAD )
return ;
2019-06-28 12:19:00 -04:00
2020-12-14 22:11:02 -05:00
SetPedState ( PED_NONE ) ;
SetMoveState ( PEDMOVE_NONE ) ;
2020-11-19 14:12:20 -05:00
m_pSeekTarget = nil ;
m_vecSeekPos = CVector ( 0.0f , 0.0f , 0.0f ) ;
m_fleeFromPosX = 0.0f ;
m_fleeFromPosY = 0.0f ;
m_fleeFrom = nil ;
m_fleeTimer = 0 ;
bUsesCollision = true ;
# ifdef VC_PED_PORTS
ClearPointGunAt ( ) ;
2020-04-23 04:24:03 -04:00
# else
2020-11-19 14:12:20 -05:00
ClearAimFlag ( ) ;
ClearLookFlag ( ) ;
2020-04-23 04:24:03 -04:00
# endif
2020-11-19 14:12:20 -05:00
bIsPointingGunAt = false ;
bRenderPedInCar = true ;
bKnockedUpIntoAir = false ;
m_pCollidingEntity = nil ;
2019-06-28 12:19:00 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : ProcessBuoyancy ( void )
2019-06-28 12:19:00 -04:00
{
2020-11-19 14:12:20 -05:00
static uint32 nGenerateRaindrops = 0 ;
static uint32 nGenerateWaterCircles = 0 ;
CRGBA color ( ( ( 0.5f * CTimeCycle : : GetDirectionalRed ( ) + CTimeCycle : : GetAmbientRed ( ) ) * 127.5f ) ,
( ( 0.5f * CTimeCycle : : GetDirectionalBlue ( ) + CTimeCycle : : GetAmbientBlue ( ) ) * 127.5f ) ,
( ( 0.5f * CTimeCycle : : GetDirectionalGreen ( ) + CTimeCycle : : GetAmbientGreen ( ) ) * 127.5f ) ,
2021-01-28 19:32:21 -05:00
CGeneral : : GetRandomNumberInRange ( 48.0f , 96.0f ) ) ;
2019-06-28 12:19:00 -04:00
2020-11-19 14:12:20 -05:00
if ( bInVehicle )
2019-06-28 12:19:00 -04:00
return ;
2020-11-19 14:12:20 -05:00
CVector buoyancyPoint ;
CVector buoyancyImpulse ;
2019-06-28 12:19:00 -04:00
2020-11-19 14:12:20 -05:00
# ifndef VC_PED_PORTS
float buoyancyLevel = ( m_nPedState = = PED_DEAD ? 1.5f : 1.3f ) ;
# else
float buoyancyLevel = ( m_nPedState = = PED_DEAD ? 1.8f : 1.1f ) ;
# endif
2019-06-28 12:19:00 -04:00
2020-11-19 14:12:20 -05:00
if ( mod_Buoyancy . ProcessBuoyancy ( this , GRAVITY * m_fMass * buoyancyLevel , & buoyancyPoint , & buoyancyImpulse ) ) {
bTouchingWater = true ;
CEntity * entity ;
CColPoint point ;
if ( CWorld : : ProcessVerticalLine ( GetPosition ( ) , GetPosition ( ) . z - 3.0f , point , entity , false , true , false , false , false , false , nil )
& & entity - > IsVehicle ( ) & & ( ( CVehicle * ) entity ) - > IsBoat ( ) ) {
bIsInWater = false ;
return ;
2020-04-23 04:24:03 -04:00
}
2020-11-19 14:12:20 -05:00
bIsInWater = true ;
ApplyMoveForce ( buoyancyImpulse ) ;
if ( ! DyingOrDead ( ) ) {
if ( bTryingToReachDryLand ) {
if ( buoyancyImpulse . z / m_fMass > GRAVITY * 0.4f * CTimer : : GetTimeStep ( ) ) {
bTryingToReachDryLand = false ;
CVector pos = GetPosition ( ) ;
if ( PlacePedOnDryLand ( ) ) {
if ( m_fHealth > 20.0f )
InflictDamage ( nil , WEAPONTYPE_DROWNING , 15.0f , PEDPIECE_TORSO , false ) ;
2020-04-23 04:24:03 -04:00
2020-11-19 14:12:20 -05:00
if ( bIsInTheAir ) {
RpAnimBlendClumpSetBlendDeltas ( GetClump ( ) , ASSOC_PARTIAL , - 1000.0f ) ;
bIsInTheAir = false ;
}
pos . z = pos . z - 0.8f ;
# ifdef PC_PARTICLE
CParticleObject : : AddObject ( POBJECT_PED_WATER_SPLASH , pos , CVector ( 0.0f , 0.0f , 0.0f ) , 0.0f , 50 , color , true ) ;
# else
CParticleObject : : AddObject ( POBJECT_PED_WATER_SPLASH , pos , CVector ( 0.0f , 0.0f , 0.0f ) , 0.0f , 50 , CRGBA ( 0 , 0 , 0 , 0 ) , true ) ;
2020-04-23 04:24:03 -04:00
# endif
2020-11-19 14:12:20 -05:00
m_vecMoveSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_IDLE ) ;
2020-11-19 14:12:20 -05:00
return ;
}
2019-06-28 12:19:00 -04:00
}
}
2020-11-19 14:12:20 -05:00
float speedMult = 0.0f ;
if ( buoyancyImpulse . z / m_fMass > GRAVITY * 0.75f * CTimer : : GetTimeStep ( )
| | mod_Buoyancy . m_waterlevel > GetPosition ( ) . z ) {
speedMult = pow ( 0.9f , CTimer : : GetTimeStep ( ) ) ;
m_vecMoveSpeed . x * = speedMult ;
m_vecMoveSpeed . y * = speedMult ;
m_vecMoveSpeed . z * = speedMult ;
bIsStanding = false ;
InflictDamage ( nil , WEAPONTYPE_DROWNING , 3.0f * CTimer : : GetTimeStep ( ) , PEDPIECE_TORSO , 0 ) ;
2020-04-23 04:24:03 -04:00
}
2020-11-19 14:12:20 -05:00
if ( buoyancyImpulse . z / m_fMass > GRAVITY * 0.25f * CTimer : : GetTimeStep ( ) ) {
if ( speedMult = = 0.0f ) {
speedMult = pow ( 0.9f , CTimer : : GetTimeStep ( ) ) ;
}
m_vecMoveSpeed . x * = speedMult ;
m_vecMoveSpeed . y * = speedMult ;
if ( m_vecMoveSpeed . z > = - 0.1f ) {
if ( m_vecMoveSpeed . z < - 0.04f )
m_vecMoveSpeed . z = - 0.02f ;
} else {
m_vecMoveSpeed . z = - 0.01f ;
DMAudio . PlayOneShot ( m_audioEntityId , SOUND_SPLASH , 0.0f ) ;
2020-04-23 04:24:03 -04:00
# ifdef PC_PARTICLE
2020-11-19 14:12:20 -05:00
CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition ( ) ;
float level = 0.0f ;
if ( CWaterLevel : : GetWaterLevel ( aBitForward , & level , false ) )
aBitForward . z = level ;
CParticleObject : : AddObject ( POBJECT_PED_WATER_SPLASH , aBitForward , CVector ( 0.0f , 0.0f , 0.1f ) , 0.0f , 200 , color , true ) ;
nGenerateRaindrops = CTimer : : GetTimeInMilliseconds ( ) + 80 ;
nGenerateWaterCircles = CTimer : : GetTimeInMilliseconds ( ) + 100 ;
2020-04-23 04:24:03 -04:00
# else
2020-11-19 14:12:20 -05:00
CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition ( ) ;
float level = 0.0f ;
if ( CWaterLevel : : GetWaterLevel ( aBitForward , & level , false ) )
aBitForward . z = level + 0.5f ;
CVector vel = m_vecMoveSpeed * 0.1f ;
vel . z = 0.18f ;
CParticleObject : : AddObject ( POBJECT_PED_WATER_SPLASH , aBitForward , vel , 0.0f , 350 , CRGBA ( 0 , 0 , 0 , 0 ) , true ) ;
nGenerateRaindrops = CTimer : : GetTimeInMilliseconds ( ) + 300 ;
nGenerateWaterCircles = CTimer : : GetTimeInMilliseconds ( ) + 60 ;
2020-04-23 04:24:03 -04:00
# endif
2020-11-19 14:12:20 -05:00
}
2019-06-28 12:19:00 -04:00
}
2020-11-19 14:12:20 -05:00
} else
return ;
} else
bTouchingWater = false ;
2019-06-28 12:19:00 -04:00
2020-11-19 14:12:20 -05:00
if ( nGenerateWaterCircles & & CTimer : : GetTimeInMilliseconds ( ) > = nGenerateWaterCircles ) {
CVector pos = GetPosition ( ) ;
float level = 0.0f ;
if ( CWaterLevel : : GetWaterLevel ( pos , & level , false ) )
pos . z = level ;
2019-06-28 12:19:00 -04:00
2020-11-19 14:12:20 -05:00
if ( pos . z ! = 0.0f ) {
nGenerateWaterCircles = 0 ;
for ( int i = 0 ; i < 4 ; i + + ) {
# ifdef PC_PARTICLE
pos . x + = CGeneral : : GetRandomNumberInRange ( - 0.75f , 0.75f ) ;
pos . y + = CGeneral : : GetRandomNumberInRange ( - 0.75f , 0.75f ) ;
CParticle : : AddParticle ( PARTICLE_RAIN_SPLASH_BIGGROW , pos , CVector ( 0.0f , 0.0f , 0.0f ) , nil , 0.0f , color , 0 , 0 , 0 , 0 ) ;
2020-04-23 04:24:03 -04:00
# else
2020-11-19 14:12:20 -05:00
pos . x + = CGeneral : : GetRandomNumberInRange ( - 2.5f , 2.5f ) ;
pos . y + = CGeneral : : GetRandomNumberInRange ( - 2.5f , 2.5f ) ;
CParticle : : AddParticle ( PARTICLE_RAIN_SPLASH_BIGGROW , pos + CVector ( 0.0f , 0.0f , 1.0f ) , CVector ( 0.0f , 0.0f , 0.0f ) ) ;
2020-04-23 04:24:03 -04:00
# endif
2020-11-19 14:12:20 -05:00
}
2019-06-28 12:19:00 -04:00
}
}
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
if ( nGenerateRaindrops & & CTimer : : GetTimeInMilliseconds ( ) > = nGenerateRaindrops ) {
CVector pos = GetPosition ( ) ;
float level = 0.0f ;
if ( CWaterLevel : : GetWaterLevel ( pos , & level , false ) )
pos . z = level ;
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
if ( pos . z > = 0.0f ) {
# ifdef PC_PARTICLE
pos . z + = 0.25f ;
# else
pos . z + = 0.5f ;
# endif
nGenerateRaindrops = 0 ;
# ifdef PC_PARTICLE
CParticleObject : : AddObject ( POBJECT_SPLASHES_AROUND , pos , CVector ( 0.0f , 0.0f , 0.0f ) , 4.5f , 1500 , CRGBA ( 0 , 0 , 0 , 0 ) , true ) ;
# else
CParticleObject : : AddObject ( POBJECT_SPLASHES_AROUND , pos , CVector ( 0.0f , 0.0f , 0.0f ) , 4.5f , 2500 , CRGBA ( 0 , 0 , 0 , 0 ) , true ) ;
# endif
}
}
2019-06-30 17:50:40 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : ProcessControl ( void )
2019-06-30 17:50:40 -04:00
{
2020-11-19 14:12:20 -05:00
CColPoint foundCol ;
CEntity * foundEnt = nil ;
if ( m_nZoneLevel > LEVEL_GENERIC & & m_nZoneLevel ! = CCollision : : ms_collisionInMemory )
2019-06-30 17:50:40 -04:00
return ;
2020-11-19 14:12:20 -05:00
int alpha = CVisibilityPlugins : : GetClumpAlpha ( GetClump ( ) ) ;
if ( ! bFadeOut ) {
if ( alpha < 255 ) {
alpha + = 16 ;
if ( alpha > 255 )
alpha = 255 ;
}
} else {
alpha - = 8 ;
if ( alpha < 0 )
alpha = 0 ;
}
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
CVisibilityPlugins : : SetClumpAlpha ( GetClump ( ) , alpha ) ;
bIsShooting = false ;
BuildPedLists ( ) ;
bIsInWater = false ;
ProcessBuoyancy ( ) ;
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_ARRESTED ) {
if ( m_nPedState = = PED_DEAD ) {
DeadPedMakesTyresBloody ( ) ;
# ifndef VC_PED_PORTS
if ( CGame : : nastyGame ) {
# else
if ( CGame : : nastyGame & & ! bIsInWater ) {
# endif
uint32 remainingBloodyFpTime = CTimer : : GetTimeInMilliseconds ( ) - m_bloodyFootprintCountOrDeathTime ;
float timeDependentDist ;
if ( remainingBloodyFpTime > = 2000 ) {
if ( remainingBloodyFpTime < = 7000 )
timeDependentDist = ( remainingBloodyFpTime - 2000 ) / 5000.0f * 0.75f ;
else
timeDependentDist = 0.75f ;
} else {
timeDependentDist = 0.0f ;
}
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < m_numNearPeds ; + + i ) {
CPed * nearPed = m_nearPeds [ i ] ;
if ( ! nearPed - > DyingOrDead ( ) ) {
CVector dist = nearPed - > GetPosition ( ) - GetPosition ( ) ;
if ( dist . MagnitudeSqr ( ) < sq ( timeDependentDist ) ) {
nearPed - > m_bloodyFootprintCountOrDeathTime = 200 ;
nearPed - > bDoBloodyFootprints = true ;
if ( nearPed - > IsPlayer ( ) ) {
if ( ! nearPed - > bIsLooking & & nearPed - > m_nPedState ! = PED_ATTACK ) {
int16 camMode = TheCamera . Cams [ TheCamera . ActiveCam ] . Mode ;
if ( camMode ! = CCam : : MODE_SNIPER
& & camMode ! = CCam : : MODE_ROCKETLAUNCHER
& & camMode ! = CCam : : MODE_M16_1STPERSON
& & camMode ! = CCam : : MODE_1STPERSON
& & camMode ! = CCam : : MODE_HELICANNON_1STPERSON
& & ! TheCamera . Cams [ TheCamera . ActiveCam ] . GetWeaponFirstPersonOn ( ) ) {
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
nearPed - > SetLookFlag ( this , true ) ;
nearPed - > SetLookTimer ( 500 ) ;
}
}
}
}
}
}
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
if ( remainingBloodyFpTime > 2000 ) {
CVector bloodPos = GetPosition ( ) ;
if ( remainingBloodyFpTime - 2000 > = 5000 ) {
if ( ! m_deadBleeding ) {
CShadows : : AddPermanentShadow ( SHADOWTYPE_DARK , gpBloodPoolTex , & bloodPos ,
0.75f , 0.0f , 0.0f , - 0.75f , 255 , 255 , 0 , 0 , 4.0f , 40000 , 1.0f ) ;
m_deadBleeding = true ;
2019-06-30 17:50:40 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
CShadows : : StoreStaticShadow (
( uintptr ) this + 17 , SHADOWTYPE_DARK , gpBloodPoolTex , & bloodPos ,
( remainingBloodyFpTime - 2000 ) / 5000.0f * 0.75f , 0.0f ,
0.0f , ( remainingBloodyFpTime - 2000 ) / 5000.0f * - 0.75f ,
255 , 255 , 0 , 0 , 4.0f , 1.0f , 40.0f , false , 0.0f ) ;
2019-06-30 17:50:40 -04:00
}
}
}
2020-11-19 14:12:20 -05:00
if ( ServiceTalkingWhenDead ( ) )
ServiceTalking ( ) ;
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
# ifdef VC_PED_PORTS
if ( bIsInWater ) {
bIsStanding = false ;
bWasStanding = false ;
CPhysical : : ProcessControl ( ) ;
2020-11-18 06:38:47 -05:00
}
2020-11-19 14:12:20 -05:00
# endif
return ;
}
bWasStanding = false ;
if ( bIsStanding ) {
if ( ! CWorld : : bForceProcessControl ) {
if ( m_pCurrentPhysSurface & & m_pCurrentPhysSurface - > bIsInSafePosition ) {
bWasPostponed = true ;
return ;
2020-11-18 06:38:47 -05:00
}
2020-11-19 14:12:20 -05:00
}
2020-11-18 06:38:47 -05:00
}
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
if ( ! IsPedInControl ( ) | | m_nWaitState ! = WAITSTATE_FALSE | | 0.01f * CTimer : : GetTimeStep ( ) < = m_fDistanceTravelled
| | ( m_nStoredMoveState ! = PEDMOVE_WALK & & m_nStoredMoveState ! = PEDMOVE_RUN & & m_nStoredMoveState ! = PEDMOVE_SPRINT ) )
m_panicCounter = 0 ;
else if ( m_panicCounter < 50 )
+ + m_panicCounter ;
2019-06-30 17:50:40 -04:00
2020-11-19 14:12:20 -05:00
if ( m_fHealth < = 1.0f & & m_nPedState < = PED_STATES_NO_AI & & ! bIsInTheAir & & ! bIsLanding )
SetDie ( ANIM_KO_SHOT_FRONT1 , 4.0f , 0.0f ) ;
2019-07-01 12:26:46 -04:00
2020-11-19 14:12:20 -05:00
bCollidedWithMyVehicle = false ;
2020-04-23 16:25:18 -04:00
2020-11-19 14:12:20 -05:00
CEntity * collidingEnt = m_pDamageEntity ;
# ifndef VC_PED_PORTS
if ( ! bUsesCollision | | m_fDamageImpulse < = 0.0f | | m_nPedState = = PED_DIE | | ! collidingEnt ) {
# else
if ( ! bUsesCollision | | ( ( ! collidingEnt | | m_fDamageImpulse < = 0.0f ) & & ( ! IsPlayer ( ) | | ! bIsStuck ) ) | | m_nPedState = = PED_DIE ) {
2020-04-23 16:25:18 -04:00
# endif
2020-11-19 14:12:20 -05:00
bHitSomethingLastFrame = false ;
if ( m_nPedStateTimer < = 500 & & bIsInTheAir ) {
if ( m_nPedStateTimer )
m_nPedStateTimer - - ;
} else if ( m_nPedStateTimer < 1001 ) {
m_nPedStateTimer = 0 ;
}
} else {
if ( m_panicCounter = = 50 & & IsPedInControl ( ) ) {
SetWaitState ( WAITSTATE_STUCK , nil ) ;
// Leftover
/*
if ( m_nPedType < PEDTYPE_COP ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else {
2019-07-10 02:06:43 -04:00
2020-11-19 14:12:20 -05:00
}
*/
# ifndef VC_PED_PORTS
} else {
# else
} else if ( collidingEnt ) {
2019-08-16 12:25:02 -04:00
# endif
2020-11-19 14:12:20 -05:00
switch ( collidingEnt - > GetType ( ) )
{
case ENTITY_TYPE_BUILDING :
case ENTITY_TYPE_OBJECT :
{
CBaseModelInfo * collidingModel = CModelInfo : : GetModelInfo ( collidingEnt - > GetModelIndex ( ) ) ;
CColModel * collidingCol = collidingModel - > GetColModel ( ) ;
if ( collidingEnt - > IsObject ( ) & & ( ( CObject * ) collidingEnt ) - > m_nSpecialCollisionResponseCases ! = COLLRESPONSE_FENCEPART
| | collidingCol - > boundingBox . max . x < 3.0f
& & collidingCol - > boundingBox . max . y < 3.0f ) {
2019-08-16 12:25:02 -04:00
2020-11-19 14:12:20 -05:00
if ( ! IsPlayer ( ) ) {
SetDirectionToWalkAroundObject ( collidingEnt ) ;
break ;
}
}
if ( IsPlayer ( ) ) {
bHitSomethingLastFrame = true ;
break ;
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float angleToFaceWhenHit = CGeneral : : GetRadianAngleBetweenPoints (
GetPosition ( ) . x ,
GetPosition ( ) . y ,
m_vecDamageNormal . x + GetPosition ( ) . x ,
m_vecDamageNormal . y + GetPosition ( ) . y ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float neededTurn = Abs ( m_fRotationCur - angleToFaceWhenHit ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( neededTurn > PI )
neededTurn = TWOPI - neededTurn ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float oldDestRot = CGeneral : : LimitRadianAngle ( m_fRotationDest ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pedInObjective & &
( m_objective = = OBJECTIVE_GOTO_CHAR_ON_FOOT | | m_objective = = OBJECTIVE_KILL_CHAR_ON_FOOT ) ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pedInObjective - > IsPlayer ( )
& & ( neededTurn < DEGTORAD ( 20.0f ) | | m_panicCounter > 10 ) ) {
if ( CanPedJumpThis ( collidingEnt ) ) {
SetJump ( ) ;
} else if ( m_objective = = OBJECTIVE_KILL_CHAR_ON_FOOT ) {
SetWaitState ( WAITSTATE_LOOK_ABOUT , nil ) ;
} else {
SetWaitState ( WAITSTATE_PLAYANIM_TAXI , nil ) ;
m_headingRate = 0.0f ;
SetLookFlag ( m_pedInObjective , true ) ;
SetLookTimer ( 3000 ) ;
Say ( SOUND_PED_TAXI_CALL ) ;
}
} else {
m_pLookTarget = m_pedInObjective ;
m_pLookTarget - > RegisterReference ( ( CEntity * * ) & m_pLookTarget ) ;
TurnBody ( ) ;
}
} else {
if ( m_nPedType ! = PEDTYPE_COP & & neededTurn < DEGTORAD ( 15.0f ) & & m_nWaitState = = WAITSTATE_FALSE ) {
if ( ( m_nStoredMoveState = = PEDMOVE_RUN | | m_nStoredMoveState = = PEDMOVE_SPRINT ) & & m_vecDamageNormal . z < 0.3f ) {
CAnimBlendAssociation * runAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_RUN ) ;
if ( ! runAssoc )
runAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_SPRINT ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( runAssoc & & runAssoc - > blendAmount > 0.9f & & runAssoc - > IsRunning ( ) ) {
SetWaitState ( WAITSTATE_HITWALL , nil ) ;
}
}
}
if ( m_nPedState = = PED_FLEE_POS ) {
CVector2D fleePos = collidingEnt - > GetPosition ( ) ;
uint32 oldFleeTimer = m_fleeTimer ;
SetFlee ( fleePos , 5000 ) ;
if ( oldFleeTimer ! = m_fleeTimer )
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( ) + 500 ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else {
if ( m_nPedState = = PED_FLEE_ENTITY & & ( neededTurn < DEGTORAD ( 25.0f ) | | m_panicCounter > 10 ) ) {
m_collidingThingTimer = CTimer : : GetTimeInMilliseconds ( ) + 2500 ;
m_collidingEntityWhileFleeing = collidingEnt ;
m_collidingEntityWhileFleeing - > RegisterReference ( ( CEntity * * ) & m_collidingEntityWhileFleeing ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
uint8 currentDir = Floor ( ( PI + m_fRotationCur ) / DEGTORAD ( 45.0f ) ) ;
uint8 nextDir ;
ThePaths . FindNextNodeWandering ( PATH_PED , GetPosition ( ) , & m_pLastPathNode , & m_pNextPathNode , currentDir , & nextDir ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else {
if ( neededTurn < DEGTORAD ( 60.0f ) ) {
CVector posToHead = m_vecDamageNormal * 4.0f ;
posToHead . z = 0.0f ;
posToHead + = GetPosition ( ) ;
int closestNodeId = ThePaths . FindNodeClosestToCoors ( posToHead , PATH_PED ,
999999.9f , false , false ) ;
float angleToFace ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective ! = OBJECTIVE_KILL_CHAR_ON_FOOT & & m_objective ! = OBJECTIVE_KILL_CHAR_ANY_MEANS ) {
if ( m_nPedState ! = PED_SEEK_POS & & m_nPedState ! = PED_SEEK_CAR ) {
if ( m_nPedState = = PED_WANDER_PATH ) {
m_pNextPathNode = & ThePaths . m_pathNodes [ closestNodeId ] ;
angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
m_pNextPathNode - > GetX ( ) , m_pNextPathNode - > GetY ( ) ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
} else {
if ( ThePaths . m_pathNodes [ closestNodeId ] . GetX ( ) = = 0.0f
| | ThePaths . m_pathNodes [ closestNodeId ] . GetY ( ) = = 0.0f ) {
posToHead = ( 3.0f * m_vecDamageNormal ) + GetPosition ( ) ;
posToHead . x + = ( CGeneral : : GetRandomNumber ( ) % 512 ) / 250.0f - 1.0f ;
posToHead . y + = ( CGeneral : : GetRandomNumber ( ) % 512 ) / 250.0f - 1.0f ;
} else {
posToHead . x = ThePaths . m_pathNodes [ closestNodeId ] . GetX ( ) ;
posToHead . y = ThePaths . m_pathNodes [ closestNodeId ] . GetY ( ) ;
}
angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
posToHead . x , posToHead . y ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_FOLLOW_PATH )
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( ) + 500 ;
}
} else {
angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
ThePaths . m_pathNodes [ closestNodeId ] . GetX ( ) ,
ThePaths . m_pathNodes [ closestNodeId ] . GetY ( ) ,
GetPosition ( ) . x ,
GetPosition ( ) . y ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
CVector2D distToNode = ThePaths . m_pathNodes [ closestNodeId ] . GetPosition ( ) - GetPosition ( ) ;
CVector2D distToSeekPos = m_vecSeekPos - GetPosition ( ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( DotProduct2D ( distToNode , distToSeekPos ) < 0.0f ) {
m_fRotationCur = m_fRotationDest ;
break ;
}
}
} else {
float angleToFaceAwayDamage = CGeneral : : GetRadianAngleBetweenPoints (
m_vecDamageNormal . x ,
m_vecDamageNormal . y ,
0.0f ,
0.0f ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( angleToFaceAwayDamage < m_fRotationCur )
angleToFaceAwayDamage + = TWOPI ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float neededTurn = angleToFaceAwayDamage - m_fRotationCur ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( neededTurn < = PI ) {
angleToFace = 0.5f * neededTurn + m_fRotationCur ;
m_fRotationCur + = DEGTORAD ( m_pedStats - > m_headingChangeRate ) * 2.0f ;
} else {
angleToFace = m_fRotationCur - ( TWOPI - neededTurn ) * 0.5f ;
m_fRotationCur - = DEGTORAD ( m_pedStats - > m_headingChangeRate ) * 2.0f ;
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( ) + 200 ;
if ( m_nPedType = = PEDTYPE_COP ) {
if ( m_pedInObjective ) {
float angleToLookCriminal = CGeneral : : GetRadianAngleBetweenPoints (
m_pedInObjective - > GetPosition ( ) . x ,
m_pedInObjective - > GetPosition ( ) . y ,
GetPosition ( ) . x ,
GetPosition ( ) . y ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
angleToLookCriminal = CGeneral : : LimitRadianAngle ( angleToLookCriminal ) ;
angleToFace = CGeneral : : LimitRadianAngle ( angleToFace ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( angleToLookCriminal < angleToFace )
angleToLookCriminal + = TWOPI ;
2020-04-23 16:25:18 -04:00
2020-11-19 14:12:20 -05:00
float neededTurnToCriminal = angleToLookCriminal - angleToFace ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( neededTurnToCriminal > DEGTORAD ( 150.0f ) & & neededTurnToCriminal < DEGTORAD ( 210.0f ) ) {
( ( CCopPed * ) this ) - > m_bStopAndShootDisabledZone = true ;
}
}
}
}
m_fRotationDest = CGeneral : : LimitRadianAngle ( angleToFace ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( m_fRotationCur - PI > m_fRotationDest ) {
m_fRotationDest + = TWOPI ;
} else if ( PI + m_fRotationCur < m_fRotationDest ) {
m_fRotationDest - = TWOPI ;
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( oldDestRot = = m_fRotationDest & & CTimer : : GetTimeInMilliseconds ( ) > m_nPedStateTimer ) {
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( ) + 200 ;
m_fRotationDest + = HALFPI ;
}
}
}
}
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_WANDER_PATH & & m_nPedState ! = PED_FLEE_ENTITY )
m_pNextPathNode = nil ;
bHitSomethingLastFrame = true ;
break ;
}
case ENTITY_TYPE_VEHICLE :
{
CVehicle * collidingVeh = ( ( CVehicle * ) collidingEnt ) ;
float collidingVehSpeedSqr = collidingVeh - > m_vecMoveSpeed . MagnitudeSqr ( ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( collidingVeh = = m_pMyVehicle )
bCollidedWithMyVehicle = true ;
2019-09-29 12:44:51 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
float oldHealth = m_fHealth ;
bool playerSufferSound = false ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( collidingVehSpeedSqr < = 1.0f / 400.0f ) {
if ( IsPedInControl ( )
& & ( ! IsPlayer ( )
| | m_objective = = OBJECTIVE_GOTO_AREA_ON_FOOT
| | m_objective = = OBJECTIVE_RUN_TO_AREA
| | m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER ) ) {
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( collidingVeh ! = m_pCurrentPhysSurface | | IsPlayer ( ) ) {
if ( ! bVehEnterDoorIsBlocked ) {
if ( collidingVeh - > GetStatus ( ) ! = STATUS_PLAYER | | CharCreatedBy = = MISSION_CHAR ) {
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
// VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR.
SetDirectionToWalkAroundObject ( collidingVeh ) ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nLastBumpPlayerCarTimer = m_nPedStateTimer ;
} else {
if ( CTimer : : GetTimeInMilliseconds ( ) > = CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nLastBumpPlayerCarTimer
| | m_nPedStateTimer > = CTimer : : GetTimeInMilliseconds ( ) ) {
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
// VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR.
SetDirectionToWalkAroundObject ( collidingVeh ) ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nLastBumpPlayerCarTimer = m_nPedStateTimer ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else if ( m_fleeFrom ! = collidingVeh ) {
SetFlee ( collidingVeh , 4000 ) ;
bUsePedNodeSeek = false ;
SetMoveState ( PEDMOVE_WALK ) ;
}
}
}
} else {
float angleLeftToCompleteTurn = Abs ( m_fRotationCur - m_fRotationDest ) ;
if ( angleLeftToCompleteTurn < 0.01f & & CanPedJumpThis ( collidingVeh ) ) {
SetJump ( ) ;
}
}
} else if ( IsPlayer ( ) & & ! bIsInTheAir ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPedInControl ( ) & & ( ( CPlayerPed * ) this ) - > m_fMoveSpeed = = 0.0f
& & ! bIsLooking & & CTimer : : GetTimeInMilliseconds ( ) > m_lookTimer & & collidingVeh - > pDriver ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
( ( CPlayerPed * ) this ) - > AnnoyPlayerPed ( false ) ;
SetLookFlag ( collidingVeh , true ) ;
SetLookTimer ( 1300 ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
eWeaponType weaponType = GetWeapon ( ) - > m_eWeaponType ;
if ( weaponType = = WEAPONTYPE_UNARMED
| | weaponType = = WEAPONTYPE_BASEBALLBAT
| | weaponType = = WEAPONTYPE_COLT45
| | weaponType = = WEAPONTYPE_UZI ) {
bShakeFist = true ;
}
} else {
SetLookFlag ( collidingVeh , true ) ;
SetLookTimer ( 500 ) ;
}
}
} else {
float adjustedImpulse = m_fDamageImpulse ;
if ( IsPlayer ( ) ) {
if ( bIsStanding ) {
float forwardVecAndDamageDirDotProd = DotProduct ( m_vecAnimMoveDelta . y * GetForward ( ) , m_vecDamageNormal ) ;
if ( forwardVecAndDamageDirDotProd < 0.0f ) {
adjustedImpulse = forwardVecAndDamageDirDotProd * m_fMass + m_fDamageImpulse ;
if ( adjustedImpulse < 0.0f )
adjustedImpulse = 0.0f ;
}
}
}
if ( m_fMass / 20.0f < adjustedImpulse )
DMAudio . PlayOneShot ( collidingVeh - > m_audioEntityId , SOUND_CAR_PED_COLLISION , adjustedImpulse ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) ) {
if ( adjustedImpulse > 20.0f )
adjustedImpulse = 20.0f ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( adjustedImpulse > 5.0f ) {
if ( adjustedImpulse < = 13.0f )
playerSufferSound = true ;
else
Say ( SOUND_PED_DAMAGE ) ;
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
CColModel * collidingCol = CModelInfo : : GetModelInfo ( collidingVeh - > m_modelIndex ) - > GetColModel ( ) ;
CVector colMinVec = collidingCol - > boundingBox . min ;
CVector colMaxVec = collidingCol - > boundingBox . max ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
CVector vehColCenterDist = collidingVeh - > GetMatrix ( ) * ( ( colMinVec + colMaxVec ) * 0.5f ) - GetPosition ( ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
// TLVC = To look vehicle center
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float angleToVehFront = collidingVeh - > GetForward ( ) . Heading ( ) ;
float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist . Heading ( ) ;
angleDiffFromLookingFrontTLVC = CGeneral : : LimitRadianAngle ( angleDiffFromLookingFrontTLVC ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
// I don't know why do we use that
float vehTopRightHeading = Atan2 ( colMaxVec . x - colMinVec . x , colMaxVec . y - colMinVec . y ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
CVector vehDist = GetPosition ( ) - collidingVeh - > GetPosition ( ) ;
vehDist . Normalise ( ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float vehRightVecAndSpeedDotProd ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( Abs ( angleDiffFromLookingFrontTLVC ) > = vehTopRightHeading & & Abs ( angleDiffFromLookingFrontTLVC ) < PI - vehTopRightHeading ) {
if ( angleDiffFromLookingFrontTLVC < = 0.0f ) {
vehRightVecAndSpeedDotProd = DotProduct ( collidingVeh - > GetRight ( ) , collidingVeh - > m_vecMoveSpeed ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
// vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right?
if ( collidingVehSpeedSqr > 1.0f / 100.0f & & vehRightVecAndSpeedDotProd < 0.1f ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
// Car's right faces towards us and isn't coming directly to us
if ( DotProduct ( collidingVeh - > GetRight ( ) , GetForward ( ) ) < 0.0f
& & DotProduct ( vehDist , collidingVeh - > m_vecMoveSpeed ) > 0.0f ) {
SetEvasiveStep ( collidingVeh , 1 ) ;
}
}
} else {
vehRightVecAndSpeedDotProd = DotProduct ( - 1.0f * collidingVeh - > GetRight ( ) , collidingVeh - > m_vecMoveSpeed ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( collidingVehSpeedSqr > 1.0f / 100.0f & & vehRightVecAndSpeedDotProd < 0.1f ) {
if ( DotProduct ( collidingVeh - > GetRight ( ) , GetForward ( ) ) > 0.0f
& & DotProduct ( vehDist , collidingVeh - > m_vecMoveSpeed ) > 0.0f ) {
SetEvasiveStep ( collidingVeh , 1 ) ;
}
}
}
} else {
vehRightVecAndSpeedDotProd = DotProduct ( vehDist , collidingVeh - > m_vecMoveSpeed ) ;
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( vehRightVecAndSpeedDotProd < = 0.1f ) {
if ( m_nPedState ! = PED_FIGHT ) {
SetLookFlag ( collidingVeh , true ) ;
SetLookTimer ( 700 ) ;
}
} else {
bIsStanding = false ;
CVector2D collidingEntMoveDir = - collidingVeh - > m_vecMoveSpeed ;
int dir = GetLocalDirection ( collidingEntMoveDir ) ;
SetFall ( 1000 , ( AnimationId ) ( dir + ANIM_KO_SKID_FRONT ) , false ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float damage ;
if ( collidingVeh - > m_modelIndex = = MI_TRAIN ) {
damage = 50.0f ;
} else {
damage = 20.0f ;
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
InflictDamage ( collidingVeh , WEAPONTYPE_RAMMEDBYCAR , damage , PEDPIECE_TORSO , dir ) ;
Say ( SOUND_PED_DAMAGE ) ;
}
} else {
KillPedWithCar ( collidingVeh , m_fDamageImpulse ) ;
}
/* VC specific
if ( m_pCollidingEntity ! = collidingEnt )
bPushedAlongByCar = true ;
*/
}
if ( m_fHealth < oldHealth & & playerSufferSound )
Say ( SOUND_PED_HIT ) ;
# else
if ( collidingVehSpeedSqr < = 1.0f / 400.0f ) {
if ( ! IsPedInControl ( )
| | IsPlayer ( )
& & m_objective ! = OBJECTIVE_GOTO_AREA_ON_FOOT
& & m_objective ! = OBJECTIVE_ENTER_CAR_AS_DRIVER
& & m_objective ! = OBJECTIVE_RUN_TO_AREA ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) & & ! bIsInTheAir ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPedInControl ( )
& & ( ( CPlayerPed * ) this ) - > m_fMoveSpeed = = 0.0f
& & ! bIsLooking
& & CTimer : : GetTimeInMilliseconds ( ) > m_lookTimer
& & collidingVeh - > pDriver ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
( ( CPlayerPed * ) this ) - > AnnoyPlayerPed ( false ) ;
SetLookFlag ( collidingVeh , true ) ;
SetLookTimer ( 1300 ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
eWeaponType weaponType = GetWeapon ( ) - > m_eWeaponType ;
if ( weaponType = = WEAPONTYPE_UNARMED
| | weaponType = = WEAPONTYPE_BASEBALLBAT
| | weaponType = = WEAPONTYPE_COLT45
| | weaponType = = WEAPONTYPE_UZI ) {
bShakeFist = true ;
}
} else {
SetLookFlag ( collidingVeh , true ) ;
SetLookTimer ( 500 ) ;
}
}
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else if ( ! bVehEnterDoorIsBlocked ) {
if ( collidingVeh - > GetStatus ( ) ! = STATUS_PLAYER | | CharCreatedBy = = MISSION_CHAR ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
SetDirectionToWalkAroundObject ( collidingVeh ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else if ( CTimer : : GetTimeInMilliseconds ( ) > = CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nLastBumpPlayerCarTimer
| | m_nPedStateTimer > = CTimer : : GetTimeInMilliseconds ( ) ) {
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
SetDirectionToWalkAroundObject ( collidingVeh ) ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nLastBumpPlayerCarTimer = m_nPedStateTimer ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
} else if ( m_fleeFrom ! = collidingVeh ) {
SetFlee ( collidingVeh , 4000 ) ;
bUsePedNodeSeek = false ;
SetMoveState ( PEDMOVE_WALK ) ;
}
}
} else {
DMAudio . PlayOneShot ( collidingVeh - > m_audioEntityId , SOUND_CAR_PED_COLLISION , m_fDamageImpulse ) ;
if ( IsPlayer ( ) ) {
CColModel * collidingCol = CModelInfo : : GetModelInfo ( collidingVeh - > GetModelIndex ( ) ) - > GetColModel ( ) ;
CVector colMinVec = collidingCol - > boundingBox . min ;
CVector colMaxVec = collidingCol - > boundingBox . max ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
CVector vehColCenterDist = collidingVeh - > GetMatrix ( ) * ( ( colMinVec + colMaxVec ) * 0.5f ) - GetPosition ( ) ;
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
// TLVC = To look vehicle center
2019-07-03 12:34:42 -04:00
2020-11-19 14:12:20 -05:00
float angleToVehFront = collidingVeh - > GetForward ( ) . Heading ( ) ;
float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist . Heading ( ) ;
angleDiffFromLookingFrontTLVC = CGeneral : : LimitRadianAngle ( angleDiffFromLookingFrontTLVC ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
// I don't know why do we use that
float vehTopRightHeading = Atan2 ( colMaxVec . x - colMinVec . x , colMaxVec . y - colMinVec . y ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
CVector vehDist = GetPosition ( ) - collidingVeh - > GetPosition ( ) ;
vehDist . Normalise ( ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
float vehRightVecAndSpeedDotProd ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( Abs ( angleDiffFromLookingFrontTLVC ) > = vehTopRightHeading & & Abs ( angleDiffFromLookingFrontTLVC ) < PI - vehTopRightHeading ) {
if ( angleDiffFromLookingFrontTLVC < = 0.0f ) {
vehRightVecAndSpeedDotProd = DotProduct ( collidingVeh - > GetRight ( ) , collidingVeh - > m_vecMoveSpeed ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
// vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right?
if ( collidingVehSpeedSqr > 1.0f / 100.0f & & vehRightVecAndSpeedDotProd < 0.1f ) {
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
// Car's right faces towards us and isn't coming directly to us
if ( DotProduct ( collidingVeh - > GetRight ( ) , GetForward ( ) ) < 0.0f
& & DotProduct ( vehDist , collidingVeh - > m_vecMoveSpeed ) > 0.0f ) {
SetEvasiveStep ( collidingVeh , 1 ) ;
}
}
} else {
vehRightVecAndSpeedDotProd = DotProduct ( - 1.0f * collidingVeh - > GetRight ( ) , collidingVeh - > m_vecMoveSpeed ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( collidingVehSpeedSqr > 1.0f / 100.0f & & vehRightVecAndSpeedDotProd < 0.1f ) {
if ( DotProduct ( collidingVeh - > GetRight ( ) , GetForward ( ) ) > 0.0f
& & DotProduct ( vehDist , collidingVeh - > m_vecMoveSpeed ) > 0.0f ) {
SetEvasiveStep ( collidingVeh , 1 ) ;
}
}
}
} else {
vehRightVecAndSpeedDotProd = DotProduct ( vehDist , collidingVeh - > m_vecMoveSpeed ) ;
}
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( vehRightVecAndSpeedDotProd < = 0.1f ) {
if ( m_nPedState ! = PED_FIGHT ) {
SetLookFlag ( collidingVeh , true ) ;
SetLookTimer ( 700 ) ;
}
} else {
bIsStanding = false ;
CVector2D collidingEntMoveDir = - collidingVeh - > m_vecMoveSpeed ;
int dir = GetLocalDirection ( collidingEntMoveDir ) ;
SetFall ( 1000 , ( AnimationId ) ( dir + ANIM_KO_SKID_FRONT ) , false ) ;
CPed * driver = collidingVeh - > pDriver ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
float damage ;
if ( driver & & driver - > IsPlayer ( ) ) {
damage = vehRightVecAndSpeedDotProd * 1000.0f ;
} else if ( collidingVeh - > GetModelIndex ( ) = = MI_TRAIN ) {
damage = 50.0f ;
} else {
damage = 20.0f ;
}
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
InflictDamage ( collidingVeh , WEAPONTYPE_RAMMEDBYCAR , damage , PEDPIECE_TORSO , dir ) ;
Say ( SOUND_PED_DAMAGE ) ;
}
} else {
KillPedWithCar ( collidingVeh , m_fDamageImpulse ) ;
}
}
# endif
break ;
}
case ENTITY_TYPE_PED :
{
CollideWithPed ( ( CPed * ) collidingEnt ) ;
if ( ( ( CPed * ) collidingEnt ) - > IsPlayer ( ) ) {
CPlayerPed * player = ( ( CPlayerPed * ) collidingEnt ) ;
Say ( SOUND_PED_CHAT ) ;
if ( m_nMoveState > PEDMOVE_STILL & & player - > IsPedInControl ( ) ) {
if ( player - > m_fMoveSpeed < 1.0f ) {
if ( ! player - > bIsLooking ) {
if ( CTimer : : GetTimeInMilliseconds ( ) > player - > m_lookTimer ) {
player - > AnnoyPlayerPed ( false ) ;
player - > SetLookFlag ( this , true ) ;
player - > SetLookTimer ( 1300 ) ;
eWeaponType weapon = player - > GetWeapon ( ) - > m_eWeaponType ;
if ( weapon = = WEAPONTYPE_UNARMED
| | weapon = = WEAPONTYPE_BASEBALLBAT
| | weapon = = WEAPONTYPE_COLT45
| | weapon = = WEAPONTYPE_UZI ) {
player - > bShakeFist = true ;
}
}
}
}
}
}
break ;
}
default :
break ;
}
2019-07-05 18:44:49 -04:00
}
2020-11-19 14:12:20 -05:00
CVector forceDir ;
if ( ! bIsInTheAir & & m_nPedState ! = PED_JUMP
2020-02-27 11:07:36 -05:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
& & m_fDamageImpulse > 0.0f
2020-02-27 11:07:36 -05:00
# endif
2020-11-19 14:12:20 -05:00
) {
2020-02-27 11:07:36 -05:00
2020-11-19 14:12:20 -05:00
forceDir = m_vecDamageNormal ;
forceDir . z = 0.0f ;
if ( ! bIsStanding ) {
forceDir * = 4.0f ;
} else {
forceDir * = 0.5f ;
}
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
ApplyMoveForce ( forceDir ) ;
}
if ( ( bIsInTheAir & & ! DyingOrDead ( ) )
# ifdef VC_PED_PORTS
| | ( ! bIsStanding & & ! bWasStanding & & m_nPedState = = PED_FALL )
# endif
) {
if ( m_nPedStateTimer > 0 & & m_nPedStateTimer < = 1000 ) {
forceDir = GetPosition ( ) - m_vecHitLastPos ;
} else {
m_nPedStateTimer = 0 ;
m_vecHitLastPos = GetPosition ( ) ;
forceDir = CVector ( 0.0f , 0.0f , 0.0f ) ;
}
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
CVector offsetToCheck ;
m_nPedStateTimer + + ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
float adjustedTs = Max ( CTimer : : GetTimeStep ( ) , 0.01f ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
CPad * pad0 = CPad : : GetPad ( 0 ) ;
if ( ( m_nPedStateTimer < = 50.0f / ( 4.0f * adjustedTs ) | | m_nPedStateTimer * 0.01f < = forceDir . MagnitudeSqr ( ) )
& & ( m_nCollisionRecords < = 1 | | m_nPedStateTimer < = 50.0f / ( 2.0f * adjustedTs ) | | m_nPedStateTimer * 1.0f / 250.0f < = Abs ( forceDir . z ) ) ) {
if ( m_nCollisionRecords = = 1 & & m_aCollisionRecords [ 0 ] ! = nil & & m_aCollisionRecords [ 0 ] - > IsBuilding ( )
& & m_nPedStateTimer > 50.0f / ( 2.0f * adjustedTs ) & & m_nPedStateTimer * 1.0f / 250.0f > Abs ( forceDir . z ) ) {
offsetToCheck . x = - forceDir . y ;
2020-04-18 14:28:49 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
offsetToCheck . z = 1.0f ;
2020-04-18 14:28:49 -04:00
# else
2020-11-19 14:12:20 -05:00
offsetToCheck . z = 0.0f ;
2020-04-18 14:28:49 -04:00
# endif
2020-11-19 14:12:20 -05:00
offsetToCheck . y = forceDir . x ;
offsetToCheck . Normalise ( ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
CVector posToCheck = GetPosition ( ) + offsetToCheck ;
2019-09-11 20:43:18 -04:00
2020-11-19 14:12:20 -05:00
// These are either obstacle or ground to land, I don't know which one.
float obstacleForFlyingZ , obstacleForFlyingOtherDirZ ;
CColPoint obstacleForFlying , obstacleForFlyingOtherDir ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
// Check is there any room for being knocked up in reverse direction of force
if ( CWorld : : ProcessVerticalLine ( posToCheck , - 20.0f , obstacleForFlying , foundEnt , true , false , false , false , false , false , nil ) ) {
obstacleForFlyingZ = obstacleForFlying . point . z ;
} else {
obstacleForFlyingZ = 500.0f ;
}
posToCheck = GetPosition ( ) - offsetToCheck ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
// Now check for direction of force this time
if ( CWorld : : ProcessVerticalLine ( posToCheck , - 20.0f , obstacleForFlyingOtherDir , foundEnt , true , false , false , false , false , false , nil ) ) {
obstacleForFlyingOtherDirZ = obstacleForFlyingOtherDir . point . z ;
} else {
obstacleForFlyingOtherDirZ = 501.0f ;
}
# ifdef VC_PED_PORTS
uint8 flyDir = 0 ;
float feetZ = GetPosition ( ) . z - FEET_OFFSET ;
if ( ( obstacleForFlyingZ < = feetZ | | obstacleForFlyingOtherDirZ > = 500.0f ) & & ( obstacleForFlyingZ < = feetZ | | obstacleForFlyingOtherDirZ < = feetZ ) ) {
if ( obstacleForFlyingOtherDirZ > feetZ & & obstacleForFlyingZ < 499.0f )
flyDir = 2 ;
} else {
flyDir = 1 ;
}
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( flyDir ! = 0 & & ! bSomeVCflag1 ) {
SetPosition ( ( flyDir = = 2 ? obstacleForFlyingOtherDir . point : obstacleForFlying . point ) ) ;
GetMatrix ( ) . GetPosition ( ) . z + = FEET_OFFSET ;
GetMatrix ( ) . UpdateRW ( ) ;
SetLanding ( ) ;
bIsStanding = true ;
}
# endif
if ( obstacleForFlyingZ < obstacleForFlyingOtherDirZ ) {
offsetToCheck * = - 1.0f ;
}
offsetToCheck . z = 1.0f ;
forceDir = 4.0f * offsetToCheck ;
forceDir . z = 4.0f ;
ApplyMoveForce ( forceDir ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
GetMatrix ( ) . GetPosition ( ) + = 0.25f * offsetToCheck ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationCur = CGeneral : : GetRadianAngleBetweenPoints ( offsetToCheck . x , offsetToCheck . y , 0.0f , 0.0f ) ;
m_fRotationCur = CGeneral : : LimitRadianAngle ( m_fRotationCur ) ;
m_fRotationDest = m_fRotationCur ;
SetHeading ( m_fRotationCur ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_FALL & & ! bIsPedDieAnimPlaying ) {
SetFall ( 1000 , ANIM_KO_SKID_BACK , true ) ;
}
bIsInTheAir = false ;
} else if ( m_vecDamageNormal . z > 0.4f ) {
# ifndef VC_PED_PORTS
forceDir = m_vecDamageNormal ;
forceDir . z = 0.0f ;
forceDir . Normalise ( ) ;
ApplyMoveForce ( 2.0f * forceDir ) ;
# else
if ( m_nPedState = = PED_JUMP ) {
if ( m_nWaitTimer < = 2000 ) {
if ( m_nWaitTimer < 1000 )
m_nWaitTimer + = CTimer : : GetTimeStep ( ) * 0.02f * 1000.0f ;
} else {
m_nWaitTimer = 0 ;
}
}
forceDir = m_vecDamageNormal ;
forceDir . z = 0.0f ;
forceDir . Normalise ( ) ;
if ( m_nPedState ! = PED_JUMP | | m_nWaitTimer > = 300 ) {
ApplyMoveForce ( 2.0f * forceDir ) ;
} else {
ApplyMoveForce ( - 4.0f * forceDir ) ;
}
# endif
}
} else if ( ( CTimer : : GetFrameCounter ( ) + m_randomSeed % 256 + 3 ) & 7 ) {
if ( IsPlayer ( ) & & m_nPedState ! = PED_JUMP & & pad0 - > JumpJustDown ( ) ) {
int16 padWalkX = pad0 - > GetPedWalkLeftRight ( ) ;
int16 padWalkY = pad0 - > GetPedWalkUpDown ( ) ;
if ( Abs ( padWalkX ) > 0.0f | | Abs ( padWalkY ) > 0.0f ) {
m_fRotationDest = CGeneral : : GetRadianAngleBetweenPoints ( 0.0f , 0.0f , - padWalkX , padWalkY ) ;
m_fRotationDest - = TheCamera . Orientation ;
m_fRotationDest = CGeneral : : LimitRadianAngle ( m_fRotationDest ) ;
m_fRotationCur = m_fRotationDest ;
SetHeading ( m_fRotationCur ) ;
}
SetJump ( ) ;
m_nPedStateTimer = 0 ;
m_vecHitLastPos = GetPosition ( ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
// Why? forceDir is unused after this point.
forceDir = CVector ( 0.0f , 0.0f , 0.0f ) ;
} else if ( IsPlayer ( ) ) {
int16 padWalkX = pad0 - > GetPedWalkLeftRight ( ) ;
int16 padWalkY = pad0 - > GetPedWalkUpDown ( ) ;
if ( Abs ( padWalkX ) > 0.0f | | Abs ( padWalkY ) > 0.0f ) {
m_fRotationDest = CGeneral : : GetRadianAngleBetweenPoints ( 0.0f , 0.0f , - padWalkX , padWalkY ) ;
m_fRotationDest - = TheCamera . Orientation ;
m_fRotationDest = CGeneral : : LimitRadianAngle ( m_fRotationDest ) ;
m_fRotationCur = m_fRotationDest ;
SetHeading ( m_fRotationCur ) ;
}
CAnimBlendAssociation * jumpAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_JUMP_GLIDE ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( ! jumpAssoc )
jumpAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FALL_GLIDE ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( jumpAssoc ) {
jumpAssoc - > blendDelta = - 3.0f ;
jumpAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
if ( m_nPedState = = PED_JUMP )
m_nPedState = PED_IDLE ;
} else {
CAnimBlendAssociation * jumpAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_JUMP_GLIDE ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( ! jumpAssoc )
jumpAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FALL_GLIDE ) ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( jumpAssoc ) {
jumpAssoc - > blendDelta = - 3.0f ;
jumpAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
}
} else {
offsetToCheck = GetPosition ( ) ;
offsetToCheck . z + = 0.5f ;
2019-07-05 18:44:49 -04:00
2020-11-19 14:12:20 -05:00
if ( CWorld : : ProcessVerticalLine ( offsetToCheck , GetPosition ( ) . z - FEET_OFFSET , foundCol , foundEnt , true , true , false , true , false , false , nil ) ) {
# ifdef VC_PED_PORTS
if ( ! bSomeVCflag1 | | FEET_OFFSET + foundCol . point . z < GetPosition ( ) . z ) {
GetMatrix ( ) . GetPosition ( ) . z = FEET_OFFSET + foundCol . point . z ;
GetMatrix ( ) . UpdateRW ( ) ;
if ( bSomeVCflag1 )
bSomeVCflag1 = false ;
}
# else
GetMatrix ( ) . GetPosition ( ) . z = FEET_OFFSET + foundCol . point . z ;
GetMatrix ( ) . UpdateRW ( ) ;
# endif
SetLanding ( ) ;
bIsStanding = true ;
}
}
} else if ( m_nPedStateTimer < 1001 ) {
m_nPedStateTimer = 0 ;
2019-07-05 18:44:49 -04:00
}
}
2019-07-10 02:06:43 -04:00
2020-11-19 14:12:20 -05:00
if ( bIsDucking )
Duck ( ) ;
2019-07-10 02:06:43 -04:00
2020-11-19 14:12:20 -05:00
if ( bStartWanderPathOnFoot ) {
if ( IsPedInControl ( ) ) {
ClearAll ( ) ;
SetWanderPath ( m_nPathDir ) ;
bStartWanderPathOnFoot = false ;
} else if ( m_nPedState = = PED_DRIVING ) {
bWanderPathAfterExitingCar = true ;
SetObjective ( OBJECTIVE_LEAVE_CAR , m_pMyVehicle ) ;
}
2019-07-10 02:06:43 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ! bIsStanding & & m_vecMoveSpeed . z > 0.25f ) {
float airResistance = Pow ( 0.95f , CTimer : : GetTimeStep ( ) ) ;
2019-07-10 02:06:43 -04:00
2020-11-19 14:12:20 -05:00
m_vecMoveSpeed * = airResistance ;
}
# ifdef VC_PED_PORTS
if ( IsPlayer ( ) | | ! bIsStanding | | m_vecMoveSpeed . x ! = 0.0f | | m_vecMoveSpeed . y ! = 0.0f | | m_vecMoveSpeed . z ! = 0.0f
| | ( m_nMoveState ! = PEDMOVE_NONE & & m_nMoveState ! = PEDMOVE_STILL )
| | m_vecAnimMoveDelta . x ! = 0.0f | | m_vecAnimMoveDelta . y ! = 0.0f
| | m_nPedState = = PED_JUMP
| | bIsInTheAir
| | m_pCurrentPhysSurface ) {
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
CPhysical : : ProcessControl ( ) ;
} else {
bHasContacted = false ;
bIsInSafePosition = false ;
bWasPostponed = false ;
bHasHitWall = false ;
m_nCollisionRecords = 0 ;
bHasCollided = false ;
m_nDamagePieceType = 0 ;
m_fDamageImpulse = 0.0f ;
m_pDamageEntity = nil ;
m_vecTurnFriction = CVector ( 0.0f , 0.0f , 0.0f ) ;
m_vecMoveFriction = CVector ( 0.0f , 0.0f , 0.0f ) ;
}
# else
CPhysical : : ProcessControl ( ) ;
2019-11-24 21:25:10 -05:00
# endif
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_DIE | | bIsPedDieAnimPlaying ) {
if ( m_nPedState ! = PED_DEAD ) {
CalculateNewVelocity ( ) ;
CalculateNewOrientation ( ) ;
}
UpdatePosition ( ) ;
PlayFootSteps ( ) ;
if ( IsPedInControl ( ) & & ! bIsStanding & & ! m_pDamageEntity & & CheckIfInTheAir ( ) ) {
SetInTheAir ( ) ;
# ifdef VC_PED_PORTS
bSomeVCflag1 = false ;
2020-07-01 08:28:43 -04:00
# endif
2020-11-19 14:12:20 -05:00
}
# ifdef VC_PED_PORTS
if ( bSomeVCflag1 ) {
CVector posToCheck = GetPosition ( ) ;
posToCheck . z + = 0.9f ;
if ( ! CWorld : : TestSphereAgainstWorld ( posToCheck , 0.2f , this , true , true , false , true , false , false ) )
bSomeVCflag1 = false ;
}
2020-07-01 08:28:43 -04:00
# endif
2020-11-19 14:12:20 -05:00
ProcessObjective ( ) ;
if ( ! bIsAimingGun ) {
if ( bIsRestoringGun )
RestoreGunPosition ( ) ;
} else {
AimGun ( ) ;
}
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( bIsLooking ) {
MoveHeadToLook ( ) ;
} else if ( bIsRestoringLook ) {
RestoreHeadPosition ( ) ;
}
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( bIsInTheAir )
InTheAir ( ) ;
2019-11-24 21:25:10 -05:00
2020-11-19 14:12:20 -05:00
if ( bUpdateAnimHeading ) {
if ( m_nPedState ! = PED_GETUP & & m_nPedState ! = PED_FALL ) {
m_fRotationCur - = HALFPI ;
m_fRotationDest = m_fRotationCur ;
bUpdateAnimHeading = false ;
}
}
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nWaitState ! = WAITSTATE_FALSE )
Wait ( ) ;
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_IDLE ) {
CAnimBlendAssociation * idleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_ARMED ) ;
if ( idleAssoc ) {
idleAssoc - > blendDelta = - 8.0f ;
idleAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
}
2019-07-15 08:11:40 -04:00
2020-12-20 18:06:00 -05:00
# ifdef CANCELLABLE_CAR_ENTER
static bool cancelJack = false ;
if ( IsPlayer ( ) ) {
if ( EnteringCar ( ) & & m_pVehicleAnim ) {
CPad * pad = CPad : : GetPad ( 0 ) ;
if ( ! pad - > ArePlayerControlsDisabled ( ) ) {
int vehAnim = m_pVehicleAnim - > animId ;
int16 padWalkX = pad - > GetPedWalkLeftRight ( ) ;
int16 padWalkY = pad - > GetPedWalkUpDown ( ) ;
if ( Abs ( padWalkX ) > 0.0f | | Abs ( padWalkY ) > 0.0f ) {
if ( vehAnim = = ANIM_CAR_OPEN_LHS | | vehAnim = = ANIM_CAR_OPEN_RHS | | vehAnim = = ANIM_COACH_OPEN_L | | vehAnim = = ANIM_COACH_OPEN_R | |
vehAnim = = ANIM_VAN_OPEN_L | | vehAnim = = ANIM_VAN_OPEN ) {
if ( ! m_pMyVehicle - > pDriver ) {
cancelJack = false ;
bCancelEnteringCar = true ;
} else
cancelJack = true ;
} else if ( vehAnim = = ANIM_CAR_QJACK & & m_pVehicleAnim - > GetTimeLeft ( ) > 0.75f ) {
cancelJack = true ;
} else if ( vehAnim = = ANIM_CAR_PULLOUT_LHS | | vehAnim = = ANIM_CAR_PULLOUT_LOW_LHS | | vehAnim = = ANIM_CAR_PULLOUT_LOW_RHS | | vehAnim = = ANIM_CAR_PULLOUT_RHS ) {
bCancelEnteringCar = true ;
cancelJack = false ;
}
}
if ( cancelJack & & vehAnim = = ANIM_CAR_QJACK & & m_pVehicleAnim - > GetTimeLeft ( ) > 0.75f & & m_pVehicleAnim - > GetTimeLeft ( ) < 0.78f ) {
cancelJack = false ;
QuitEnteringCar ( ) ;
RestorePreviousObjective ( ) ;
}
if ( cancelJack & & ( vehAnim = = ANIM_CAR_PULLOUT_LHS | | vehAnim = = ANIM_CAR_PULLOUT_LOW_LHS | | vehAnim = = ANIM_CAR_PULLOUT_LOW_RHS | | vehAnim = = ANIM_CAR_PULLOUT_RHS ) ) {
cancelJack = false ;
bCancelEnteringCar = true ;
}
}
} else
cancelJack = false ;
}
# endif
2020-11-19 14:12:20 -05:00
switch ( m_nPedState ) {
case PED_IDLE :
Idle ( ) ;
break ;
case PED_LOOK_ENTITY :
case PED_LOOK_HEADING :
Look ( ) ;
break ;
case PED_WANDER_RANGE :
WanderRange ( ) ;
CheckAroundForPossibleCollisions ( ) ;
break ;
case PED_WANDER_PATH :
WanderPath ( ) ;
break ;
case PED_ENTER_CAR :
case PED_CARJACK :
break ;
case PED_FLEE_POS :
ms_vec2DFleePosition . x = m_fleeFromPosX ;
ms_vec2DFleePosition . y = m_fleeFromPosY ;
Flee ( ) ;
break ;
case PED_FLEE_ENTITY :
if ( ! m_fleeFrom ) {
SetIdle ( ) ;
break ;
}
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_nPedStateTimer )
break ;
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
ms_vec2DFleePosition = m_fleeFrom - > GetPosition ( ) ;
Flee ( ) ;
break ;
case PED_FOLLOW_PATH :
FollowPath ( ) ;
break ;
case PED_PAUSE :
Pause ( ) ;
break ;
case PED_ATTACK :
Attack ( ) ;
break ;
case PED_FIGHT :
Fight ( ) ;
break ;
case PED_CHAT :
Chat ( ) ;
break ;
case PED_AIM_GUN :
if ( m_pPointGunAt & & m_pPointGunAt - > IsPed ( )
# ifdef FIX_BUGS
& & ! GetWeapon ( ) - > IsTypeMelee ( )
# endif
& & ( ( CPed * ) m_pPointGunAt ) - > CanSeeEntity ( this , CAN_SEE_ENTITY_ANGLE_THRESHOLD * 2 ) ) {
( ( CPed * ) m_pPointGunAt ) - > ReactToPointGun ( this ) ;
}
PointGunAt ( ) ;
break ;
case PED_SEEK_CAR :
SeekCar ( ) ;
break ;
case PED_SEEK_IN_BOAT :
SeekBoatPosition ( ) ;
break ;
case PED_INVESTIGATE :
InvestigateEvent ( ) ;
break ;
case PED_ON_FIRE :
if ( IsPlayer ( ) )
break ;
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_fleeTimer ) {
if ( m_fleeFrom ) {
ms_vec2DFleePosition = m_fleeFrom - > GetPosition ( ) ;
} else {
ms_vec2DFleePosition . x = m_fleeFromPosX ;
ms_vec2DFleePosition . y = m_fleeFromPosY ;
}
Flee ( ) ;
} else {
if ( m_pFire )
m_pFire - > Extinguish ( ) ;
}
break ;
case PED_FALL :
Fall ( ) ;
break ;
case PED_GETUP :
SetGetUp ( ) ;
break ;
case PED_ENTER_TRAIN :
EnterTrain ( ) ;
break ;
case PED_EXIT_TRAIN :
ExitTrain ( ) ;
break ;
case PED_DRIVING :
{
if ( ! m_pMyVehicle ) {
bInVehicle = false ;
FlagToDestroyWhenNextProcessed ( ) ;
return ;
}
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pMyVehicle - > pDriver ! = this | | m_pMyVehicle - > IsBoat ( ) ) {
LookForSexyPeds ( ) ;
LookForSexyCars ( ) ;
break ;
}
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pMyVehicle - > m_vehType = = VEHICLE_TYPE_BIKE | | ! m_pMyVehicle - > pDriver - > IsPlayer ( ) ) {
break ;
}
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
CPad * pad = CPad : : GetPad ( 0 ) ;
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
# ifdef CAR_AIRBREAK
if ( ! pad - > ArePlayerControlsDisabled ( ) ) {
if ( pad - > GetHorn ( ) ) {
float c = Cos ( m_fRotationCur ) ;
float s = Sin ( m_fRotationCur ) ;
m_pMyVehicle - > GetRight ( ) = CVector ( 1.0f , 0.0f , 0.0f ) ;
m_pMyVehicle - > GetForward ( ) = CVector ( 0.0f , 1.0f , 0.0f ) ;
m_pMyVehicle - > GetUp ( ) = CVector ( 0.0f , 0.0f , 1.0f ) ;
if ( pad - > GetAccelerate ( ) ) {
m_pMyVehicle - > ApplyMoveForce ( GetForward ( ) * 30.0f ) ;
} else if ( pad - > GetBrake ( ) ) {
m_pMyVehicle - > ApplyMoveForce ( - GetForward ( ) * 30.0f ) ;
} else {
int16 lr = pad - > GetSteeringLeftRight ( ) ;
if ( lr < 0 ) {
//m_pMyVehicle->ApplyTurnForce(20.0f * -GetRight(), GetForward());
m_pMyVehicle - > ApplyMoveForce ( - GetRight ( ) * 30.0f ) ;
} else if ( lr > 0 ) {
m_pMyVehicle - > ApplyMoveForce ( GetRight ( ) * 30.0f ) ;
} else {
m_pMyVehicle - > ApplyMoveForce ( 0.0f , 0.0f , 50.0f ) ;
}
}
}
}
2020-07-01 08:28:43 -04:00
# endif
2020-11-19 14:12:20 -05:00
float steerAngle = m_pMyVehicle - > m_fSteerAngle ;
CAnimBlendAssociation * lDriveAssoc ;
CAnimBlendAssociation * rDriveAssoc ;
CAnimBlendAssociation * lbAssoc ;
CAnimBlendAssociation * sitAssoc ;
if ( m_pMyVehicle - > bLowVehicle ) {
sitAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_LSIT ) ;
2020-07-01 08:28:43 -04:00
2020-11-19 14:12:20 -05:00
if ( ! sitAssoc | | sitAssoc - > blendAmount < 1.0f ) {
break ;
}
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
lDriveAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_DRIVE_LOW_L ) ;
lbAssoc = nil ;
rDriveAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_DRIVE_LOW_R ) ;
} else {
sitAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_SIT ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( ! sitAssoc | | sitAssoc - > blendAmount < 1.0f ) {
break ;
}
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
lDriveAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_DRIVE_L ) ;
rDriveAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_DRIVE_R ) ;
lbAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_LB ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( lbAssoc & &
TheCamera . Cams [ TheCamera . ActiveCam ] . Mode = = CCam : : MODE_1STPERSON
& & TheCamera . Cams [ TheCamera . ActiveCam ] . DirectionWasLooking = = LOOKING_LEFT ) {
lbAssoc - > blendDelta = - 1000.0f ;
}
}
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * driveByAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_DRIVEBY_L ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( ! driveByAssoc )
driveByAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_DRIVEBY_R ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( m_pMyVehicle - > bLowVehicle | | m_pMyVehicle - > m_fGasPedal > = 0.0f | | driveByAssoc ) {
if ( steerAngle = = 0.0f | | driveByAssoc ) {
if ( lDriveAssoc )
lDriveAssoc - > blendAmount = 0.0f ;
if ( rDriveAssoc )
rDriveAssoc - > blendAmount = 0.0f ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
} else if ( steerAngle < = 0.0f ) {
if ( lDriveAssoc )
lDriveAssoc - > blendAmount = 0.0f ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( rDriveAssoc )
rDriveAssoc - > blendAmount = clamp ( steerAngle * - 100.0f / 61.0f , 0.0f , 1.0f ) ;
else if ( m_pMyVehicle - > bLowVehicle )
CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_DRIVE_LOW_R ) ;
else
CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_DRIVE_R ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
} else {
if ( rDriveAssoc )
rDriveAssoc - > blendAmount = 0.0f ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( lDriveAssoc )
lDriveAssoc - > blendAmount = clamp ( steerAngle * 100.0f / 61.0f , 0.0f , 1.0f ) ;
else if ( m_pMyVehicle - > bLowVehicle )
CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_DRIVE_LOW_L ) ;
else
CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_DRIVE_L ) ;
}
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( lbAssoc )
lbAssoc - > blendDelta = - 4.0f ;
} else {
if ( ( TheCamera . Cams [ TheCamera . ActiveCam ] . Mode ! = CCam : : MODE_1STPERSON
| | TheCamera . Cams [ TheCamera . ActiveCam ] . DirectionWasLooking ! = LOOKING_LEFT )
& & ( ! lbAssoc | | lbAssoc - > blendAmount < 1.0f ) ) {
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_LB , 4.0f ) ;
}
}
break ;
}
case PED_DIE :
Die ( ) ;
break ;
case PED_HANDS_UP :
if ( m_pedStats - > m_temper < = 50 ) {
if ( ! RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_HANDSCOWER ) ) {
CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_HANDSCOWER ) ;
Say ( SOUND_PED_HANDS_COWER ) ;
}
} else if ( ! RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_HANDSUP ) ) {
CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_HANDSUP ) ;
Say ( SOUND_PED_HANDS_UP ) ;
}
break ;
default : break ;
}
SetMoveAnim ( ) ;
if ( bPedIsBleeding ) {
if ( CGame : : nastyGame ) {
if ( ! ( CTimer : : GetFrameCounter ( ) & 3 ) ) {
CVector cameraDist = GetPosition ( ) - TheCamera . GetPosition ( ) ;
if ( cameraDist . MagnitudeSqr ( ) < sq ( 50.0f ) ) {
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
float length = ( CGeneral : : GetRandomNumber ( ) & 127 ) * 0.0015f + 0.15f ;
CVector bloodPos (
( ( CGeneral : : GetRandomNumber ( ) & 127 ) - 64 ) * 0.007f ,
( ( CGeneral : : GetRandomNumber ( ) & 127 ) - 64 ) * 0.007f ,
1.0f ) ;
bloodPos + = GetPosition ( ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
CShadows : : AddPermanentShadow ( SHADOWTYPE_DARK , gpBloodPoolTex , & bloodPos , length , 0.0f ,
0.0f , - length , 255 , 255 , 0 , 0 , 4.0f , ( CGeneral : : GetRandomNumber ( ) & 4095 ) + 2000 , 1.0f ) ;
}
}
2019-07-15 08:11:40 -04:00
}
}
2020-11-19 14:12:20 -05:00
ServiceTalking ( ) ;
if ( bInVehicle & & ! m_pMyVehicle )
bInVehicle = false ;
# ifndef VC_PED_PORTS
m_pCurrentPhysSurface = nil ;
# endif
} else {
if ( bIsStanding & & ( ! m_pCurrentPhysSurface | | IsPlayer ( ) )
| | bIsInWater | | ! bUsesCollision ) {
SetDead ( ) ;
}
m_pCurrentPhysSurface = nil ;
2019-07-15 08:11:40 -04:00
}
}
}
2020-11-19 14:12:20 -05:00
int32
CPed : : ProcessEntityCollision ( CEntity * collidingEnt , CColPoint * collidingPoints )
2019-07-15 08:11:40 -04:00
{
2020-11-19 14:12:20 -05:00
bool collidedWithBoat = false ;
bool belowTorsoCollided = false ;
float gravityEffect = - 0.15f * CTimer : : GetTimeStep ( ) ;
CColPoint intersectionPoint ;
CColLine ourLine ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
CColModel * ourCol = CModelInfo : : GetModelInfo ( GetModelIndex ( ) ) - > GetColModel ( ) ;
CColModel * hisCol = CModelInfo : : GetModelInfo ( collidingEnt - > GetModelIndex ( ) ) - > GetColModel ( ) ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( ! bUsesCollision )
return false ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
if ( collidingEnt - > IsVehicle ( ) & & ( ( CVehicle * ) collidingEnt ) - > IsBoat ( ) )
collidedWithBoat = true ;
2019-07-15 08:11:40 -04:00
2020-11-19 14:12:20 -05:00
// ofc we're not vehicle
if ( ! m_bIsVehicleBeingShifted & & ! bSkipLineCol
2020-03-25 10:13:06 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
& & ! collidingEnt - > IsPed ( )
2020-03-25 10:13:06 -04:00
# endif
2020-11-19 14:12:20 -05:00
) {
if ( ! bCollisionProcessed ) {
2020-03-07 14:22:43 -05:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
m_pCurrentPhysSurface = nil ;
# endif
if ( bIsStanding ) {
bIsStanding = false ;
bWasStanding = true ;
}
bCollisionProcessed = true ;
m_fCollisionSpeed + = m_vecMoveSpeed . Magnitude2D ( ) * CTimer : : GetTimeStep ( ) ;
bStillOnValidPoly = false ;
if ( IsPlayer ( ) | | m_fCollisionSpeed > = 1.0f
& & ( m_fCollisionSpeed > = 2.0f | | m_nPedState ! = PED_WANDER_PATH ) ) {
m_collPoly . valid = false ;
m_fCollisionSpeed = 0.0f ;
bHitSteepSlope = false ;
} else {
CVector pos = GetPosition ( ) ;
float potentialGroundZ = GetPosition ( ) . z - FEET_OFFSET ;
if ( bWasStanding ) {
pos . z + = - 0.25f ;
potentialGroundZ + = gravityEffect ;
}
if ( CCollision : : IsStoredPolyStillValidVerticalLine ( pos , potentialGroundZ , intersectionPoint , & m_collPoly ) ) {
bStillOnValidPoly = true ;
# ifdef VC_PED_PORTS
if ( ! bSomeVCflag1 | | FEET_OFFSET + intersectionPoint . point . z < GetPosition ( ) . z ) {
GetMatrix ( ) . GetPosition ( ) . z = FEET_OFFSET + intersectionPoint . point . z ;
if ( bSomeVCflag1 )
bSomeVCflag1 = false ;
}
# else
GetMatrix ( ) . GetPosition ( ) . z = FEET_OFFSET + intersectionPoint . point . z ;
2020-03-07 14:22:43 -05:00
# endif
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
m_vecMoveSpeed . z = 0.0f ;
bIsStanding = true ;
} else {
m_collPoly . valid = false ;
m_fCollisionSpeed = 0.0f ;
bHitSteepSlope = false ;
}
}
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ! bStillOnValidPoly ) {
CVector potentialCenter = GetPosition ( ) ;
potentialCenter . z = GetPosition ( ) . z - 0.52f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
// 0.52f should be a ped's approx. radius
float totalRadiusWhenCollided = collidingEnt - > GetBoundRadius ( ) + 0.52f - gravityEffect ;
if ( bWasStanding ) {
if ( collidedWithBoat ) {
potentialCenter . z + = 2.0f * gravityEffect ;
totalRadiusWhenCollided + = Abs ( gravityEffect ) ;
} else {
potentialCenter . z + = gravityEffect ;
}
}
if ( sq ( totalRadiusWhenCollided ) > ( potentialCenter - collidingEnt - > GetBoundCentre ( ) ) . MagnitudeSqr ( ) ) {
ourLine . p0 = GetPosition ( ) ;
ourLine . p1 = GetPosition ( ) ;
ourLine . p1 . z = GetPosition ( ) . z - FEET_OFFSET ;
if ( bWasStanding ) {
ourLine . p1 . z = ourLine . p1 . z + gravityEffect ;
ourLine . p0 . z = ourLine . p0 . z + - 0.25f ;
}
float minDist = 1.0f ;
belowTorsoCollided = CCollision : : ProcessVerticalLine ( ourLine , collidingEnt - > GetMatrix ( ) , * hisCol ,
intersectionPoint , minDist , false , & m_collPoly ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( collidedWithBoat & & bWasStanding & & ! belowTorsoCollided ) {
ourLine . p0 . z = ourLine . p1 . z ;
ourLine . p1 . z = ourLine . p1 . z + gravityEffect ;
belowTorsoCollided = CCollision : : ProcessVerticalLine ( ourLine , collidingEnt - > GetMatrix ( ) , * hisCol ,
intersectionPoint , minDist , false , & m_collPoly ) ;
}
if ( belowTorsoCollided ) {
# ifndef VC_PED_PORTS
if ( ! collidingEnt - > IsPed ( ) ) {
# endif
if ( ! bIsStanding
| | FEET_OFFSET + intersectionPoint . point . z > GetPosition ( ) . z
| | collidedWithBoat & & 3.12f + intersectionPoint . point . z > GetPosition ( ) . z ) {
if ( ! collidingEnt - > IsVehicle ( ) & & ! collidingEnt - > IsObject ( ) ) {
m_pCurSurface = collidingEnt ;
collidingEnt - > RegisterReference ( ( CEntity * * ) & m_pCurSurface ) ;
bTryingToReachDryLand = false ;
bOnBoat = false ;
} else {
m_pCurrentPhysSurface = ( CPhysical * ) collidingEnt ;
collidingEnt - > RegisterReference ( ( CEntity * * ) & m_pCurrentPhysSurface ) ;
m_vecOffsetFromPhysSurface = intersectionPoint . point - collidingEnt - > GetPosition ( ) ;
m_pCurSurface = collidingEnt ;
collidingEnt - > RegisterReference ( ( CEntity * * ) & m_pCurSurface ) ;
m_collPoly . valid = false ;
if ( collidingEnt - > IsVehicle ( ) & & ( ( CVehicle * ) collidingEnt ) - > IsBoat ( ) ) {
bOnBoat = true ;
} else {
bOnBoat = false ;
}
}
2020-06-03 23:03:12 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
if ( ! bSomeVCflag1 | | FEET_OFFSET + intersectionPoint . point . z < GetPosition ( ) . z ) {
GetMatrix ( ) . GetPosition ( ) . z = FEET_OFFSET + intersectionPoint . point . z ;
if ( bSomeVCflag1 )
bSomeVCflag1 = false ;
}
# else
GetMatrix ( ) . GetPosition ( ) . z = FEET_OFFSET + intersectionPoint . point . z ;
2020-06-03 23:03:12 -04:00
# endif
2020-11-19 14:12:20 -05:00
m_nSurfaceTouched = intersectionPoint . surfaceB ;
if ( m_nSurfaceTouched = = SURFACE_STEEP_CLIFF ) {
bHitSteepSlope = true ;
m_vecDamageNormal = intersectionPoint . normal ;
}
}
# ifdef VC_PED_PORTS
float upperSpeedLimit = 0.33f ;
float lowerSpeedLimit = - 0.25f ;
float speed = m_vecMoveSpeed . Magnitude2D ( ) ;
if ( m_nPedState = = PED_IDLE ) {
upperSpeedLimit * = 2.0f ;
lowerSpeedLimit * = 1.5f ;
}
CAnimBlendAssociation * fallAnim = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FALL_FALL ) ;
if ( ! bWasStanding & & speed > upperSpeedLimit & & ( /*!bPushedAlongByCar ||*/ m_vecMoveSpeed . z < lowerSpeedLimit )
& & m_pCollidingEntity ! = collidingEnt ) {
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
float damage = 100.0f * Max ( speed - 0.25f , 0.0f ) ;
float damage2 = damage ;
if ( m_vecMoveSpeed . z < - 0.25f )
damage + = ( - 0.25f - m_vecMoveSpeed . z ) * 150.0f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
uint8 dir = 2 ; // from backward
if ( m_vecMoveSpeed . x > 0.01f | | m_vecMoveSpeed . x < - 0.01f | | m_vecMoveSpeed . y > 0.01f | | m_vecMoveSpeed . y < - 0.01f ) {
CVector2D offset = - m_vecMoveSpeed ;
dir = GetLocalDirection ( offset ) ;
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
InflictDamage ( collidingEnt , WEAPONTYPE_FALL , damage , PEDPIECE_TORSO , dir ) ;
if ( IsPlayer ( ) & & damage2 > 5.0f )
Say ( SOUND_PED_LAND ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
} else if ( ! bWasStanding & & fallAnim & & - 0.016f * CTimer : : GetTimeStep ( ) > m_vecMoveSpeed . z ) {
InflictDamage ( collidingEnt , WEAPONTYPE_FALL , 15.0f , PEDPIECE_TORSO , 2 ) ;
}
# else
float speedSqr = 0.0f ;
CAnimBlendAssociation * fallAnim = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FALL_FALL ) ;
if ( ! bWasStanding & & ( m_vecMoveSpeed . z < - 0.25f | | ( speedSqr = m_vecMoveSpeed . MagnitudeSqr ( ) ) > sq ( 0.5f ) ) ) {
if ( speedSqr = = 0.0f )
speedSqr = sq ( m_vecMoveSpeed . z ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
uint8 dir = 2 ; // from backward
if ( m_vecMoveSpeed . x > 0.01f | | m_vecMoveSpeed . x < - 0.01f | | m_vecMoveSpeed . y > 0.01f | | m_vecMoveSpeed . y < - 0.01f ) {
CVector2D offset = - m_vecMoveSpeed ;
dir = GetLocalDirection ( offset ) ;
}
InflictDamage ( collidingEnt , WEAPONTYPE_FALL , 350.0f * sq ( speedSqr ) , PEDPIECE_TORSO , dir ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
} else if ( ! bWasStanding & & fallAnim & & - 0.016f * CTimer : : GetTimeStep ( ) > m_vecMoveSpeed . z ) {
InflictDamage ( collidingEnt , WEAPONTYPE_FALL , 15.0f , PEDPIECE_TORSO , 2 ) ;
}
# endif
m_vecMoveSpeed . z = 0.0f ;
bIsStanding = true ;
# ifndef VC_PED_PORTS
} else {
bOnBoat = false ;
}
# endif
} else {
bOnBoat = false ;
}
}
2019-07-17 22:26:46 -04:00
}
}
2020-11-19 14:12:20 -05:00
int ourCollidedSpheres = CCollision : : ProcessColModels ( GetMatrix ( ) , * ourCol , collidingEnt - > GetMatrix ( ) , * hisCol , collidingPoints , nil , nil ) ;
if ( ourCollidedSpheres > 0 | | belowTorsoCollided ) {
AddCollisionRecord ( collidingEnt ) ;
if ( ! collidingEnt - > IsBuilding ( ) )
( ( CPhysical * ) collidingEnt ) - > AddCollisionRecord ( this ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( ourCollidedSpheres > 0 & & ( collidingEnt - > IsBuilding ( ) | | collidingEnt - > GetIsStatic ( ) ) ) {
bHasHitWall = true ;
}
}
if ( collidingEnt - > IsBuilding ( ) | | collidingEnt - > GetIsStatic ( ) ) {
if ( bWasStanding ) {
CVector sphereNormal ;
float normalLength ;
for ( int sphere = 0 ; sphere < ourCollidedSpheres ; sphere + + ) {
sphereNormal = collidingPoints [ sphere ] . normal ;
# ifdef VC_PED_PORTS
if ( sphereNormal . z > = - 1.0f | | ! IsPlayer ( ) ) {
# endif
normalLength = sphereNormal . Magnitude2D ( ) ;
if ( normalLength ! = 0.0f ) {
sphereNormal . x = sphereNormal . x / normalLength ;
sphereNormal . y = sphereNormal . y / normalLength ;
}
# ifdef VC_PED_PORTS
} else {
float speed = m_vecMoveSpeed . Magnitude2D ( ) ;
sphereNormal . x = - m_vecMoveSpeed . x / Max ( 0.001f , speed ) ;
sphereNormal . y = - m_vecMoveSpeed . y / Max ( 0.001f , speed ) ;
GetMatrix ( ) . GetPosition ( ) . z - = 0.05f ;
bSomeVCflag1 = true ;
}
# endif
sphereNormal . Normalise ( ) ;
collidingPoints [ sphere ] . normal = sphereNormal ;
if ( collidingPoints [ sphere ] . surfaceB = = SURFACE_STEEP_CLIFF )
bHitSteepSlope = true ;
}
}
}
return ourCollidedSpheres ;
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
static void
particleProduceFootSplash ( CPed * ped , CVector const & pos , float size , int times )
2019-07-17 22:26:46 -04:00
{
2020-11-19 14:12:20 -05:00
# ifdef PC_PARTICLE
for ( int i = 0 ; i < times ; i + + ) {
CVector adjustedPos = pos ;
adjustedPos . x + = CGeneral : : GetRandomNumberInRange ( - 0.1f , 0.1f ) ;
adjustedPos . y + = CGeneral : : GetRandomNumberInRange ( - 0.1f , 0.1f ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
CVector direction = ped - > GetForward ( ) * - 0.05f ;
CParticle : : AddParticle ( PARTICLE_RAIN_SPLASHUP , adjustedPos , direction , nil , size , CRGBA ( 32 , 32 , 32 , 32 ) , 0 , 0 , CGeneral : : GetRandomNumber ( ) & 1 , 200 ) ;
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
# else
for ( int32 i = 0 ; i < times ; i + + )
{
CVector adjustedPos = pos ;
adjustedPos . x + = CGeneral : : GetRandomNumberInRange ( - 0.2f , 0.2f ) ;
adjustedPos . y + = CGeneral : : GetRandomNumberInRange ( - 0.2f , 0.2f ) ;
CParticle : : AddParticle ( PARTICLE_RAIN_SPLASHUP , adjustedPos , CVector ( 0.0f , 0.0f , 0.0f ) , nil , size , CRGBA ( 0 , 0 , 0 , 0 ) , 0 , 0 , CGeneral : : GetRandomNumber ( ) & 1 , 200 ) ;
}
# endif
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
static void
particleProduceFootDust ( CPed * ped , CVector const & pos , float size , int times )
{
switch ( ped - > m_nSurfaceTouched )
{
case SURFACE_TARMAC :
case SURFACE_GRAVEL :
case SURFACE_PAVEMENT :
case SURFACE_SAND :
for ( int i = 0 ; i < times ; + + i ) {
CVector adjustedPos = pos ;
adjustedPos . x + = CGeneral : : GetRandomNumberInRange ( - 0.1f , 0.1f ) ;
adjustedPos . y + = CGeneral : : GetRandomNumberInRange ( - 0.1f , 0.1f ) ;
CParticle : : AddParticle ( PARTICLE_PEDFOOT_DUST , adjustedPos , CVector ( 0.0f , 0.0f , 0.0f ) , nil , size , CRGBA ( 0 , 0 , 0 , 0 ) , 0 , 0 , 0 , 0 ) ;
}
break ;
default :
break ;
}
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : PlayFootSteps ( void )
{
if ( bDoBloodyFootprints ) {
if ( m_bloodyFootprintCountOrDeathTime > 0 & & m_bloodyFootprintCountOrDeathTime < 300 ) {
m_bloodyFootprintCountOrDeathTime - - ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( m_bloodyFootprintCountOrDeathTime = = 0 )
bDoBloodyFootprints = false ;
2019-07-17 22:26:46 -04:00
}
}
2020-11-19 14:12:20 -05:00
if ( ! bIsStanding )
return ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * assoc = RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) ) ;
CAnimBlendAssociation * walkRunAssoc = nil ;
float walkRunAssocBlend = 0.0f , idleAssocBlend = 0.0f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
for ( ; assoc ; assoc = RpAnimBlendGetNextAssociation ( assoc ) ) {
if ( assoc - > flags & ASSOC_WALK ) {
walkRunAssoc = assoc ;
walkRunAssocBlend + = assoc - > blendAmount ;
} else if ( ( assoc - > flags & ASSOC_NOWALK ) = = 0 ) {
idleAssocBlend + = assoc - > blendAmount ;
2019-07-17 22:26:46 -04:00
}
}
2020-11-19 14:12:20 -05:00
# ifdef GTA_PS2_STUFF
CAnimBlendAssociation * runStopAsoc = NULL ;
if ( IsPlayer ( ) )
{
runStopAsoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_RUN_STOP ) ;
if ( runStopAsoc = = NULL )
runStopAsoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_RUN_STOP_R ) ;
}
if ( runStopAsoc ! = NULL & & runStopAsoc - > blendAmount > 0.1f )
{
{
CVector pos ( 0.0f , 0.0f , 0.0f ) ;
TransformToNode ( pos , PED_FOOTL ) ;
pos . z - = 0.1f ;
pos + = GetForward ( ) * 0.2f ;
particleProduceFootDust ( this , pos , 0.02f , 1 ) ;
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
{
CVector pos ( 0.0f , 0.0f , 0.0f ) ;
TransformToNode ( pos , PED_FOOTR ) ;
pos . z - = 0.1f ;
pos + = GetForward ( ) * 0.2f ;
particleProduceFootDust ( this , pos , 0.02f , 1 ) ;
2019-07-17 22:26:46 -04:00
}
}
2020-11-19 14:12:20 -05:00
# endif
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( walkRunAssoc & & walkRunAssocBlend > 0.5f & & idleAssocBlend < 1.0f ) {
float stepStart = 1 / 15.0f ;
float stepEnd = walkRunAssoc - > hierarchy - > totalLength / 2.0f + stepStart ;
float currentTime = walkRunAssoc - > currentTime ;
int stepPart = 0 ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( currentTime > = stepStart & & currentTime - walkRunAssoc - > timeStep < stepStart )
stepPart = 1 ;
else if ( currentTime > = stepEnd & & currentTime - walkRunAssoc - > timeStep < stepEnd )
stepPart = 2 ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( stepPart ! = 0 ) {
DMAudio . PlayOneShot ( m_audioEntityId , stepPart = = 1 ? SOUND_STEP_START : SOUND_STEP_END , 1.0f ) ;
CVector footPos ( 0.0f , 0.0f , 0.0f ) ;
TransformToNode ( footPos , stepPart = = 1 ? PED_FOOTL : PED_FOOTR ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
CVector forward = GetForward ( ) ;
footPos . z - = 0.1f ;
footPos + = 0.2f * forward ;
if ( bDoBloodyFootprints ) {
CVector2D top ( forward * 0.26f ) ;
CVector2D right ( GetRight ( ) * 0.14f ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
CShadows : : AddPermanentShadow ( SHADOWTYPE_DARK , gpBloodPoolTex , & footPos ,
top . x , top . y ,
right . x , right . y ,
255 , 255 , 0 , 0 , 4.0f , 3000.0f , 1.0f ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( m_bloodyFootprintCountOrDeathTime < = 20 ) {
m_bloodyFootprintCountOrDeathTime = 0 ;
bDoBloodyFootprints = false ;
2019-09-26 17:01:50 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_bloodyFootprintCountOrDeathTime - = 20 ;
2019-09-26 17:01:50 -04:00
}
}
2020-11-19 14:12:20 -05:00
if ( CWeather : : Rain < = 0.1f | | CCullZones : : CamNoRain ( ) | | CCullZones : : PlayerNoRain ( ) ) {
if ( IsPlayer ( ) )
particleProduceFootDust ( this , footPos , 0.0f , 4 ) ;
}
# ifdef PC_PARTICLE
else if ( stepPart = = 2 )
# else
else
2019-09-26 17:01:50 -04:00
# endif
2020-11-19 14:12:20 -05:00
{
particleProduceFootSplash ( this , footPos , 0.15f , 4 ) ;
}
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nSurfaceTouched = = SURFACE_WATER ) {
float pedSpeed = CVector2D ( m_vecMoveSpeed ) . Magnitude ( ) ;
if ( pedSpeed > 0.03f & & CTimer : : GetFrameCounter ( ) % 2 = = 0 & & pedSpeed > 0.13f ) {
# ifdef PC_PARTICLE
float particleSize = pedSpeed * 2.0f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
if ( particleSize < 0.25f )
particleSize = 0.25f ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( particleSize > 0.75f )
particleSize = 0.75f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
CVector particlePos = GetPosition ( ) + GetForward ( ) * 0.3f ;
particlePos . z - = 1.2f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
CVector particleDir = m_vecMoveSpeed * - 0.75f ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
particleDir . z = CGeneral : : GetRandomNumberInRange ( 0.01f , 0.03f ) ;
CParticle : : AddParticle ( PARTICLE_PED_SPLASH , particlePos , particleDir , nil , 0.8f * particleSize , CRGBA ( 155 , 155 , 185 , 128 ) , 0 , 0 , 0 , 0 ) ;
particleDir . z = CGeneral : : GetRandomNumberInRange ( 0.03f , 0.05f ) ;
CParticle : : AddParticle ( PARTICLE_RUBBER_SMOKE , particlePos , particleDir , nil , particleSize , CRGBA ( 255 , 255 , 255 , 255 ) , 0 , 0 , 0 , 0 ) ;
# else
CVector particlePos = ( GetPosition ( ) - 0.3f * GetUp ( ) ) + GetForward ( ) * 0.3f ;
CVector particleDir = m_vecMoveSpeed * 0.45f ;
particleDir . z = CGeneral : : GetRandomNumberInRange ( 0.03f , 0.05f ) ;
CParticle : : AddParticle ( PARTICLE_PED_SPLASH , particlePos - CVector ( 0.0f , 0.0f , 1.2f ) , particleDir , nil , 0.0f , CRGBA ( 155 , 185 , 155 , 255 ) ) ;
# endif
}
}
2019-07-17 22:26:46 -04:00
}
2020-11-19 14:12:20 -05:00
// Actually GetLocalDirectionTo(Turn/Look)
int
CPed : : GetLocalDirection ( const CVector2D & posOffset )
2019-07-17 22:26:46 -04:00
{
2020-11-19 14:12:20 -05:00
int direction ;
float angle ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
for ( angle = posOffset . Heading ( ) - m_fRotationCur + DEGTORAD ( 45.0f ) ; angle < 0.0f ; angle + = TWOPI ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
for ( direction = RADTODEG ( angle ) / 90.0f ; direction > 3 ; direction - = 4 ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
// 0-forward, 1-left, 2-backward, 3-right.
return direction ;
}
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
# ifdef NEW_WALK_AROUND_ALGORITHM
CVector
LocalPosForWalkAround ( CVector2D colMin , CVector2D colMax , int walkAround , uint32 enterDoorNode , bool itsVan ) {
switch ( walkAround ) {
case 0 :
if ( enterDoorNode = = CAR_DOOR_LF )
return CVector ( colMin . x , colMax . y - 1.0f , 0.0f ) ;
case 1 :
return CVector ( colMin . x , colMax . y , 0.0f ) ;
case 2 :
case 3 :
if ( walkAround = = 3 & & enterDoorNode = = CAR_DOOR_RF )
return CVector ( colMax . x , colMax . y - 1.0f , 0.0f ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
return CVector ( colMax . x , colMax . y , 0.0f ) ;
case 4 :
if ( enterDoorNode = = CAR_DOOR_RR & & ! itsVan )
return CVector ( colMax . x , colMin . y + 1.0f , 0.0f ) ;
case 5 :
return CVector ( colMax . x , colMin . y , 0.0f ) ;
case 6 :
case 7 :
if ( walkAround = = 7 & & enterDoorNode = = CAR_DOOR_LR & & ! itsVan )
return CVector ( colMin . x , colMin . y + 1.0f , 0.0f ) ;
2019-07-17 22:26:46 -04:00
2020-11-19 14:12:20 -05:00
return CVector ( colMin . x , colMin . y , 0.0f ) ;
default :
return CVector ( 0.0f , 0.0f , 0.0f ) ;
2019-07-17 22:26:46 -04:00
}
}
2020-11-19 14:12:20 -05:00
bool
CanWeSeeTheCorner ( CVector2D dist , CVector2D fwdOffset )
2019-07-20 17:29:58 -04:00
{
2020-11-19 14:12:20 -05:00
// because fov isn't important if dist is more then 5 unit, we want shortest way
if ( dist . Magnitude ( ) > 5.0f )
return true ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
if ( DotProduct2D ( dist , fwdOffset ) < 0.0f )
return false ;
return true ;
2019-07-20 17:29:58 -04:00
}
2020-11-19 14:12:20 -05:00
# endif
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
// This function looks completely same on VC.
2019-07-20 17:29:58 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : SetDirectionToWalkAroundObject ( CEntity * obj )
2019-07-20 17:29:58 -04:00
{
2020-11-19 14:12:20 -05:00
float distLimitForTimer = 8.0f ;
CColModel * objCol = CModelInfo : : GetModelInfo ( obj - > GetModelIndex ( ) ) - > GetColModel ( ) ;
CVector objColMin = objCol - > boundingBox . min ;
CVector objColMax = objCol - > boundingBox . max ;
CVector objColCenter = ( objColMin + objColMax ) / 2.0f ;
CMatrix objMat ( obj - > GetMatrix ( ) ) ;
float dirToSet = obj - > GetForward ( ) . Heading ( ) ;
bool goingToEnterCarAndItsVan = false ;
bool goingToEnterCar = false ;
bool objUpsideDown = false ;
float checkIntervalInDist = ( objColMax . y - objColMin . y ) * 0.1f ;
float checkIntervalInTime ;
if ( m_nMoveState = = PEDMOVE_NONE | | m_nMoveState = = PEDMOVE_STILL )
2019-07-20 17:29:58 -04:00
return ;
2020-11-19 14:12:20 -05:00
# ifndef PEDS_REPORT_CRIMES_ON_PHONE
if ( CharCreatedBy ! = MISSION_CHAR & & obj - > GetModelIndex ( ) = = MI_PHONEBOOTH1 ) {
bool isRunning = m_nMoveState = = PEDMOVE_RUN | | m_nMoveState = = PEDMOVE_SPRINT ;
SetFindPathAndFlee ( obj , 5000 , ! isRunning ) ;
return ;
2019-07-20 17:29:58 -04:00
}
2020-11-19 14:12:20 -05:00
# endif
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
CVector2D adjustedColMin ( objColMin . x - 0.35f , objColMin . y - 0.35f ) ;
CVector2D adjustedColMax ( objColMax . x + 0.35f , objColMax . y + 0.35f ) ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
checkIntervalInDist = Max ( checkIntervalInDist , 0.5f ) ;
checkIntervalInDist = Min ( checkIntervalInDist , ( objColMax . z - objColMin . z ) / 2.0f ) ;
checkIntervalInDist = Min ( checkIntervalInDist , ( adjustedColMax . x - adjustedColMin . x ) / 2.0f ) ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
if ( objMat . GetUp ( ) . z < 0.0f )
objUpsideDown = true ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( obj - > GetModelIndex ( ) ! = MI_TRAFFICLIGHTS & & obj - > GetModelIndex ( ) ! = MI_SINGLESTREETLIGHTS1 & & obj - > GetModelIndex ( ) ! = MI_SINGLESTREETLIGHTS2 ) {
objColCenter = obj - > GetMatrix ( ) * objColCenter ;
} else {
checkIntervalInDist = 0.4f ;
if ( objMat . GetUp ( ) . z < = 0.57f ) {
// Specific calculations for traffic lights, didn't get a bit.
adjustedColMin . x = 1.2f * ( adjustedColMin . x < adjustedColMin . y ? adjustedColMin . x : adjustedColMin . y ) ;
adjustedColMax . x = 1.2f * ( adjustedColMax . x > adjustedColMax . y ? adjustedColMax . x : adjustedColMax . y ) ;
adjustedColMin . y = 1.2f * objColMin . z ;
adjustedColMax . y = 1.2f * objColMax . z ;
dirToSet = objMat . GetUp ( ) . Heading ( ) ;
objMat . SetUnity ( ) ;
objMat . RotateZ ( dirToSet ) ;
objMat . GetPosition ( ) + = obj - > GetPosition ( ) ;
objColCenter = obj - > GetPosition ( ) ;
2019-07-20 17:29:58 -04:00
} else {
2020-11-19 14:12:20 -05:00
objColCenter . x = adjustedColMax . x - 0.25f ;
objColCenter = obj - > GetMatrix ( ) * objColCenter ;
distLimitForTimer = 0.75f ;
2019-07-20 17:29:58 -04:00
}
2020-11-19 14:12:20 -05:00
objUpsideDown = false ;
2019-07-20 17:29:58 -04:00
}
2020-11-19 14:12:20 -05:00
float oldRotDest = m_fRotationDest ;
# ifndef NEW_WALK_AROUND_ALGORITHM
float angleToFaceObjCenter = ( objColCenter - GetPosition ( ) ) . Heading ( ) ;
float angleDiffBtwObjCenterAndForward = CGeneral : : LimitRadianAngle ( dirToSet - angleToFaceObjCenter ) ;
float objTopRightHeading = Atan2 ( adjustedColMax . x - adjustedColMin . x , adjustedColMax . y - adjustedColMin . y ) ;
# endif
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) ) {
if ( FindPlayerPed ( ) - > m_fMoveSpeed < = 0.0f )
checkIntervalInTime = 0.0f ;
else
checkIntervalInTime = 2.0f / FindPlayerPed ( ) - > m_fMoveSpeed ;
} else {
switch ( m_nMoveState ) {
case PEDMOVE_WALK :
checkIntervalInTime = 2.0f ;
break ;
case PEDMOVE_RUN :
checkIntervalInTime = 0.5f ;
break ;
case PEDMOVE_SPRINT :
checkIntervalInTime = 0.5f ;
break ;
default :
checkIntervalInTime = 0.0f ;
break ;
}
}
if ( m_pSeekTarget = = obj & & obj - > IsVehicle ( ) ) {
if ( m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER | | m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER
| | m_objective = = OBJECTIVE_SOLICIT_VEHICLE ) {
goingToEnterCar = true ;
if ( IsPlayer ( ) )
checkIntervalInTime = 0.0f ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ( ( CVehicle * ) obj ) - > bIsVan )
goingToEnterCarAndItsVan = true ;
}
}
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
int entityOnTopLeftOfObj = 0 ;
int entityOnBottomLeftOfObj = 0 ;
int entityOnTopRightOfObj = 0 ;
int entityOnBottomRightOfObj = 0 ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) > m_collidingThingTimer | | m_collidingEntityWhileFleeing ! = obj ) {
bool collidingThingChanged = true ;
CEntity * obstacle ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
# ifndef NEW_WALK_AROUND_ALGORITHM
if ( ! obj - > IsVehicle ( ) | | objUpsideDown ) {
collidingThingChanged = false ;
} else {
# else
CVector cornerToGo = CVector ( 10.0f , 10.0f , 10.0f ) ;
int dirToGo ;
m_walkAroundType = 0 ;
int iWouldPreferGoingBack = 0 ; // 1:left 2:right
# endif
float adjustedCheckInterval = 0.7f * checkIntervalInDist ;
CVector posToCheck ;
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
// Top left of obj
posToCheck . x = adjustedColMin . x + adjustedCheckInterval ;
posToCheck . y = adjustedColMax . y - adjustedCheckInterval ;
posToCheck . z = 0.0f ;
posToCheck = objMat * posToCheck ;
posToCheck . z + = 0.6f ;
obstacle = CWorld : : TestSphereAgainstWorld ( posToCheck , checkIntervalInDist , obj ,
true , true , false , true , false , false ) ;
if ( obstacle ) {
if ( obstacle - > IsBuilding ( ) ) {
entityOnTopLeftOfObj = 1 ;
} else if ( obstacle - > IsVehicle ( ) ) {
entityOnTopLeftOfObj = 2 ;
} else {
entityOnTopLeftOfObj = 3 ;
2019-07-20 17:29:58 -04:00
}
}
2020-11-19 14:12:20 -05:00
# ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector tl = obj - > GetMatrix ( ) * CVector ( adjustedColMin . x , adjustedColMax . y , 0.0f ) - GetPosition ( ) ;
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_LF | | m_vehDoor = = CAR_DOOR_LR ) ) {
2020-11-19 14:12:20 -05:00
cornerToGo = tl ;
m_walkAroundType = 1 ;
2019-07-20 17:29:58 -04:00
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_LR )
2020-11-19 14:12:20 -05:00
iWouldPreferGoingBack = 1 ;
} else if ( CanWeSeeTheCorner ( tl , GetForward ( ) ) ) {
cornerToGo = tl ;
dirToGo = GetLocalDirection ( tl ) ;
if ( dirToGo = = 1 )
m_walkAroundType = 0 ; // ALL of the next turns will be right turn
else if ( dirToGo = = 3 )
m_walkAroundType = 1 ; // ALL of the next turns will be left turn
}
}
# endif
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
// Top right of obj
posToCheck . x = adjustedColMax . x - adjustedCheckInterval ;
posToCheck . y = adjustedColMax . y - adjustedCheckInterval ;
posToCheck . z = 0.0f ;
posToCheck = objMat * posToCheck ;
posToCheck . z + = 0.6f ;
obstacle = CWorld : : TestSphereAgainstWorld ( posToCheck , checkIntervalInDist , obj ,
true , true , false , true , false , false ) ;
if ( obstacle ) {
if ( obstacle - > IsBuilding ( ) ) {
entityOnTopRightOfObj = 1 ;
} else if ( obstacle - > IsVehicle ( ) ) {
entityOnTopRightOfObj = 2 ;
} else {
entityOnTopRightOfObj = 3 ;
}
}
# ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector tr = obj - > GetMatrix ( ) * CVector ( adjustedColMax . x , adjustedColMax . y , 0.0f ) - GetPosition ( ) ;
if ( tr . Magnitude2D ( ) < cornerToGo . Magnitude2D ( ) ) {
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_RF | | m_vehDoor = = CAR_DOOR_RR ) ) {
2020-11-19 14:12:20 -05:00
cornerToGo = tr ;
m_walkAroundType = 2 ;
2019-07-20 17:29:58 -04:00
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_RR )
2020-11-19 14:12:20 -05:00
iWouldPreferGoingBack = 2 ;
} else if ( CanWeSeeTheCorner ( tr , GetForward ( ) ) ) {
cornerToGo = tr ;
dirToGo = GetLocalDirection ( tr ) ;
if ( dirToGo = = 1 )
m_walkAroundType = 2 ; // ALL of the next turns will be right turn
else if ( dirToGo = = 3 )
m_walkAroundType = 3 ; // ALL of the next turns will be left turn
}
}
}
# endif
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
// Bottom right of obj
posToCheck . x = adjustedColMax . x - adjustedCheckInterval ;
posToCheck . y = adjustedColMin . y + adjustedCheckInterval ;
posToCheck . z = 0.0f ;
posToCheck = objMat * posToCheck ;
posToCheck . z + = 0.6f ;
obstacle = CWorld : : TestSphereAgainstWorld ( posToCheck , checkIntervalInDist , obj ,
true , true , false , true , false , false ) ;
if ( obstacle ) {
if ( obstacle - > IsBuilding ( ) ) {
entityOnBottomRightOfObj = 1 ;
} else if ( obstacle - > IsVehicle ( ) ) {
entityOnBottomRightOfObj = 2 ;
} else {
entityOnBottomRightOfObj = 3 ;
}
2019-07-20 17:29:58 -04:00
}
2020-11-19 14:12:20 -05:00
# ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector br = obj - > GetMatrix ( ) * CVector ( adjustedColMax . x , adjustedColMin . y , 0.0f ) - GetPosition ( ) ;
if ( iWouldPreferGoingBack = = 2 )
m_walkAroundType = 4 ;
else if ( br . Magnitude2D ( ) < cornerToGo . Magnitude2D ( ) ) {
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_RF | | m_vehDoor = = CAR_DOOR_RR ) ) {
2020-11-19 14:12:20 -05:00
cornerToGo = br ;
m_walkAroundType = 5 ;
} else if ( CanWeSeeTheCorner ( br , GetForward ( ) ) ) {
cornerToGo = br ;
dirToGo = GetLocalDirection ( br ) ;
if ( dirToGo = = 1 )
m_walkAroundType = 4 ; // ALL of the next turns will be right turn
else if ( dirToGo = = 3 )
m_walkAroundType = 5 ; // ALL of the next turns will be left turn
}
}
}
# endif
2019-07-20 17:29:58 -04:00
2020-11-19 14:12:20 -05:00
// Bottom left of obj
posToCheck . x = adjustedColMin . x + adjustedCheckInterval ;
posToCheck . y = adjustedColMin . y + adjustedCheckInterval ;
posToCheck . z = 0.0f ;
posToCheck = objMat * posToCheck ;
posToCheck . z + = 0.6f ;
obstacle = CWorld : : TestSphereAgainstWorld ( posToCheck , checkIntervalInDist , obj ,
true , true , false , true , false , false ) ;
if ( obstacle ) {
if ( obstacle - > IsBuilding ( ) ) {
entityOnBottomLeftOfObj = 1 ;
} else if ( obstacle - > IsVehicle ( ) ) {
entityOnBottomLeftOfObj = 2 ;
} else {
entityOnBottomLeftOfObj = 3 ;
}
}
# ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector bl = obj - > GetMatrix ( ) * CVector ( adjustedColMin . x , adjustedColMin . y , 0.0f ) - GetPosition ( ) ;
if ( iWouldPreferGoingBack = = 1 )
m_walkAroundType = 7 ;
else if ( bl . Magnitude2D ( ) < cornerToGo . Magnitude2D ( ) ) {
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_LF | | m_vehDoor = = CAR_DOOR_LR ) ) {
2020-11-19 14:12:20 -05:00
cornerToGo = bl ;
m_walkAroundType = 6 ;
} else if ( CanWeSeeTheCorner ( bl , GetForward ( ) ) ) {
cornerToGo = bl ;
dirToGo = GetLocalDirection ( bl ) ;
if ( dirToGo = = 1 )
m_walkAroundType = 6 ; // ALL of the next turns will be right turn
else if ( dirToGo = = 3 )
m_walkAroundType = 7 ; // ALL of the next turns will be left turn
2019-07-20 17:29:58 -04:00
}
}
2020-11-19 14:12:20 -05:00
}
# else
2019-07-20 17:29:58 -04:00
}
2020-11-19 14:12:20 -05:00
if ( entityOnTopLeftOfObj & & entityOnTopRightOfObj & & entityOnBottomRightOfObj & & entityOnBottomLeftOfObj ) {
collidingThingChanged = false ;
entityOnTopLeftOfObj = 0 ;
entityOnBottomLeftOfObj = 0 ;
entityOnTopRightOfObj = 0 ;
entityOnBottomRightOfObj = 0 ;
2019-09-11 20:43:18 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ! collidingThingChanged ) {
m_walkAroundType = 0 ;
2019-09-11 20:43:18 -04:00
} else {
2020-11-19 14:12:20 -05:00
if ( Abs ( angleDiffBtwObjCenterAndForward ) > = objTopRightHeading ) {
if ( PI - objTopRightHeading > = Abs ( angleDiffBtwObjCenterAndForward ) ) {
if ( ( angleDiffBtwObjCenterAndForward < = 0.0f | | objUpsideDown ) & & ( angleDiffBtwObjCenterAndForward < 0.0f | | ! objUpsideDown ) ) {
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_RF | | m_vehDoor = = CAR_DOOR_RR ) ) {
2020-11-19 14:12:20 -05:00
m_walkAroundType = 0 ;
} else {
if ( CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) > = 0.0f ) {
if ( entityOnBottomRightOfObj = = 1 | | entityOnBottomRightOfObj & & ! entityOnTopLeftOfObj & & ! entityOnTopRightOfObj ) {
m_walkAroundType = 1 ;
} else if ( entityOnBottomLeftOfObj = = 1 | | entityOnBottomLeftOfObj & & ! entityOnTopLeftOfObj & & ! entityOnTopRightOfObj ) {
m_walkAroundType = 1 ;
}
} else {
if ( entityOnTopRightOfObj = = 1 | | entityOnTopRightOfObj & & ! entityOnBottomRightOfObj & & ! entityOnBottomLeftOfObj ) {
m_walkAroundType = 4 ;
} else if ( entityOnTopLeftOfObj = = 1 | | entityOnTopLeftOfObj & & ! entityOnBottomRightOfObj & & ! entityOnBottomLeftOfObj ) {
m_walkAroundType = 4 ;
}
}
}
} else {
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_LF | | m_vehDoor = = CAR_DOOR_LR ) ) {
2020-11-19 14:12:20 -05:00
m_walkAroundType = 0 ;
} else {
if ( CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) < = 0.0f ) {
if ( entityOnBottomLeftOfObj = = 1 | | entityOnBottomLeftOfObj & & ! entityOnTopLeftOfObj & & ! entityOnTopRightOfObj ) {
m_walkAroundType = 2 ;
} else if ( entityOnBottomRightOfObj = = 1 | | entityOnBottomRightOfObj & & ! entityOnTopLeftOfObj & & ! entityOnTopRightOfObj ) {
m_walkAroundType = 2 ;
}
} else {
if ( entityOnTopLeftOfObj = = 1 | | entityOnTopLeftOfObj & & ! entityOnBottomRightOfObj & & ! entityOnBottomLeftOfObj ) {
m_walkAroundType = 3 ;
} else if ( entityOnTopRightOfObj = = 1 | | entityOnTopRightOfObj & & ! entityOnBottomRightOfObj & & ! entityOnBottomLeftOfObj ) {
m_walkAroundType = 3 ;
}
}
}
}
2021-01-13 07:01:11 -05:00
} else if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_LF | | m_vehDoor = = CAR_DOOR_LR )
2020-11-19 14:12:20 -05:00
| | CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) < 0.0f ) {
if ( entityOnTopLeftOfObj = = 1 | | entityOnTopLeftOfObj & & ! entityOnTopRightOfObj & & ! entityOnBottomRightOfObj ) {
m_walkAroundType = 3 ;
}
} else if ( entityOnTopRightOfObj = = 1 | | entityOnTopRightOfObj & & ! entityOnTopLeftOfObj & & ! entityOnBottomLeftOfObj ) {
m_walkAroundType = 4 ;
}
2021-01-13 07:01:11 -05:00
} else if ( goingToEnterCar & & ( m_vehDoor = = CAR_DOOR_LF | | m_vehDoor = = CAR_DOOR_LR )
2020-11-19 14:12:20 -05:00
| | CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) > 0.0f ) {
if ( entityOnBottomLeftOfObj = = 1 | | entityOnBottomLeftOfObj & & ! entityOnTopRightOfObj & & ! entityOnBottomRightOfObj ) {
m_walkAroundType = 2 ;
}
} else if ( entityOnBottomRightOfObj = = 1 | | entityOnBottomRightOfObj & & ! entityOnTopLeftOfObj & & ! entityOnBottomLeftOfObj ) {
m_walkAroundType = 1 ;
2020-02-03 13:03:48 -05:00
} else {
2020-11-19 14:12:20 -05:00
m_walkAroundType = 0 ;
2020-02-03 13:03:48 -05:00
}
}
# endif
2019-09-13 15:04:55 -04:00
}
2020-11-19 14:12:20 -05:00
m_collidingEntityWhileFleeing = obj ;
m_collidingEntityWhileFleeing - > RegisterReference ( ( CEntity * * ) & m_collidingEntityWhileFleeing ) ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
// TODO: This random may need to be changed.
m_collidingThingTimer = CTimer : : GetTimeInMilliseconds ( ) + 512 + CGeneral : : GetRandomNumber ( ) ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
CVector localPosToHead ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
# ifdef NEW_WALK_AROUND_ALGORITHM
int nextWalkAround = m_walkAroundType ;
if ( m_walkAroundType % 2 = = 0 ) {
nextWalkAround + = 2 ;
if ( nextWalkAround > 6 )
nextWalkAround = 0 ;
} else {
nextWalkAround - = 2 ;
if ( nextWalkAround < 0 )
nextWalkAround = 7 ;
2019-09-13 15:04:55 -04:00
}
2021-01-13 07:01:11 -05:00
CVector nextPosToHead = objMat * LocalPosForWalkAround ( adjustedColMin , adjustedColMax , nextWalkAround , goingToEnterCar ? m_vehDoor : 0 , goingToEnterCarAndItsVan ) ;
2020-11-19 14:12:20 -05:00
bool nextRouteIsClear = CWorld : : GetIsLineOfSightClear ( GetPosition ( ) , nextPosToHead , true , true , true , true , true , true , false ) ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
if ( nextRouteIsClear )
m_walkAroundType = nextWalkAround ;
else {
2021-01-13 07:01:11 -05:00
CVector posToHead = objMat * LocalPosForWalkAround ( adjustedColMin , adjustedColMax , m_walkAroundType , goingToEnterCar ? m_vehDoor : 0 , goingToEnterCarAndItsVan ) ;
2020-11-19 14:12:20 -05:00
bool currentRouteIsClear = CWorld : : GetIsLineOfSightClear ( GetPosition ( ) , posToHead ,
true , true , true , true , true , true , false ) ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
/* Either;
* - Some obstacle came in and it ' s impossible to reach current destination
* - We reached to the destination , but since next route is not clear , we ' re turning around us
*/
if ( ! currentRouteIsClear | |
( ( posToHead - GetPosition ( ) ) . Magnitude2D ( ) < 0.8f & &
! CWorld : : GetIsLineOfSightClear ( GetPosition ( ) + GetForward ( ) , nextPosToHead ,
true , true , true , true , true , true , false ) ) ) {
// Change both target and direction (involves changing even/oddness)
if ( m_walkAroundType % 2 = = 0 ) {
m_walkAroundType - = 2 ;
if ( m_walkAroundType < 0 )
m_walkAroundType = 7 ;
else
m_walkAroundType + = 1 ;
} else {
m_walkAroundType + = 2 ;
if ( m_walkAroundType > 7 )
m_walkAroundType = 0 ;
else
m_walkAroundType - = 1 ;
2019-11-09 10:17:54 -05:00
}
2019-09-13 15:04:55 -04:00
}
2020-02-03 13:03:48 -05:00
}
2019-09-13 15:04:55 -04:00
2021-01-13 07:01:11 -05:00
localPosToHead = LocalPosForWalkAround ( adjustedColMin , adjustedColMax , m_walkAroundType , goingToEnterCar ? m_vehDoor : 0 , goingToEnterCarAndItsVan ) ;
2020-11-19 14:12:20 -05:00
# else
if ( Abs ( angleDiffBtwObjCenterAndForward ) < objTopRightHeading ) {
if ( goingToEnterCar ) {
if ( goingToEnterCarAndItsVan ) {
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_LR | | m_vehDoor = = CAR_DOOR_RR )
2020-11-19 14:12:20 -05:00
return ;
}
2021-01-13 07:01:11 -05:00
if ( m_vehDoor ! = CAR_DOOR_LF & & m_vehDoor ! = CAR_DOOR_LR & & ( ! entityOnBottomRightOfObj | | entityOnBottomLeftOfObj ) ) {
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( dirToSet - HALFPI ) ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
} else {
m_fRotationDest = CGeneral : : LimitRadianAngle ( HALFPI + dirToSet ) ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
}
} else {
if ( m_walkAroundType ! = 1 & & m_walkAroundType ! = 4
& & ( m_walkAroundType | | CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) < = 0.0f ) ) {
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( dirToSet - HALFPI ) ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
} else {
m_fRotationDest = CGeneral : : LimitRadianAngle ( HALFPI + dirToSet ) ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
}
2019-09-13 15:04:55 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
if ( PI - objTopRightHeading > = Abs ( angleDiffBtwObjCenterAndForward ) ) {
if ( angleDiffBtwObjCenterAndForward < = 0.0f ) {
2021-01-13 07:01:11 -05:00
if ( ! goingToEnterCar | | ! goingToEnterCarAndItsVan | | m_vehDoor ! = CAR_DOOR_LR & & m_vehDoor ! = CAR_DOOR_RR ) {
2020-11-19 14:12:20 -05:00
if ( goingToEnterCar ) {
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_RF | | ( m_vehDoor = = CAR_DOOR_RR & & ! goingToEnterCarAndItsVan ) )
2020-11-19 14:12:20 -05:00
return ;
}
if ( m_walkAroundType = = 4 | | m_walkAroundType = = 3
| | ! m_walkAroundType & & CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) > 0.0f ) {
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( PI + dirToSet ) ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
} else {
m_fRotationDest = dirToSet ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMax . y ;
}
} else {
m_fRotationDest = CGeneral : : LimitRadianAngle ( PI + dirToSet ) ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
}
2021-01-13 07:01:11 -05:00
} else if ( goingToEnterCar & & goingToEnterCarAndItsVan & & ( m_vehDoor = = CAR_DOOR_LR | | m_vehDoor = = CAR_DOOR_RR ) ) {
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( PI + dirToSet ) ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
} else {
if ( goingToEnterCar ) {
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_LF | | m_vehDoor = = CAR_DOOR_LR & & ! goingToEnterCarAndItsVan )
2020-11-19 14:12:20 -05:00
return ;
}
if ( m_walkAroundType = = 1 | | m_walkAroundType = = 2
| | ! m_walkAroundType & & CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) > 0.0f ) {
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationDest = dirToSet ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMax . y ;
} else {
m_fRotationDest = CGeneral : : LimitRadianAngle ( PI + dirToSet ) ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMin . y ;
}
}
} else {
2021-01-13 07:01:11 -05:00
if ( goingToEnterCar & & ( ! goingToEnterCarAndItsVan | | m_vehDoor ! = CAR_DOOR_LR & & m_vehDoor ! = CAR_DOOR_RR ) ) {
if ( m_vehDoor ! = CAR_DOOR_LF & & m_vehDoor ! = CAR_DOOR_LR & & ( ! entityOnTopRightOfObj | | entityOnTopLeftOfObj ) ) {
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( dirToSet - HALFPI ) ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMax . y ;
} else {
m_fRotationDest = CGeneral : : LimitRadianAngle ( HALFPI + dirToSet ) ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMax . y ;
}
} else {
if ( m_walkAroundType = = 2 | | m_walkAroundType = = 3
| | ! m_walkAroundType & & CGeneral : : LimitRadianAngle ( m_fRotationDest - angleToFaceObjCenter ) > 0.0f ) {
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( dirToSet - HALFPI ) ;
localPosToHead . x = adjustedColMax . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMax . y ;
} else {
m_fRotationDest = CGeneral : : LimitRadianAngle ( HALFPI + dirToSet ) ;
localPosToHead . x = adjustedColMin . x ;
localPosToHead . z = 0.0f ;
localPosToHead . y = adjustedColMax . y ;
}
2020-05-11 19:24:57 -04:00
}
2019-09-13 15:04:55 -04:00
}
}
2020-11-19 14:12:20 -05:00
# endif
if ( objUpsideDown )
localPosToHead . x = localPosToHead . x * - 1.0f ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
localPosToHead = objMat * localPosToHead ;
m_actionX = localPosToHead . x ;
m_actionY = localPosToHead . y ;
localPosToHead - = GetPosition ( ) ;
m_fRotationDest = CGeneral : : LimitRadianAngle ( localPosToHead . Heading ( ) ) ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
if ( m_fRotationDest ! = m_fRotationCur & & bHitSomethingLastFrame ) {
if ( m_fRotationDest = = oldRotDest ) {
m_fRotationDest = oldRotDest ;
2019-09-13 15:04:55 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( PI + dirToSet ) ;
2019-09-13 15:04:55 -04:00
}
}
2020-11-19 14:12:20 -05:00
float dist = localPosToHead . Magnitude2D ( ) ;
if ( dist < 0.5f )
dist = 0.5f ;
2019-09-13 15:04:55 -04:00
2020-11-19 14:12:20 -05:00
if ( dist > distLimitForTimer )
dist = distLimitForTimer ;
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( ) + 280.0f * dist * checkIntervalInTime ;
2019-09-13 15:04:55 -04:00
}
2020-11-19 14:12:20 -05:00
bool
CPed : : IsPedInControl ( void )
2019-09-13 15:04:55 -04:00
{
2020-11-19 14:12:20 -05:00
return m_nPedState < = PED_STATES_NO_AI
& & ! bIsInTheAir & & ! bIsLanding
& & m_fHealth > 0.0f ;
2019-09-13 15:04:55 -04:00
}
2020-11-19 14:12:20 -05:00
bool
CPed : : IsPedShootable ( void )
2019-09-16 13:32:58 -04:00
{
2020-11-19 14:12:20 -05:00
return m_nPedState < = PED_STATES_NO_ST ;
2019-09-16 13:32:58 -04:00
}
bool
2020-11-19 14:12:20 -05:00
CPed : : UseGroundColModel ( void )
2019-09-16 13:32:58 -04:00
{
2020-11-19 14:12:20 -05:00
return m_nPedState = = PED_FALL | |
m_nPedState = = PED_DIVE_AWAY | |
m_nPedState = = PED_DIE | |
m_nPedState = = PED_DEAD ;
}
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : CanPedReturnToState ( void )
{
return m_nPedState < = PED_STATES_NO_AI & & m_nPedState ! = PED_AIM_GUN & & m_nPedState ! = PED_ATTACK & &
m_nPedState ! = PED_FIGHT & & m_nPedState ! = PED_STEP_AWAY & & m_nPedState ! = PED_SNIPER_MODE & & m_nPedState ! = PED_LOOK_ENTITY ;
}
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : CanSetPedState ( void )
{
return ! DyingOrDead ( ) & & m_nPedState ! = PED_ARRESTED & & ! EnteringCar ( ) & & m_nPedState ! = PED_STEAL_CAR ;
}
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : CanStrafeOrMouseControl ( void )
{
# ifdef FREE_CAM
if ( CCamera : : bFreeCam )
2019-09-16 13:32:58 -04:00
return false ;
2020-07-01 08:28:43 -04:00
# endif
2020-11-19 14:12:20 -05:00
return m_nPedState = = PED_NONE | | m_nPedState = = PED_IDLE | | m_nPedState = = PED_FLEE_POS | | m_nPedState = = PED_FLEE_ENTITY | |
m_nPedState = = PED_ATTACK | | m_nPedState = = PED_FIGHT | | m_nPedState = = PED_AIM_GUN | | m_nPedState = = PED_JUMP ;
2019-09-16 13:32:58 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : PedGetupCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-09-16 13:32:58 -04:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedState = = PED_GETUP )
RpAnimBlendClumpSetBlendDeltas ( ped - > GetClump ( ) , ASSOC_PARTIAL , - 1000.0f ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
ped - > bFallenDown = false ;
animAssoc - > blendDelta = - 1000.0f ;
if ( ped - > m_nPedState = = PED_GETUP )
ped - > RestorePreviousState ( ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedState ! = PED_FLEE_POS & & ped - > m_nPedState ! = PED_FLEE_ENTITY )
ped - > SetMoveState ( PEDMOVE_STILL ) ;
else
ped - > SetMoveState ( PEDMOVE_RUN ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
ped - > SetMoveAnim ( ) ;
ped - > bGetUpAnimStarted = false ;
2019-09-16 13:32:58 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : PedLandCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-09-16 13:32:58 -04:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
animAssoc - > blendDelta = - 1000.0f ;
ped - > bIsLanding = false ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedState = = PED_JUMP )
ped - > RestorePreviousState ( ) ;
}
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : PedStaggerCB ( CAnimBlendAssociation * animAssoc , void * arg )
{
/*
CPed * ped = ( CPed * ) arg ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedState = = PED_STAGGER )
// nothing
*/
2019-09-16 13:32:58 -04:00
}
void
CPed : : PedSetOutCarCB ( CAnimBlendAssociation * animAssoc , void * arg )
{
CPed * ped = ( CPed * ) arg ;
CVehicle * veh = ped - > m_pMyVehicle ;
bool startedToRun = false ;
ped - > bUsesCollision = true ;
ped - > m_actionX = 0.0f ;
ped - > m_actionY = 0.0f ;
2020-03-01 19:03:39 -05:00
ped - > bVehExitWillBeInstant = false ;
2019-09-26 17:01:50 -04:00
if ( veh & & veh - > IsBoat ( ) )
2019-09-16 13:32:58 -04:00
ped - > ApplyMoveSpeed ( ) ;
2020-07-03 09:51:33 -04:00
if ( ped - > m_objective = = OBJECTIVE_LEAVE_CAR )
2019-09-16 13:32:58 -04:00
ped - > RestorePreviousObjective ( ) ;
2019-09-26 17:01:50 -04:00
# ifdef VC_PED_PORTS
else if ( ped - > m_objective = = OBJECTIVE_LEAVE_CAR_AND_DIE ) {
ped - > m_fHealth = 0.0f ;
ped - > SetDie ( ANIM_FLOOR_HIT , 4.0f , 0.5f ) ;
}
# endif
2019-09-16 13:32:58 -04:00
ped - > bInVehicle = false ;
2021-01-13 07:01:11 -05:00
if ( veh & & veh - > IsCar ( ) & & ! veh - > IsRoomForPedToLeaveCar ( ped - > m_vehDoor , nil ) ) {
2019-09-16 13:32:58 -04:00
ped - > PositionPedOutOfCollision ( ) ;
}
if ( ped - > m_nPedState = = PED_EXIT_CAR ) {
if ( ped - > m_nPedType = = PEDTYPE_COP )
ped - > SetIdle ( ) ;
else
ped - > RestorePreviousState ( ) ;
veh = ped - > m_pMyVehicle ;
if ( ped - > bFleeAfterExitingCar & & veh ) {
ped - > bFleeAfterExitingCar = false ;
ped - > SetFlee ( veh - > GetPosition ( ) , 12000 ) ;
ped - > bUsePedNodeSeek = true ;
ped - > m_pNextPathNode = nil ;
if ( CGeneral : : GetRandomNumber ( ) & 1 | | ped - > m_pedStats - > m_fear > 70 ) {
ped - > SetMoveState ( PEDMOVE_SPRINT ) ;
ped - > Say ( SOUND_PED_FLEE_SPRINT ) ;
} else {
ped - > SetMoveState ( PEDMOVE_RUN ) ;
ped - > Say ( SOUND_PED_FLEE_RUN ) ;
}
2020-11-19 14:12:20 -05:00
startedToRun = true ;
// This is not a good way to do this...
ped - > m_nLastPedState = PED_WANDER_PATH ;
} else if ( ped - > bWanderPathAfterExitingCar ) {
ped - > SetWanderPath ( CGeneral : : GetRandomNumberInRange ( 0.0f , 8.0f ) ) ;
ped - > bWanderPathAfterExitingCar = false ;
if ( ped - > m_nPedType = = PEDTYPE_PROSTITUTE )
ped - > SetObjectiveTimer ( 30000 ) ;
ped - > m_nLastPedState = PED_NONE ;
} else if ( ped - > bGonnaKillTheCarJacker ) {
// Kill objective is already given at this point.
ped - > bGonnaKillTheCarJacker = false ;
if ( ped - > m_pedInObjective ) {
if ( ! ( CGeneral : : GetRandomNumber ( ) & 1 )
& & ped - > m_nPedType ! = PEDTYPE_COP
& & ( ! ped - > m_pedInObjective - > IsPlayer ( ) | | ! CTheScripts : : IsPlayerOnAMission ( ) ) ) {
ped - > ClearObjective ( ) ;
ped - > SetObjective ( OBJECTIVE_ENTER_CAR_AS_DRIVER , veh ) ;
}
ped - > m_leaveCarTimer = CTimer : : GetTimeInMilliseconds ( ) + 1500 ;
}
int waitTime = 1500 ;
ped - > SetWaitState ( WAITSTATE_PLAYANIM_COWER , & waitTime ) ;
ped - > SetMoveState ( PEDMOVE_RUN ) ;
startedToRun = true ;
} else if ( ped - > m_objective = = OBJECTIVE_NONE & & ped - > CharCreatedBy ! = MISSION_CHAR & & ped - > m_nPedState = = PED_IDLE & & ! ped - > IsPlayer ( ) ) {
ped - > SetWanderPath ( CGeneral : : GetRandomNumberInRange ( 0.0f , 8.0f ) ) ;
}
}
# ifdef VC_PED_PORTS
else {
ped - > m_nPedState = PED_IDLE ;
}
# endif
if ( animAssoc )
animAssoc - > blendDelta = - 1000.0f ;
ped - > RestartNonPartialAnims ( ) ;
ped - > m_pVehicleAnim = nil ;
CVector posFromZ = ped - > GetPosition ( ) ;
CPedPlacement : : FindZCoorForPed ( & posFromZ ) ;
ped - > m_vecMoveSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
ped - > SetPosition ( posFromZ ) ;
veh = ped - > m_pMyVehicle ;
if ( veh ) {
if ( ped - > m_nPedType = = PEDTYPE_PROSTITUTE ) {
if ( veh - > pDriver ) {
if ( veh - > pDriver - > IsPlayer ( ) & & ped - > CharCreatedBy = = RANDOM_CHAR ) {
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nNextSexMoneyUpdateTime = 0 ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nNextSexFrequencyUpdateTime = 0 ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_pHooker = nil ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nMoney - = 100 ;
if ( CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nMoney < 0 )
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nMoney = 0 ;
}
}
}
2021-01-13 07:01:11 -05:00
veh - > m_nGettingOutFlags & = ~ GetCarDoorFlag ( ped - > m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
if ( veh - > pDriver = = ped ) {
veh - > RemoveDriver ( ) ;
2020-12-24 09:44:59 -05:00
# ifndef FIX_BUGS // RemoveDriver does it anyway
2020-11-19 14:12:20 -05:00
veh - > SetStatus ( STATUS_ABANDONED ) ;
2020-12-24 09:44:59 -05:00
# endif
2020-11-19 14:12:20 -05:00
if ( veh - > m_nDoorLock = = CARLOCK_LOCKED_INITIALLY )
veh - > m_nDoorLock = CARLOCK_UNLOCKED ;
if ( ped - > m_nPedType = = PEDTYPE_COP & & veh - > IsLawEnforcementVehicle ( ) )
veh - > ChangeLawEnforcerState ( false ) ;
} else {
veh - > RemovePassenger ( ped ) ;
}
if ( veh - > bIsBus & & ! veh - > IsUpsideDown ( ) & & ! veh - > IsOnItsSide ( ) ) {
float angleAfterExit ;
2021-01-13 07:01:11 -05:00
if ( ped - > m_vehDoor = = CAR_DOOR_LF ) {
2020-11-19 14:12:20 -05:00
angleAfterExit = HALFPI + veh - > GetForward ( ) . Heading ( ) ;
} else {
angleAfterExit = veh - > GetForward ( ) . Heading ( ) - HALFPI ;
}
ped - > SetHeading ( angleAfterExit ) ;
ped - > m_fRotationDest = angleAfterExit ;
ped - > m_fRotationCur = angleAfterExit ;
if ( ! ped - > bBusJacked )
ped - > SetMoveState ( PEDMOVE_WALK ) ;
}
if ( CGarages : : IsPointWithinAnyGarage ( ped - > GetPosition ( ) ) )
veh - > bLightsOn = false ;
}
if ( ped - > IsPlayer ( ) )
AudioManager . PlayerJustLeftCar ( ) ;
ped - > ReplaceWeaponWhenExitingVehicle ( ) ;
ped - > bOnBoat = false ;
if ( ped - > bBusJacked ) {
ped - > SetFall ( 1500 , ANIM_KO_SKID_BACK , false ) ;
ped - > bBusJacked = false ;
}
ped - > m_nStoredMoveState = PEDMOVE_NONE ;
if ( ! ped - > IsPlayer ( ) ) {
// It's a shame...
# ifdef FIX_BUGS
int createdBy = ped - > CharCreatedBy ;
# else
int createdBy = ! ped - > CharCreatedBy ;
# endif
if ( createdBy = = MISSION_CHAR & & ! startedToRun )
ped - > SetMoveState ( PEDMOVE_WALK ) ;
}
}
void
CPed : : PedSetDraggedOutCarCB ( CAnimBlendAssociation * dragAssoc , void * arg )
{
CAnimBlendAssociation * quickJackedAssoc ;
CVehicle * vehicle ;
CPed * ped = ( CPed * ) arg ;
quickJackedAssoc = RpAnimBlendClumpGetAssociation ( ped - > GetClump ( ) , ANIM_CAR_QJACKED ) ;
if ( ped - > m_nPedState ! = PED_ARRESTED ) {
ped - > m_nLastPedState = PED_NONE ;
if ( dragAssoc )
dragAssoc - > blendDelta = - 1000.0f ;
}
ped - > RestartNonPartialAnims ( ) ;
ped - > m_pVehicleAnim = nil ;
ped - > m_pSeekTarget = nil ;
vehicle = ped - > m_pMyVehicle ;
if ( vehicle ) {
2021-01-13 07:01:11 -05:00
vehicle - > m_nGettingOutFlags & = ~ GetCarDoorFlag ( ped - > m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
if ( vehicle - > pDriver = = ped ) {
vehicle - > RemoveDriver ( ) ;
if ( vehicle - > m_nDoorLock = = CARLOCK_LOCKED_INITIALLY )
vehicle - > m_nDoorLock = CARLOCK_UNLOCKED ;
if ( ped - > m_nPedType = = PEDTYPE_COP & & vehicle - > IsLawEnforcementVehicle ( ) )
vehicle - > ChangeLawEnforcerState ( false ) ;
} else {
vehicle - > RemovePassenger ( ped ) ;
}
}
ped - > bInVehicle = false ;
if ( ped - > IsPlayer ( ) )
AudioManager . PlayerJustLeftCar ( ) ;
# ifdef VC_PED_PORTS
if ( ped - > m_objective = = OBJECTIVE_LEAVE_CAR_AND_DIE ) {
dragAssoc - > SetDeleteCallback ( PedSetDraggedOutCarPositionCB , ped ) ;
ped - > m_fHealth = 0.0f ;
ped - > SetDie ( ANIM_FLOOR_HIT , 1000.0f , 0.5f ) ;
return ;
}
# endif
if ( quickJackedAssoc ) {
dragAssoc - > SetDeleteCallback ( PedSetQuickDraggedOutCarPositionCB , ped ) ;
} else {
dragAssoc - > SetDeleteCallback ( PedSetDraggedOutCarPositionCB , ped ) ;
if ( ped - > CanSetPedState ( ) )
CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_GETUP1 , 1000.0f ) ;
}
ped - > ReplaceWeaponWhenExitingVehicle ( ) ;
ped - > m_nStoredMoveState = PEDMOVE_NONE ;
ped - > bVehExitWillBeInstant = false ;
}
void
CPed : : PedSetInCarCB ( CAnimBlendAssociation * animAssoc , void * arg )
{
CPed * ped = ( CPed * ) arg ;
CVehicle * veh = ped - > m_pMyVehicle ;
// Pointless code
if ( ! veh )
return ;
# ifdef VC_PED_PORTS
// Situation of entering car as a driver while there is already a driver exiting atm.
CPed * driver = veh - > pDriver ;
if ( driver & & driver - > m_nPedState = = PED_DRIVING & & ! veh - > bIsBus & & driver - > m_objective = = OBJECTIVE_LEAVE_CAR
& & ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER | | ped - > m_nPedState = = PED_CARJACK ) ) {
if ( ! ped - > IsPlayer ( ) & & ( ped - > CharCreatedBy ! = MISSION_CHAR | | driver - > IsPlayer ( ) ) ) {
ped - > QuitEnteringCar ( ) ;
return ;
}
if ( driver - > CharCreatedBy = = MISSION_CHAR ) {
PedSetOutCarCB ( nil , veh - > pDriver ) ;
if ( driver - > m_pMyVehicle ) {
driver - > PositionPedOutOfCollision ( ) ;
} else {
driver - > m_pMyVehicle = veh ;
driver - > PositionPedOutOfCollision ( ) ;
driver - > m_pMyVehicle = nil ;
}
veh - > pDriver = nil ;
} else {
driver - > SetDead ( ) ;
driver - > FlagToDestroyWhenNextProcessed ( ) ;
veh - > pDriver = nil ;
}
}
# endif
if ( ! ped - > IsNotInWreckedVehicle ( ) | | ped - > DyingOrDead ( ) )
return ;
ped - > bInVehicle = true ;
if ( ped - > m_nPedType = = PEDTYPE_PROSTITUTE ) {
if ( veh - > pDriver ) {
if ( veh - > pDriver - > IsPlayer ( ) & & ped - > CharCreatedBy = = RANDOM_CHAR ) {
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nSexFrequency = 1000 ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nNextSexMoneyUpdateTime = CTimer : : GetTimeInMilliseconds ( ) + 1000 ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nNextSexFrequencyUpdateTime = CTimer : : GetTimeInMilliseconds ( ) + 3000 ;
CWorld : : Players [ CWorld : : PlayerInFocus ] . m_pHooker = ( CCivilianPed * ) ped ;
}
}
}
if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER
# if defined VC_PED_PORTS || defined FIX_BUGS
| | ped - > m_nPedState = = PED_CARJACK
# endif
)
veh - > bIsBeingCarJacked = false ;
if ( veh - > m_nNumGettingIn )
- - veh - > m_nNumGettingIn ;
if ( ped - > IsPlayer ( ) & & ( ( CPlayerPed * ) ped ) - > m_bAdrenalineActive )
( ( CPlayerPed * ) ped ) - > ClearAdrenaline ( ) ;
if ( veh - > IsBoat ( ) ) {
if ( ped - > IsPlayer ( ) ) {
# if defined VC_PED_PORTS || defined FIX_BUGS
CCarCtrl : : RegisterVehicleOfInterest ( veh ) ;
# endif
if ( veh - > GetStatus ( ) = = STATUS_SIMPLE ) {
veh - > m_vecMoveSpeed = CVector ( 0.0f , 0.0f , - 0.00001f ) ;
veh - > m_vecTurnSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
}
veh - > SetStatus ( STATUS_PLAYER ) ;
AudioManager . PlayerJustGotInCar ( ) ;
}
veh - > SetDriver ( ped ) ;
if ( ! veh - > bEngineOn )
veh - > bEngineOn = true ;
2019-09-16 13:32:58 -04:00
2020-12-14 22:11:02 -05:00
ped - > SetPedState ( PED_DRIVING ) ;
2020-11-19 14:12:20 -05:00
ped - > StopNonPartialAnims ( ) ;
return ;
}
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_pVehicleAnim )
ped - > m_pVehicleAnim - > blendDelta = - 1000.0f ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
ped - > bDoBloodyFootprints = false ;
if ( veh - > m_nAlarmState = = - 1 )
veh - > m_nAlarmState = 15000 ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > IsPlayer ( ) ) {
if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
if ( veh - > GetStatus ( ) = = STATUS_SIMPLE ) {
veh - > m_vecMoveSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
veh - > m_vecTurnSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
veh - > SetStatus ( STATUS_PLAYER ) ;
}
AudioManager . PlayerJustGotInCar ( ) ;
} else if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
if ( veh - > GetStatus ( ) = = STATUS_SIMPLE ) {
veh - > m_vecMoveSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
veh - > m_vecTurnSpeed = CVector ( 0.0f , 0.0f , 0.0f ) ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
veh - > SetStatus ( STATUS_PHYSICS ) ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
for ( int i = 0 ; i < veh - > m_nNumMaxPassengers ; + + i ) {
CPed * passenger = veh - > pPassengers [ i ] ;
if ( passenger & & passenger - > CharCreatedBy = = RANDOM_CHAR ) {
passenger - > SetObjective ( OBJECTIVE_LEAVE_CAR , veh ) ;
2019-09-26 17:01:50 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
passenger - > m_leaveCarTimer = CTimer : : GetTimeInMilliseconds ( ) ;
# endif
}
}
}
// This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below.
# if !defined VC_PED_PORTS && !defined FIX_BUGS
else if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER ) {
if ( ped - > m_nPedState = = PED_CARJACK ) {
veh - > AddPassenger ( ped , 0 ) ;
2020-12-14 22:11:02 -05:00
ped - > SetPedState ( PED_DRIVING ) ;
2020-11-19 14:12:20 -05:00
ped - > RestorePreviousObjective ( ) ;
ped - > SetObjective ( OBJECTIVE_LEAVE_CAR , veh ) ;
} else if ( veh - > pDriver & & ped - > CharCreatedBy = = RANDOM_CHAR ) {
veh - > AutoPilot . m_nCruiseSpeed = 17 ;
}
2019-09-26 17:01:50 -04:00
}
# endif
2020-11-19 14:12:20 -05:00
if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER | | ped - > m_nPedState = = PED_CARJACK ) {
veh - > SetDriver ( ped ) ;
if ( veh - > VehicleCreatedBy = = PARKED_VEHICLE ) {
veh - > VehicleCreatedBy = RANDOM_VEHICLE ;
+ + CCarCtrl : : NumRandomCars ;
- - CCarCtrl : : NumParkedCars ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
if ( veh - > bIsAmbulanceOnDuty ) {
veh - > bIsAmbulanceOnDuty = false ;
- - CCarCtrl : : NumAmbulancesOnDuty ;
}
if ( veh - > bIsFireTruckOnDuty ) {
veh - > bIsFireTruckOnDuty = false ;
- - CCarCtrl : : NumFiretrucksOnDuty ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedType = = PEDTYPE_COP & & veh - > IsLawEnforcementVehicle ( ) )
veh - > ChangeLawEnforcerState ( true ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ! veh - > bEngineOn ) {
veh - > bEngineOn = true ;
DMAudio . PlayOneShot ( ped - > m_audioEntityId , SOUND_CAR_ENGINE_START , 1.0f ) ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER & & ped - > CharCreatedBy = = RANDOM_CHAR
& & ped ! = FindPlayerPed ( ) & & ped - > m_nPedType ! = PEDTYPE_EMERGENCY ) {
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
CCarCtrl : : JoinCarWithRoadSystem ( veh ) ;
veh - > AutoPilot . m_nCarMission = MISSION_CRUISE ;
veh - > AutoPilot . m_nTempAction = TEMPACT_NONE ;
veh - > AutoPilot . m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS ;
veh - > AutoPilot . m_nCruiseSpeed = 25 ;
}
2020-12-14 22:11:02 -05:00
ped - > SetPedState ( PED_DRIVING ) ;
2020-11-19 14:12:20 -05:00
if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_prevObjective = = OBJECTIVE_RUN_TO_AREA | | ped - > m_prevObjective = = OBJECTIVE_GOTO_CHAR_ON_FOOT | | ped - > m_prevObjective = = OBJECTIVE_KILL_CHAR_ON_FOOT )
ped - > m_prevObjective = OBJECTIVE_NONE ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
ped - > RestorePreviousObjective ( ) ;
}
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
} else if ( ped - > m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER ) {
if ( veh - > bIsBus ) {
veh - > AddPassenger ( ped ) ;
} else {
2021-01-13 07:01:11 -05:00
switch ( ped - > m_vehDoor ) {
2020-11-19 14:12:20 -05:00
case CAR_DOOR_RF :
veh - > AddPassenger ( ped , 0 ) ;
break ;
case CAR_DOOR_RR :
veh - > AddPassenger ( ped , 2 ) ;
break ;
case CAR_DOOR_LR :
veh - > AddPassenger ( ped , 1 ) ;
break ;
default :
veh - > AddPassenger ( ped ) ;
break ;
}
}
2020-12-14 22:11:02 -05:00
ped - > SetPedState ( PED_DRIVING ) ;
2020-11-19 14:12:20 -05:00
if ( ped - > m_prevObjective = = OBJECTIVE_RUN_TO_AREA | | ped - > m_prevObjective = = OBJECTIVE_GOTO_CHAR_ON_FOOT | | ped - > m_prevObjective = = OBJECTIVE_KILL_CHAR_ON_FOOT )
ped - > m_prevObjective = OBJECTIVE_NONE ;
ped - > RestorePreviousObjective ( ) ;
# ifdef VC_PED_PORTS
if ( veh - > pDriver & & ped - > CharCreatedBy = = RANDOM_CHAR )
veh - > AutoPilot . m_nCruiseSpeed = 17 ;
# endif
2019-09-16 13:32:58 -04:00
}
2021-01-13 07:01:11 -05:00
veh - > m_nGettingInFlags & = ~ GetCarDoorFlag ( ped - > m_vehDoor ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( veh - > bIsBus & & ! veh - > m_nGettingInFlags )
( ( CAutomobile * ) veh ) - > SetBusDoorTimer ( 1000 , 1 ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
switch ( ped - > m_objective ) {
case OBJECTIVE_KILL_CHAR_ON_FOOT :
case OBJECTIVE_KILL_CHAR_ANY_MEANS :
case OBJECTIVE_LEAVE_CAR :
case OBJECTIVE_FOLLOW_CAR_IN_CAR :
case OBJECTIVE_GOTO_AREA_ANY_MEANS :
case OBJECTIVE_GOTO_AREA_ON_FOOT :
case OBJECTIVE_RUN_TO_AREA :
break ;
default :
ped - > SetObjective ( OBJECTIVE_NONE ) ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
if ( veh - > pDriver = = ped ) {
if ( veh - > bLowVehicle ) {
ped - > m_pVehicleAnim = CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_LSIT , 100.0f ) ;
} else {
ped - > m_pVehicleAnim = CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_SIT , 100.0f ) ;
}
} else if ( veh - > bLowVehicle ) {
ped - > m_pVehicleAnim = CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_SITPLO , 100.0f ) ;
} else {
ped - > m_pVehicleAnim = CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_SITP , 100.0f ) ;
}
ped - > StopNonPartialAnims ( ) ;
if ( veh - > bIsBus )
ped - > bRenderPedInCar = false ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
// FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check.
# ifndef FIX_BUGS
if ( ped - > IsPlayer ( ) & & ! CCarCtrl : : IsThisVehicleInteresting ( veh ) & & veh - > VehicleCreatedBy ! = MISSION_VEHICLE ) {
# else
if ( ped - > IsPlayer ( ) & & veh - > VehicleCreatedBy ! = MISSION_VEHICLE ) {
# endif
CCarCtrl : : RegisterVehicleOfInterest ( veh ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( ! veh - > bHasBeenOwnedByPlayer & & veh - > VehicleCreatedBy ! = MISSION_VEHICLE )
CEventList : : RegisterEvent ( EVENT_STEAL_CAR , EVENT_ENTITY_VEHICLE , veh , ped , 1500 ) ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
veh - > bHasBeenOwnedByPlayer = true ;
}
ped - > bChangedSeat = true ;
2019-09-16 13:32:58 -04:00
}
bool
2020-11-19 14:12:20 -05:00
CPed : : CanBeDeleted ( void )
2019-09-16 13:32:58 -04:00
{
2020-11-19 14:12:20 -05:00
if ( bInVehicle )
2019-09-16 13:32:58 -04:00
return false ;
2020-11-19 14:12:20 -05:00
switch ( CharCreatedBy ) {
case RANDOM_CHAR :
return true ;
case MISSION_CHAR :
return false ;
default :
2019-09-16 13:32:58 -04:00
return true ;
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : AddWeaponModel ( int id )
2019-09-16 13:32:58 -04:00
{
2020-11-19 14:12:20 -05:00
RpAtomic * atm ;
2019-09-16 13:32:58 -04:00
2020-11-19 14:12:20 -05:00
if ( id ! = - 1 ) {
# ifdef PED_SKIN
if ( IsClumpSkinned ( GetClump ( ) ) ) {
if ( m_pWeaponModel )
RemoveWeaponModel ( - 1 ) ;
2020-04-17 00:01:54 -04:00
2020-11-19 14:12:20 -05:00
m_pWeaponModel = ( RpAtomic * ) CModelInfo : : GetModelInfo ( id ) - > CreateInstance ( ) ;
} else
2020-04-17 00:01:54 -04:00
# endif
2020-11-19 14:12:20 -05:00
{
atm = ( RpAtomic * ) CModelInfo : : GetModelInfo ( id ) - > CreateInstance ( ) ;
RwFrameDestroy ( RpAtomicGetFrame ( atm ) ) ;
RpAtomicSetFrame ( atm , m_pFrames [ PED_HANDR ] - > frame ) ;
RpClumpAddAtomic ( GetClump ( ) , atm ) ;
2019-09-16 13:32:58 -04:00
}
2020-11-19 14:12:20 -05:00
m_wepModelID = id ;
2019-09-16 13:32:58 -04:00
}
}
2019-06-24 18:42:23 -04:00
2020-11-19 14:12:20 -05:00
static RwObject *
RemoveAllModelCB ( RwObject * object , void * data )
2019-09-20 15:40:33 -04:00
{
2020-11-19 14:12:20 -05:00
RpAtomic * atomic = ( RpAtomic * ) object ;
if ( CVisibilityPlugins : : GetAtomicModelInfo ( atomic ) ) {
RpClumpRemoveAtomic ( RpAtomicGetClump ( atomic ) , atomic ) ;
RpAtomicDestroy ( atomic ) ;
2019-09-20 15:40:33 -04:00
}
2020-11-19 14:12:20 -05:00
return object ;
2019-09-20 15:40:33 -04:00
}
2020-11-19 14:12:20 -05:00
void
CPed : : RemoveWeaponModel ( int modelId )
2019-09-20 15:40:33 -04:00
{
2020-11-19 14:12:20 -05:00
// modelId is not used!! This function just removes the current weapon.
# ifdef PED_SKIN
if ( IsClumpSkinned ( GetClump ( ) ) ) {
if ( m_pWeaponModel ) {
RwFrame * frm = RpAtomicGetFrame ( m_pWeaponModel ) ;
RpAtomicDestroy ( m_pWeaponModel ) ;
RwFrameDestroy ( frm ) ;
m_pWeaponModel = nil ;
2019-09-20 15:40:33 -04:00
}
2020-11-19 14:12:20 -05:00
} else
# endif
RwFrameForAllObjects ( m_pFrames [ PED_HANDR ] - > frame , RemoveAllModelCB , nil ) ;
m_wepModelID = - 1 ;
}
uint32
CPed : : GiveWeapon ( eWeaponType weaponType , uint32 ammo )
{
CWeapon & weapon = GetWeapon ( weaponType ) ;
if ( HasWeapon ( weaponType ) ) {
if ( weapon . m_nAmmoTotal + 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 + + ;
2019-09-20 15:40:33 -04:00
}
2020-11-19 14:12:20 -05:00
if ( weapon . m_eWeaponState = = WEAPONSTATE_OUT_OF_AMMO )
weapon . m_eWeaponState = WEAPONSTATE_READY ;
2019-09-20 15:40:33 -04:00
2020-11-19 14:12:20 -05:00
return weaponType ;
}
2019-09-20 15:40:33 -04:00
2020-11-19 14:12:20 -05:00
// Some kind of VC leftover I think
int
CPed : : GetWeaponSlot ( eWeaponType weaponType )
{
if ( HasWeapon ( weaponType ) )
return weaponType ;
else
return - 1 ;
2019-09-20 15:40:33 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetCurrentWeapon ( uint32 weaponType )
2019-09-20 15:40:33 -04:00
{
2020-11-19 14:12:20 -05:00
CWeaponInfo * weaponInfo ;
if ( HasWeapon ( weaponType ) ) {
weaponInfo = CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) ;
RemoveWeaponModel ( weaponInfo - > m_nModelId ) ;
2020-11-18 06:38:47 -05:00
2020-11-19 14:12:20 -05:00
m_currentWeapon = weaponType ;
2020-04-23 16:25:18 -04:00
2020-11-19 14:12:20 -05:00
weaponInfo = CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) ;
AddWeaponModel ( weaponInfo - > m_nModelId ) ;
2020-04-23 16:25:18 -04:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : GrantAmmo ( eWeaponType weaponType , uint32 ammo )
2020-04-23 16:25:18 -04:00
{
2020-11-19 14:12:20 -05:00
if ( HasWeapon ( weaponType ) ) {
GetWeapon ( weaponType ) . m_nAmmoTotal + = ammo ;
} else {
GetWeapon ( weaponType ) . Initialise ( weaponType , ammo ) ;
m_maxWeaponTypeAllowed + + ;
}
2020-04-23 16:25:18 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetAmmo ( eWeaponType weaponType , uint32 ammo )
2020-04-23 16:25:18 -04:00
{
2020-11-19 14:12:20 -05:00
if ( HasWeapon ( weaponType ) ) {
GetWeapon ( weaponType ) . m_nAmmoTotal = ammo ;
} else {
GetWeapon ( weaponType ) . Initialise ( weaponType , ammo ) ;
m_maxWeaponTypeAllowed + + ;
2019-09-20 15:40:33 -04:00
}
}
2019-09-26 17:01:50 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : ClearWeapons ( void )
2019-09-26 17:01:50 -04:00
{
2020-11-19 14:12:20 -05:00
CWeaponInfo * currentWeapon = CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) ;
RemoveWeaponModel ( currentWeapon - > m_nModelId ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
m_maxWeaponTypeAllowed = WEAPONTYPE_BASEBALLBAT ;
m_currentWeapon = WEAPONTYPE_UNARMED ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
currentWeapon = CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) ;
AddWeaponModel ( currentWeapon - > m_nModelId ) ;
for ( int i = 0 ; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS ; i + + ) {
CWeapon & weapon = GetWeapon ( i ) ;
weapon . m_eWeaponType = WEAPONTYPE_UNARMED ;
weapon . m_eWeaponState = WEAPONSTATE_READY ;
weapon . m_nAmmoInClip = 0 ;
weapon . m_nAmmoTotal = 0 ;
weapon . m_nTimer = 0 ;
}
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : PreRender ( void )
{
CShadows : : StoreShadowForPed ( this ,
CTimeCycle : : m_fShadowDisplacementX [ CTimeCycle : : m_CurrentStoredValue ] , CTimeCycle : : m_fShadowDisplacementY [ CTimeCycle : : m_CurrentStoredValue ] ,
CTimeCycle : : m_fShadowFrontX [ CTimeCycle : : m_CurrentStoredValue ] , CTimeCycle : : m_fShadowFrontY [ CTimeCycle : : m_CurrentStoredValue ] ,
CTimeCycle : : m_fShadowSideX [ CTimeCycle : : m_CurrentStoredValue ] , CTimeCycle : : m_fShadowSideY [ CTimeCycle : : m_CurrentStoredValue ] ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
# ifdef PED_SKIN
if ( IsClumpSkinned ( GetClump ( ) ) ) {
UpdateRpHAnim ( ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( bBodyPartJustCameOff & & m_bodyPartBleeding = = PED_HEAD ) {
// scale head to 0 if shot off
RpHAnimHierarchy * hier = GetAnimHierarchyFromSkinClump ( GetClump ( ) ) ;
int32 idx = RpHAnimIDGetIndex ( hier , ConvertPedNode2BoneTag ( PED_HEAD ) ) ;
RwMatrix * head = & RpHAnimHierarchyGetMatrixArray ( hier ) [ idx ] ;
RwV3d zero = { 0.0f , 0.0f , 0.0f } ;
RwMatrixScale ( head , & zero , rwCOMBINEPRECONCAT ) ;
}
}
# endif
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( bBodyPartJustCameOff & & bIsPedDieAnimPlaying & & m_bodyPartBleeding ! = - 1 & & ( CTimer : : GetFrameCounter ( ) & 7 ) > 3 ) {
CVector bloodDir ( 0.0f , 0.0f , 0.0f ) ;
CVector bloodPos ( 0.0f , 0.0f , 0.0f ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
TransformToNode ( bloodPos , m_bodyPartBleeding ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
switch ( m_bodyPartBleeding ) {
case PED_HEAD :
bloodDir = 0.1f * GetUp ( ) ;
break ;
case PED_UPPERARML :
bloodDir = 0.04f * GetUp ( ) - 0.04f * GetRight ( ) ;
break ;
case PED_UPPERARMR :
bloodDir = 0.04f * GetUp ( ) - 0.04f * GetRight ( ) ;
break ;
case PED_UPPERLEGL :
bloodDir = 0.04f * GetUp ( ) + 0.05f * GetForward ( ) ;
break ;
case PED_UPPERLEGR :
bloodDir = 0.04f * GetUp ( ) + 0.05f * GetForward ( ) ;
break ;
default :
bloodDir = CVector ( 0.0f , 0.0f , 0.0f ) ;
break ;
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < 4 ; i + + )
CParticle : : AddParticle ( PARTICLE_BLOOD_SPURT , bloodPos , bloodDir , nil , 0.0f , 0 , 0 , 0 , 0 ) ;
}
if ( CWeather : : Rain > 0.3f & & TheCamera . SoundDistUp > 15.0f ) {
if ( ( TheCamera . GetPosition ( ) - GetPosition ( ) ) . Magnitude ( ) < 25.0f ) {
bool doSplashUp = true ;
CColModel * ourCol = CModelInfo : : GetModelInfo ( GetModelIndex ( ) ) - > GetColModel ( ) ;
CVector speed = FindPlayerSpeed ( ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( Abs ( speed . x ) < = 0.05f & & Abs ( speed . y ) < = 0.05f ) {
if ( ! OnGround ( ) & & m_nPedState ! = PED_ATTACK & & m_nPedState ! = PED_FIGHT ) {
if ( ! IsPedHeadAbovePos ( 0.3f ) | | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_TIRED ) ) {
doSplashUp = false ;
}
} else
doSplashUp = false ;
} else
doSplashUp = false ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( doSplashUp & & ourCol - > numSpheres > 0 ) {
for ( int i = 0 ; i < ourCol - > numSpheres ; i + + ) {
CColSphere * sphere = & ourCol - > spheres [ i ] ;
CVector splashPos ;
switch ( sphere - > piece ) {
case PEDPIECE_LEFTARM :
case PEDPIECE_RIGHTARM :
case PEDPIECE_HEAD :
splashPos = GetMatrix ( ) * ourCol - > spheres [ i ] . center ;
splashPos . z + = 0.7f * sphere - > radius ;
splashPos . x + = CGeneral : : GetRandomNumberInRange ( - 0.15f , 0.15f ) ;
splashPos . y + = CGeneral : : GetRandomNumberInRange ( - 0.15f , 0.15f ) ;
CParticle : : AddParticle ( PARTICLE_RAIN_SPLASHUP , splashPos , CVector ( 0.0f , 0.0f , 0.0f ) , nil , 0.0f , 0 , 0 , CGeneral : : GetRandomNumber ( ) & 1 , 0 ) ;
break ;
default :
2019-09-26 17:01:50 -04:00
break ;
}
}
2020-11-19 14:12:20 -05:00
}
}
}
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : Render ( void )
{
if ( bInVehicle & & m_nPedState ! = PED_EXIT_CAR & & m_nPedState ! = PED_DRAG_FROM_CAR ) {
if ( ! bRenderPedInCar )
return ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
float camDistSq = ( TheCamera . GetPosition ( ) - GetPosition ( ) ) . MagnitudeSqr ( ) ;
if ( camDistSq > SQR ( 25.0f * TheCamera . LODDistMultiplier ) )
return ;
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
CEntity : : Render ( ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
# ifdef PED_SKIN
if ( IsClumpSkinned ( GetClump ( ) ) ) {
renderLimb ( PED_HEAD ) ;
renderLimb ( PED_HANDL ) ;
renderLimb ( PED_HANDR ) ;
}
if ( m_pWeaponModel & & IsClumpSkinned ( GetClump ( ) ) ) {
RpHAnimHierarchy * hier = GetAnimHierarchyFromSkinClump ( GetClump ( ) ) ;
int idx = RpHAnimIDGetIndex ( hier , m_pFrames [ PED_HANDR ] - > nodeID ) ;
RwMatrix * mat = & RpHAnimHierarchyGetMatrixArray ( hier ) [ idx ] ;
RwFrame * frame = RpAtomicGetFrame ( m_pWeaponModel ) ;
* RwFrameGetMatrix ( frame ) = * mat ;
RwFrameUpdateObjects ( frame ) ;
RpAtomicRender ( m_pWeaponModel ) ;
}
# endif
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : CheckAroundForPossibleCollisions ( void )
{
CVector ourCentre , objCentre ;
CEntity * objects [ 8 ] ;
int16 maxObject ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_nPedStateTimer )
return ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
GetBoundCentre ( ourCentre ) ;
CWorld : : FindObjectsInRange ( ourCentre , 10.0f , true , & maxObject , 6 , objects , false , true , false , true , false ) ;
for ( int i = 0 ; i < maxObject ; i + + ) {
CEntity * object = objects [ i ] ;
if ( bRunningToPhone ) {
if ( gPhoneInfo . PhoneAtThisPosition ( object - > GetPosition ( ) ) )
2019-09-26 17:01:50 -04:00
break ;
2020-11-19 14:12:20 -05:00
}
object - > GetBoundCentre ( objCentre ) ;
float radius = object - > GetBoundRadius ( ) ;
if ( radius > 4.5f | | radius < 1.0f )
radius = 1.0f ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
// Developers gave up calculating Z diff. later according to asm.
float diff = CVector ( ourCentre - objCentre ) . MagnitudeSqr2D ( ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( sq ( radius + 1.0f ) > diff )
m_fRotationDest + = DEGTORAD ( 22.5f ) ;
}
}
void
CPed : : SetIdle ( void )
{
if ( m_nPedState ! = PED_IDLE & & m_nPedState ! = PED_MUG & & m_nPedState ! = PED_FLEE_ENTITY ) {
2019-10-13 00:05:08 -04:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_AIM_GUN )
ClearPointGunAt ( ) ;
m_nLastPedState = PED_NONE ;
2019-10-13 00:05:08 -04:00
# endif
2020-12-14 22:11:02 -05:00
SetPedState ( PED_IDLE ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_STILL ) ;
}
if ( m_nWaitState = = WAITSTATE_FALSE ) {
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + CGeneral : : GetRandomNumberInRange ( 2000 , 4000 ) ;
}
}
void
CPed : : Idle ( void )
{
CVehicle * veh = m_pMyVehicle ;
2021-01-13 07:01:11 -05:00
if ( veh & & veh - > m_nGettingOutFlags & & m_vehDoor ) {
2019-09-26 17:01:50 -04:00
2021-01-13 07:01:11 -05:00
if ( veh - > m_nGettingOutFlags & GetCarDoorFlag ( m_vehDoor ) ) {
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective ! = OBJECTIVE_KILL_CHAR_ON_FOOT ) {
2021-01-13 07:01:11 -05:00
CVector doorPos = GetPositionToOpenCarDoor ( veh , m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
CVector doorDist = GetPosition ( ) - doorPos ;
if ( doorDist . MagnitudeSqr ( ) < sq ( 0.5f ) ) {
SetMoveState ( PEDMOVE_WALK ) ;
return ;
2019-09-26 17:01:50 -04:00
}
}
2020-11-19 14:12:20 -05:00
}
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * armedIdleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_ARMED ) ;
CAnimBlendAssociation * unarmedIdleAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_STANCE ) ;
int waitTime ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nMoveState = = PEDMOVE_STILL ) {
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
eWeaponType curWeapon = GetWeapon ( ) - > m_eWeaponType ;
if ( ! armedIdleAssoc | |
CTimer : : GetTimeInMilliseconds ( ) < = m_nWaitTimer & & curWeapon ! = WEAPONTYPE_UNARMED & & curWeapon ! = WEAPONTYPE_MOLOTOV & & curWeapon ! = WEAPONTYPE_GRENADE ) {
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( ( ! GetWeapon ( ) - > IsType2Handed ( ) | | curWeapon = = WEAPONTYPE_SHOTGUN ) & & curWeapon ! = WEAPONTYPE_BASEBALLBAT
| | ! unarmedIdleAssoc | | unarmedIdleAssoc - > blendAmount < = 0.95f | | m_nWaitState ! = WAITSTATE_FALSE | | CTimer : : GetTimeInMilliseconds ( ) < = m_nWaitTimer ) {
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
m_moved = CVector2D ( 0.0f , 0.0f ) ;
return ;
2019-09-26 17:01:50 -04:00
}
2020-11-19 14:12:20 -05:00
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_ARMED , 3.0f ) ;
waitTime = CGeneral : : GetRandomNumberInRange ( 4000 , 7500 ) ;
} else {
armedIdleAssoc - > blendDelta = - 2.0f ;
armedIdleAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
waitTime = CGeneral : : GetRandomNumberInRange ( 3000 , 8500 ) ;
}
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + waitTime ;
} else {
if ( armedIdleAssoc ) {
armedIdleAssoc - > blendDelta = - 8.0f ;
armedIdleAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
m_nWaitTimer = 0 ;
}
if ( ! IsPlayer ( ) )
SetMoveState ( PEDMOVE_STILL ) ;
}
m_moved = CVector2D ( 0.0f , 0.0f ) ;
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : ClearPause ( void )
{
RestorePreviousState ( ) ;
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : Pause ( void )
{
m_moved = CVector2D ( 0.0f , 0.0f ) ;
if ( CTimer : : GetTimeInMilliseconds ( ) > m_leaveCarTimer )
ClearPause ( ) ;
}
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetFall ( int extraTime , AnimationId animId , uint8 evenIfNotInControl )
{
if ( ! IsPedInControl ( ) & & ( ! evenIfNotInControl | | DyingOrDead ( ) ) )
return ;
ClearLookFlag ( ) ;
ClearAimFlag ( ) ;
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_FALL ) ;
2020-11-19 14:12:20 -05:00
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 = UINT32_MAX ;
} 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 ) ;
}
bFallenDown = true ;
}
void
CPed : : ClearFall ( void )
{
SetGetUp ( ) ;
}
void
CPed : : Fall ( void )
{
if ( m_getUpTimer ! = UINT32_MAX & & CTimer : : GetTimeInMilliseconds ( ) > m_getUpTimer
# ifdef VC_PED_PORTS
& & bIsStanding
# endif
)
ClearFall ( ) ;
// VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III.
}
bool
CPed : : CheckIfInTheAir ( void )
{
if ( bInVehicle )
return false ;
CVector pos = GetPosition ( ) ;
CColPoint foundColPoint ;
CEntity * foundEntity ;
float startZ = pos . z - 1.54f ;
bool foundGround = CWorld : : ProcessVerticalLine ( pos , startZ , foundColPoint , foundEntity , true , true , false , true , false , false , nil ) ;
if ( ! foundGround & & m_nPedState ! = PED_JUMP )
{
pos . z - = FEET_OFFSET ;
if ( CWorld : : TestSphereAgainstWorld ( pos , 0.15f , this , true , false , false , false , false , false ) )
foundGround = true ;
}
return ! foundGround ;
}
void
CPed : : SetInTheAir ( void )
{
if ( bIsInTheAir )
return ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
bIsInTheAir = true ;
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_FALL_GLIDE , 4.0f ) ;
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_ATTACK ) {
ClearAttack ( ) ;
ClearPointGunAt ( ) ;
} else if ( m_nPedState = = PED_FIGHT ) {
EndFight ( ENDFIGHT_FAST ) ;
}
}
void
CPed : : InTheAir ( void )
{
CColPoint foundCol ;
CEntity * foundEnt ;
CVector ourPos = GetPosition ( ) ;
CVector bitBelow = GetPosition ( ) ;
bitBelow . z - = 4.04f ;
if ( m_vecMoveSpeed . z < 0.0f & & ! bIsPedDieAnimPlaying ) {
if ( ! DyingOrDead ( ) ) {
if ( CWorld : : ProcessLineOfSight ( ourPos , bitBelow , foundCol , foundEnt , true , true , false , true , false , false , false ) ) {
if ( GetPosition ( ) . z - foundCol . point . z < 1.3f
2020-03-01 19:03:39 -05:00
# ifdef VC_PED_PORTS
2020-11-19 14:12:20 -05:00
| | bIsStanding
2020-03-01 19:03:39 -05:00
# endif
2020-11-19 14:12:20 -05:00
)
SetLanding ( ) ;
} else {
if ( ! RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FALL_FALL ) ) {
if ( m_vecMoveSpeed . z < - 0.1f )
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_FALL_FALL , 4.0f ) ;
2019-09-26 17:01:50 -04:00
}
}
2020-11-19 14:12:20 -05:00
}
}
}
void
CPed : : SetLanding ( void )
{
if ( DyingOrDead ( ) )
return ;
CAnimBlendAssociation * fallAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_FALL_FALL ) ;
CAnimBlendAssociation * landAssoc ;
RpAnimBlendClumpSetBlendDeltas ( GetClump ( ) , ASSOC_PARTIAL , - 1000.0f ) ;
if ( fallAssoc ) {
landAssoc = CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_FALL_COLLAPSE ) ;
DMAudio . PlayOneShot ( m_audioEntityId , SOUND_FALL_COLLAPSE , 1.0f ) ;
if ( IsPlayer ( ) )
Say ( SOUND_PED_LAND ) ;
} else {
landAssoc = CAnimManager : : AddAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_FALL_LAND ) ;
DMAudio . PlayOneShot ( m_audioEntityId , SOUND_FALL_LAND , 1.0f ) ;
}
landAssoc - > SetFinishCallback ( PedLandCB , this ) ;
bIsInTheAir = false ;
bIsLanding = true ;
}
void
CPed : : SetGetUp ( void )
{
if ( m_nPedState = = PED_GETUP & & bGetUpAnimStarted )
return ;
if ( ! CanSetPedState ( ) )
return ;
if ( m_fHealth > = 1.0f | | IsPedHeadAbovePos ( - 0.3f ) ) {
if ( bUpdateAnimHeading ) {
m_fRotationCur = CGeneral : : LimitRadianAngle ( m_fRotationCur ) ;
m_fRotationCur - = HALFPI ;
bUpdateAnimHeading = false ;
}
if ( m_nPedState ! = PED_GETUP ) {
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_GETUP ) ;
2020-11-19 14:12:20 -05:00
}
CVehicle * collidingVeh = ( CVehicle * ) m_pCollidingEntity ;
CVehicle * veh = ( CVehicle * ) CPedPlacement : : IsPositionClearOfCars ( & GetPosition ( ) ) ;
if ( veh & & veh - > m_vehType ! = VEHICLE_TYPE_BIKE | |
collidingVeh & & collidingVeh - > IsVehicle ( ) & & collidingVeh - > m_vehType ! = VEHICLE_TYPE_BIKE
& & ( ( uint8 ) ( CTimer : : GetFrameCounter ( ) + m_randomSeed + 5 ) % 8 | |
CCollision : : ProcessColModels ( GetMatrix ( ) , * GetColModel ( ) , collidingVeh - > GetMatrix ( ) , * collidingVeh - > GetColModel ( ) ,
aTempPedColPts , nil , nil ) > 0 ) ) {
bGetUpAnimStarted = false ;
if ( IsPlayer ( ) )
InflictDamage ( nil , WEAPONTYPE_RUNOVERBYCAR , CTimer : : GetTimeStep ( ) , PEDPIECE_TORSO , 0 ) ;
else {
if ( ! CPad : : GetPad ( 0 ) - > ArePlayerControlsDisabled ( ) )
return ;
InflictDamage ( nil , WEAPONTYPE_RUNOVERBYCAR , 1000.0f , PEDPIECE_TORSO , 0 ) ;
2019-09-26 17:01:50 -04:00
}
2020-11-19 14:12:20 -05:00
return ;
2019-09-26 17:01:50 -04:00
}
2020-11-19 14:12:20 -05:00
bGetUpAnimStarted = true ;
m_pCollidingEntity = nil ;
bKnockedUpIntoAir = false ;
CAnimBlendAssociation * animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_SPRINT ) ;
if ( animAssoc ) {
if ( RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_RUN ) ) {
CAnimManager : : BlendAnimation ( GetClump ( ) , m_animGroup , ANIM_RUN , 8.0f ) ;
2019-09-26 17:01:50 -04:00
} else {
2020-11-19 14:12:20 -05:00
CAnimManager : : BlendAnimation ( GetClump ( ) , m_animGroup , ANIM_IDLE_STANCE , 8.0f ) ;
2019-09-26 17:01:50 -04:00
}
2020-11-19 14:12:20 -05:00
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
if ( RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) , ASSOC_FRONTAL ) )
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_GETUP_FRONT , 1000.0f ) ;
else
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_GETUP1 , 1000.0f ) ;
animAssoc - > SetFinishCallback ( PedGetupCB , this ) ;
} else {
m_fHealth = 0.0f ;
SetDie ( NUM_ANIMS , 4.0f , 0.0f ) ;
}
}
void
CPed : : Mug ( void )
{
if ( m_pSeekTarget & & m_pSeekTarget - > IsPed ( ) ) {
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_attackTimer - 2000 ) {
if ( ( m_pSeekTarget - > GetPosition ( ) - GetPosition ( ) ) . Magnitude ( ) > 3.0f )
m_wepSkills = 50 ;
Say ( SOUND_PED_MUGGING ) ;
( ( CPed * ) m_pSeekTarget ) - > Say ( SOUND_PED_ROBBED ) ;
} else {
SetWanderPath ( CGeneral : : GetRandomNumber ( ) & 7 ) ;
SetFlee ( m_pSeekTarget , 20000 ) ;
2019-09-26 17:01:50 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
SetIdle ( ) ;
}
}
void
CPed : : SetLookTimer ( int time )
{
if ( CTimer : : GetTimeInMilliseconds ( ) > m_lookTimer ) {
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + time ;
2019-09-26 17:01:50 -04:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetAttackTimer ( uint32 time )
{
if ( CTimer : : GetTimeInMilliseconds ( ) > m_attackTimer )
m_attackTimer = Max ( m_shootTimer , CTimer : : GetTimeInMilliseconds ( ) ) + time ;
}
2019-09-26 17:01:50 -04:00
void
CPed : : SetShootTimer ( uint32 time )
{
if ( CTimer : : GetTimeInMilliseconds ( ) > m_shootTimer ) {
m_shootTimer = CTimer : : GetTimeInMilliseconds ( ) + time ;
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : ClearLook ( void )
{
RestorePreviousState ( ) ;
ClearLookFlag ( ) ;
}
void
CPed : : Look ( void )
{
// UNUSED: This is a perfectly empty function.
}
bool
CPed : : TurnBody ( void )
{
bool turnDone = true ;
if ( m_pLookTarget )
m_fLookDirection = CGeneral : : GetRadianAngleBetweenPoints (
m_pLookTarget - > GetPosition ( ) . x ,
m_pLookTarget - > GetPosition ( ) . y ,
GetPosition ( ) . x ,
GetPosition ( ) . y ) ;
float limitedLookDir = CGeneral : : LimitRadianAngle ( m_fLookDirection ) ;
float currentRot = m_fRotationCur ;
if ( currentRot - PI > limitedLookDir )
limitedLookDir + = 2 * PI ;
else if ( PI + currentRot < limitedLookDir )
limitedLookDir - = 2 * PI ;
float neededTurn = currentRot - limitedLookDir ;
m_fRotationDest = limitedLookDir ;
if ( Abs ( neededTurn ) > 0.05f ) {
turnDone = false ;
currentRot - = neededTurn * 0.2f ;
}
m_fRotationCur = currentRot ;
m_fLookDirection = limitedLookDir ;
return turnDone ;
}
void
CPed : : SetSeek ( CVector pos , float distanceToCountDone )
{
if ( ! IsPedInControl ( )
| | ( m_nPedState = = PED_SEEK_POS & & m_vecSeekPos . x = = pos . x & & m_vecSeekPos . y = = pos . y ) )
return ;
if ( GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_M16
| | GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_AK47
| | GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_SNIPERRIFLE
| | GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_ROCKETLAUNCHER
| | GetWeapon ( ) - > m_eWeaponType = = WEAPONTYPE_SHOTGUN ) {
ClearPointGunAt ( ) ;
}
if ( m_nPedState ! = PED_SEEK_POS )
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_SEEK_POS ) ;
2020-11-19 14:12:20 -05:00
m_distanceToCountSeekDone = distanceToCountDone ;
m_vecSeekPos = pos ;
}
void
CPed : : SetSeek ( CEntity * seeking , float distanceToCountDone )
2019-09-26 17:01:50 -04:00
{
2020-11-19 14:12:20 -05:00
if ( ! IsPedInControl ( ) )
2019-09-26 17:01:50 -04:00
return ;
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_SEEK_ENTITY & & m_pSeekTarget = = seeking )
2020-07-01 08:28:43 -04:00
return ;
2020-11-19 14:12:20 -05:00
if ( ! seeking )
return ;
if ( m_nPedState ! = PED_SEEK_ENTITY )
SetStoredState ( ) ;
2019-09-26 17:01:50 -04:00
2020-12-14 22:11:02 -05:00
SetPedState ( PED_SEEK_ENTITY ) ;
2020-11-19 14:12:20 -05:00
m_distanceToCountSeekDone = distanceToCountDone ;
m_pSeekTarget = seeking ;
m_pSeekTarget - > RegisterReference ( ( CEntity * * ) & m_pSeekTarget ) ;
SetMoveState ( PEDMOVE_STILL ) ;
2019-09-26 17:01:50 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : ClearSeek ( void )
2019-09-26 17:01:50 -04:00
{
2020-11-19 14:12:20 -05:00
SetIdle ( ) ;
bRunningToPhone = false ;
2019-09-26 17:01:50 -04:00
}
2020-11-19 14:12:20 -05:00
bool
CPed : : Seek ( void )
2019-09-26 17:01:50 -04:00
{
2020-11-19 14:12:20 -05:00
float distanceToCountItDone = m_distanceToCountSeekDone ;
eMoveState nextMove = PEDMOVE_NONE ;
2019-10-06 17:39:25 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective ! = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
2019-09-26 17:01:50 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_EXIT_TRAIN & & m_nPedState ! = PED_ENTER_TRAIN & & m_nPedState ! = PED_SEEK_IN_BOAT & &
m_objective ! = OBJECTIVE_ENTER_CAR_AS_PASSENGER & & m_objective ! = OBJECTIVE_SOLICIT_VEHICLE & & ! bDuckAndCover ) {
if ( ( ! m_pedInObjective | | ! m_pedInObjective - > bInVehicle )
& & ! ( ( CTimer : : GetFrameCounter ( ) + ( m_randomSeed % 256 ) + 17 ) & 7 ) ) {
2019-10-05 09:44:03 -04:00
2020-11-19 14:12:20 -05:00
CEntity * obstacle = CWorld : : TestSphereAgainstWorld ( m_vecSeekPos , 0.4f , nil ,
false , true , false , false , false , false ) ;
2019-10-05 09:44:03 -04:00
2020-11-19 14:12:20 -05:00
if ( obstacle ) {
if ( ! obstacle - > IsVehicle ( ) | | ( ( CVehicle * ) obstacle ) - > m_vehType = = VEHICLE_TYPE_CAR ) {
distanceToCountItDone = 2.5f ;
} else {
CVehicleModelInfo * vehModel = ( CVehicleModelInfo * ) CModelInfo : : GetModelInfo ( obstacle - > GetModelIndex ( ) ) ;
float yLength = vehModel - > GetColModel ( ) - > boundingBox . max . y
- vehModel - > GetColModel ( ) - > boundingBox . min . y ;
distanceToCountItDone = yLength * 0.55f ;
}
}
}
}
2019-09-29 12:44:51 -04:00
}
2019-10-05 14:50:02 -04:00
2020-11-19 14:12:20 -05:00
if ( ! m_pSeekTarget & & m_nPedState = = PED_SEEK_ENTITY )
ClearSeek ( ) ;
2019-10-05 14:50:02 -04:00
2020-11-19 14:12:20 -05:00
float seekPosDist = ( m_vecSeekPos - GetPosition ( ) ) . Magnitude2D ( ) ;
if ( seekPosDist < 2.0f | | m_objective = = OBJECTIVE_GOTO_AREA_ON_FOOT ) {
if ( m_objective = = OBJECTIVE_FOLLOW_CHAR_IN_FORMATION ) {
if ( m_pedInObjective - > m_nMoveState ! = PEDMOVE_STILL )
nextMove = m_pedInObjective - > m_nMoveState ;
} else
nextMove = PEDMOVE_WALK ;
} else if ( m_objective ! = OBJECTIVE_FOLLOW_CHAR_IN_FORMATION ) {
if ( m_objective = = OBJECTIVE_KILL_CHAR_ON_FOOT | | m_objective = = OBJECTIVE_KILL_CHAR_ANY_MEANS | | m_objective = = OBJECTIVE_RUN_TO_AREA | | bIsRunning )
nextMove = PEDMOVE_RUN ;
else
nextMove = PEDMOVE_WALK ;
} else if ( seekPosDist < = 2.0f ) {
if ( m_pedInObjective - > m_nMoveState ! = PEDMOVE_STILL )
nextMove = m_pedInObjective - > m_nMoveState ;
} else {
nextMove = PEDMOVE_RUN ;
}
if ( m_nPedState = = PED_SEEK_ENTITY ) {
if ( m_pSeekTarget - > IsPed ( ) ) {
if ( ( ( CPed * ) m_pSeekTarget ) - > bInVehicle )
distanceToCountItDone + = 2.0f ;
}
}
if ( seekPosDist > = distanceToCountItDone ) {
if ( bIsRunning )
nextMove = PEDMOVE_RUN ;
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_nPedStateTimer ) {
if ( m_actionX ! = 0.0f & & m_actionY ! = 0.0f ) {
m_fRotationDest = CGeneral : : GetRadianAngleBetweenPoints (
m_actionX , m_actionY ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
float neededTurn = Abs ( m_fRotationDest - m_fRotationCur ) ;
if ( neededTurn > PI )
neededTurn = TWOPI - neededTurn ;
if ( neededTurn > HALFPI ) {
if ( seekPosDist > = 1.0f ) {
if ( seekPosDist < 2.0f ) {
if ( bIsRunning )
nextMove = PEDMOVE_RUN ;
else
nextMove = PEDMOVE_WALK ;
}
} else {
nextMove = PEDMOVE_STILL ;
}
}
CVector2D moveDist ( GetPosition ( ) . x - m_actionX , GetPosition ( ) . y - m_actionY ) ;
if ( moveDist . Magnitude ( ) < 0.5f ) {
m_nPedStateTimer = 0 ;
m_actionX = 0 ;
m_actionY = 0 ;
}
}
} else {
m_fRotationDest = CGeneral : : GetRadianAngleBetweenPoints (
m_vecSeekPos . x , m_vecSeekPos . y ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
float neededTurn = Abs ( m_fRotationDest - m_fRotationCur ) ;
if ( neededTurn > PI )
neededTurn = TWOPI - neededTurn ;
if ( neededTurn > HALFPI ) {
if ( seekPosDist > = 1.0 & & neededTurn < = DEGTORAD ( 135.0f ) ) {
if ( seekPosDist < 2.0f )
nextMove = PEDMOVE_WALK ;
} else {
nextMove = PEDMOVE_STILL ;
}
}
}
if ( ( ( m_nPedState = = PED_FLEE_POS | | m_nPedState = = PED_FLEE_ENTITY ) & & m_nMoveState < nextMove )
| | ( m_nPedState ! = PED_FLEE_POS & & m_nPedState ! = PED_FLEE_ENTITY & & m_objective ! = OBJECTIVE_GOTO_CHAR_ON_FOOT & & m_nWaitState = = WAITSTATE_FALSE ) ) {
SetMoveState ( nextMove ) ;
}
SetMoveAnim ( ) ;
2019-10-05 14:50:02 -04:00
return false ;
2020-11-19 14:12:20 -05:00
}
if ( ( m_objective ! = OBJECTIVE_FOLLOW_CHAR_IN_FORMATION | | m_pedInObjective - > m_nMoveState = = PEDMOVE_STILL ) & & m_nMoveState ! = PEDMOVE_STILL ) {
m_nPedStateTimer = 0 ;
m_actionX = 0 ;
m_actionY = 0 ;
}
if ( m_objective = = OBJECTIVE_GOTO_AREA_ON_FOOT | | m_objective = = OBJECTIVE_RUN_TO_AREA | | m_objective = = OBJECTIVE_GOTO_AREA_ANY_MEANS ) {
if ( m_pNextPathNode )
m_pNextPathNode = nil ;
else
bScriptObjectiveCompleted = true ;
bUsePedNodeSeek = true ;
}
if ( SeekFollowingPath ( nil ) )
m_nCurPathNode + + ;
2019-10-05 14:50:02 -04:00
return true ;
}
2019-09-29 12:44:51 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : SetFlee ( CVector2D const & from , int time )
2019-09-29 12:44:51 -04:00
{
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) < m_nPedStateTimer | | ! IsPedInControl ( ) | | bKindaStayInSamePlace )
return ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_FLEE_ENTITY ) {
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_FLEE_POS ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_RUN ) ;
m_fleeFromPosX = from . x ;
m_fleeFromPosY = from . y ;
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
bUsePedNodeSeek = true ;
m_pNextPathNode = nil ;
m_fleeTimer = CTimer : : GetTimeInMilliseconds ( ) + time ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
float angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
GetPosition ( ) . x , GetPosition ( ) . y ,
from . x , from . y ) ;
m_fRotationDest = CGeneral : : LimitRadianAngle ( angleToFace ) ;
if ( m_fRotationCur - PI > m_fRotationDest ) {
m_fRotationDest + = 2 * PI ;
} else if ( PI + m_fRotationCur < m_fRotationDest ) {
m_fRotationDest - = 2 * PI ;
2020-07-01 08:28:43 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-11-24 21:25:10 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetFlee ( CEntity * fleeFrom , int time )
{
if ( ! IsPedInControl ( ) | | bKindaStayInSamePlace | | ! fleeFrom )
return ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_FLEE_ENTITY ) ;
2020-11-19 14:12:20 -05:00
bUsePedNodeSeek = true ;
SetMoveState ( PEDMOVE_RUN ) ;
m_fleeFrom = fleeFrom ;
m_fleeFrom - > RegisterReference ( ( CEntity * * ) & m_fleeFrom ) ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( time < = 0 )
m_fleeTimer = 0 ;
else
m_fleeTimer = CTimer : : GetTimeInMilliseconds ( ) + time ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
float angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
GetPosition ( ) . x , GetPosition ( ) . y ,
fleeFrom - > GetPosition ( ) . x , fleeFrom - > GetPosition ( ) . y ) ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
m_fRotationDest = CGeneral : : LimitRadianAngle ( angleToFace ) ;
if ( m_fRotationCur - PI > m_fRotationDest ) {
m_fRotationDest + = 2 * PI ;
} else if ( PI + m_fRotationCur < m_fRotationDest ) {
m_fRotationDest - = 2 * PI ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : ClearFlee ( void )
{
RestorePreviousState ( ) ;
bUsePedNodeSeek = false ;
2021-01-13 07:41:24 -05:00
m_chatTimer = 0 ;
2020-11-19 14:12:20 -05:00
m_fleeTimer = 0 ;
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : Flee ( void )
{
if ( CTimer : : GetTimeInMilliseconds ( ) > m_fleeTimer & & m_fleeTimer ) {
bool mayFinishFleeing = true ;
if ( m_nPedState = = PED_FLEE_ENTITY ) {
if ( ( CVector2D ( GetPosition ( ) ) - ms_vec2DFleePosition ) . MagnitudeSqr ( ) < sq ( 30.0f ) )
mayFinishFleeing = false ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
if ( mayFinishFleeing ) {
eMoveState moveState = m_nMoveState ;
ClearFlee ( ) ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective = = OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE | | m_objective = = OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS )
RestorePreviousObjective ( ) ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( ( m_nPedState = = PED_IDLE | | m_nPedState = = PED_WANDER_PATH ) & & CGeneral : : GetRandomNumber ( ) & 1 ) {
SetWaitState ( moveState < = PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE , nil ) ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
return ;
}
m_fleeTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
}
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
if ( bUsePedNodeSeek ) {
CPathNode * realLastNode = nil ;
uint8 nextDirection = 0 ;
uint8 curDirectionShouldBe = 9 ; // means not defined yet
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedStateTimer < CTimer : : GetTimeInMilliseconds ( )
& & m_collidingThingTimer < CTimer : : GetTimeInMilliseconds ( ) ) {
2019-11-04 18:04:26 -05:00
2021-01-13 07:41:24 -05:00
if ( m_pNextPathNode & & CTimer : : GetTimeInMilliseconds ( ) > m_chatTimer ) {
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
curDirectionShouldBe = CGeneral : : GetNodeHeadingFromVector ( GetPosition ( ) . x - ms_vec2DFleePosition . x , GetPosition ( ) . y - ms_vec2DFleePosition . y ) ;
if ( m_nPathDir < curDirectionShouldBe )
m_nPathDir + = 8 ;
int dirDiff = m_nPathDir - curDirectionShouldBe ;
if ( dirDiff > 2 & & dirDiff < 6 ) {
realLastNode = nil ;
m_pLastPathNode = m_pNextPathNode ;
m_pNextPathNode = nil ;
2019-09-29 12:44:51 -04:00
}
}
2020-11-19 14:12:20 -05:00
if ( m_pNextPathNode ) {
m_vecSeekPos = m_pNextPathNode - > GetPosition ( ) ;
if ( m_nMoveState = = PEDMOVE_RUN )
bIsRunning = true ;
eMoveState moveState = m_nMoveState ;
if ( Seek ( ) ) {
realLastNode = m_pLastPathNode ;
m_pLastPathNode = m_pNextPathNode ;
m_pNextPathNode = nil ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
bIsRunning = false ;
SetMoveState ( moveState ) ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( ! m_pNextPathNode ) {
if ( curDirectionShouldBe = = 9 ) {
curDirectionShouldBe = CGeneral : : GetNodeHeadingFromVector ( GetPosition ( ) . x - ms_vec2DFleePosition . x , GetPosition ( ) . y - ms_vec2DFleePosition . y ) ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
ThePaths . FindNextNodeWandering ( PATH_PED , GetPosition ( ) , & m_pLastPathNode , & m_pNextPathNode ,
curDirectionShouldBe ,
& nextDirection ) ;
if ( curDirectionShouldBe < nextDirection )
curDirectionShouldBe + = 8 ;
if ( m_pNextPathNode & & m_pNextPathNode ! = realLastNode & & m_pNextPathNode ! = m_pLastPathNode & & curDirectionShouldBe - nextDirection ! = 4 ) {
m_nPathDir = nextDirection ;
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 2000 ;
2020-11-19 14:12:20 -05:00
} else {
bUsePedNodeSeek = false ;
SetMoveState ( PEDMOVE_RUN ) ;
Flee ( ) ;
2019-09-29 12:44:51 -04:00
}
}
2020-11-19 14:12:20 -05:00
return ;
}
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
if ( ( m_nPedState = = PED_FLEE_ENTITY | | m_nPedState = = PED_ON_FIRE ) & & m_nPedStateTimer < CTimer : : GetTimeInMilliseconds ( ) ) {
float angleToFleeFromPos = CGeneral : : GetRadianAngleBetweenPoints (
GetPosition ( ) . x ,
GetPosition ( ) . y ,
ms_vec2DFleePosition . x ,
ms_vec2DFleePosition . y ) ;
m_fRotationDest = CGeneral : : LimitRadianAngle ( angleToFleeFromPos ) ;
if ( m_fRotationCur - PI > m_fRotationDest )
m_fRotationDest + = TWOPI ;
else if ( PI + m_fRotationCur < m_fRotationDest )
m_fRotationDest - = TWOPI ;
}
if ( CTimer : : GetTimeInMilliseconds ( ) & 0x20 ) {
//CVector forwardPos = GetPosition();
CMatrix forwardMat ( GetMatrix ( ) ) ;
forwardMat . GetPosition ( ) + = Multiply3x3 ( forwardMat , CVector ( 0.0f , 4.0f , 0.0f ) ) ;
CVector forwardPos = forwardMat . GetPosition ( ) ;
CEntity * foundEnt ;
CColPoint foundCol ;
bool found = CWorld : : ProcessVerticalLine ( forwardPos , forwardMat . GetPosition ( ) . z - 100.0f , foundCol , foundEnt , 1 , 0 , 0 , 0 , 1 , 0 , 0 ) ;
if ( ! found | | Abs ( forwardPos . z - forwardMat . GetPosition ( ) . z ) > 1.0f ) {
m_fRotationDest + = DEGTORAD ( 112.5f ) ;
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( ) + 2000 ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) > = m_collidingThingTimer )
return ;
if ( ! m_collidingEntityWhileFleeing )
return ;
double collidingThingPriorityMult = ( double ) ( m_collidingThingTimer - CTimer : : GetTimeInMilliseconds ( ) ) * 2.0 / 2500 ;
if ( collidingThingPriorityMult < = 1.5 ) {
double angleToFleeEntity = CGeneral : : GetRadianAngleBetweenPoints (
GetPosition ( ) . x ,
GetPosition ( ) . y ,
m_collidingEntityWhileFleeing - > GetPosition ( ) . x ,
m_collidingEntityWhileFleeing - > GetPosition ( ) . y ) ;
angleToFleeEntity = CGeneral : : LimitRadianAngle ( angleToFleeEntity ) ;
double angleToFleeCollidingThing = CGeneral : : GetRadianAngleBetweenPoints (
m_vecDamageNormal . x ,
m_vecDamageNormal . y ,
0.0f ,
0.0f ) ;
angleToFleeCollidingThing = CGeneral : : LimitRadianAngle ( angleToFleeCollidingThing ) ;
if ( angleToFleeEntity - PI > angleToFleeCollidingThing )
angleToFleeCollidingThing + = TWOPI ;
else if ( PI + angleToFleeEntity < angleToFleeCollidingThing )
angleToFleeCollidingThing - = TWOPI ;
if ( collidingThingPriorityMult < = 1.0f ) {
// Range [0.0, 1.0]
float angleToFleeBoth = ( angleToFleeCollidingThing + angleToFleeEntity ) * 0.5f ;
if ( m_fRotationDest - PI > angleToFleeBoth )
angleToFleeBoth + = TWOPI ;
else if ( PI + m_fRotationDest < angleToFleeBoth )
angleToFleeBoth - = TWOPI ;
m_fRotationDest = ( 1.0f - collidingThingPriorityMult ) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth ;
2019-09-29 12:44:51 -04:00
} else {
2020-11-19 14:12:20 -05:00
// Range (1.0, 1.5]
double adjustedMult = ( collidingThingPriorityMult - 1.0f ) * 2.0f ;
m_fRotationDest = angleToFleeEntity * ( 1.0 - adjustedMult ) + adjustedMult * angleToFleeCollidingThing ;
}
} else {
m_fRotationDest = CGeneral : : GetRadianAngleBetweenPoints (
m_vecDamageNormal . x ,
m_vecDamageNormal . y ,
0.0f ,
0.0f ) ;
m_fRotationDest = CGeneral : : LimitRadianAngle ( m_fRotationDest ) ;
}
m_fRotationCur = CGeneral : : LimitRadianAngle ( m_fRotationCur ) ;
if ( m_fRotationCur - PI > m_fRotationDest )
m_fRotationDest + = TWOPI ;
else if ( PI + m_fRotationCur < m_fRotationDest )
m_fRotationDest - = TWOPI ;
}
// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway
void
CPed : : WanderRange ( void )
{
bool arrived = Seek ( ) ;
if ( arrived ) {
Idle ( ) ;
if ( ( m_randomSeed + 3 * CTimer : : GetFrameCounter ( ) ) % 1000 > 997 ) {
CVector2D newCoords2D = m_wanderRangeBounds - > GetRandomPointInRange ( ) ;
SetSeek ( CVector ( newCoords2D . x , newCoords2D . y , GetPosition ( ) . z ) , 2.5f ) ;
2019-09-29 12:44:51 -04:00
}
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : SetWanderPath ( int8 pathStateDest )
{
uint8 nextPathState ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
if ( IsPedInControl ( ) ) {
if ( bKindaStayInSamePlace ) {
SetIdle ( ) ;
return false ;
} else {
m_nPathDir = pathStateDest ;
if ( pathStateDest = = 0 )
pathStateDest = CGeneral : : GetRandomNumberInRange ( 1 , 7 ) ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
ThePaths . FindNextNodeWandering ( PATH_PED , GetPosition ( ) , & m_pLastPathNode , & m_pNextPathNode ,
m_nPathDir , & nextPathState ) ;
// Circular loop until we find a node for current m_nPathDir
while ( ! m_pNextPathNode ) {
m_nPathDir = ( m_nPathDir + 1 ) % 8 ;
// We're at where we started and couldn't find any node
if ( m_nPathDir = = pathStateDest ) {
ClearAll ( ) ;
SetIdle ( ) ;
return false ;
}
ThePaths . FindNextNodeWandering ( PATH_PED , GetPosition ( ) , & m_pLastPathNode , & m_pNextPathNode ,
m_nPathDir , & nextPathState ) ;
}
// We did it, save next path state and return true
m_nPathDir = nextPathState ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_WANDER_PATH ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_WALK ) ;
bIsRunning = false ;
return true ;
}
2019-09-29 12:44:51 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_nPathDir = pathStateDest ;
bStartWanderPathOnFoot = true ;
return false ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : WanderPath ( void )
{
if ( ! m_pNextPathNode ) {
printf ( " THIS SHOULDN@T HAPPEN TOO OFTEN \n " ) ;
SetIdle ( ) ;
return ;
}
if ( m_nWaitState = = WAITSTATE_FALSE ) {
if ( m_nMoveState = = PEDMOVE_STILL | | m_nMoveState = = PEDMOVE_NONE )
SetMoveState ( PEDMOVE_WALK ) ;
}
m_vecSeekPos = m_pNextPathNode - > GetPosition ( ) ;
m_vecSeekPos . z + = 1.0f ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
// Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
if ( ! Seek ( ) )
return ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
CPathNode * previousLastNode = m_pLastPathNode ;
uint8 randVal = ( m_randomSeed + 3 * CTimer : : GetFrameCounter ( ) ) % 100 ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
// We don't prefer 180-degree turns in normal situations
uint8 dirWeWouldntPrefer = m_nPathDir ;
if ( dirWeWouldntPrefer < = 3 )
dirWeWouldntPrefer + = 4 ;
else
dirWeWouldntPrefer - = 4 ;
CPathNode * nodeWeWouldntPrefer = nil ;
uint8 dirToSet = 9 ; // means undefined
uint8 dirWeWouldntPrefer2 = 9 ; // means undefined
if ( randVal < = 90 ) {
if ( randVal > 80 ) {
m_nPathDir + = 2 ;
m_nPathDir % = 8 ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
m_nPathDir - = 2 ;
if ( m_nPathDir < 0 )
m_nPathDir + = 8 ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
m_pLastPathNode = m_pNextPathNode ;
ThePaths . FindNextNodeWandering ( PATH_PED , GetPosition ( ) , & m_pLastPathNode , & m_pNextPathNode ,
m_nPathDir , & dirToSet ) ;
uint8 tryCount = 0 ;
// NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7
while ( ! m_pNextPathNode ) {
tryCount + + ;
m_nPathDir = ( m_nPathDir + 1 ) % 8 ;
// We're at where we started and couldn't find any node
if ( tryCount > 7 ) {
if ( ! nodeWeWouldntPrefer ) {
ClearAll ( ) ;
SetIdle ( ) ;
// Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.
Error ( " Can't find valid path node, SetWanderPath, Ped.cpp " ) ;
return ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
m_pNextPathNode = nodeWeWouldntPrefer ;
dirToSet = dirWeWouldntPrefer2 ;
2019-09-29 12:44:51 -04:00
} else {
2020-11-19 14:12:20 -05:00
ThePaths . FindNextNodeWandering ( PATH_PED , GetPosition ( ) , & m_pLastPathNode , & m_pNextPathNode ,
m_nPathDir , & dirToSet ) ;
if ( m_pNextPathNode ) {
if ( dirToSet = = dirWeWouldntPrefer ) {
nodeWeWouldntPrefer = m_pNextPathNode ;
dirWeWouldntPrefer2 = dirToSet ;
m_pNextPathNode = nil ;
}
2019-09-29 12:44:51 -04:00
}
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
m_nPathDir = dirToSet ;
if ( m_pLastPathNode = = m_pNextPathNode ) {
m_pNextPathNode = previousLastNode ;
SetWaitState ( WAITSTATE_DOUBLEBACK , nil ) ;
Say ( SOUND_PED_WAIT_DOUBLEBACK ) ;
} else if ( ThePaths . TestForPedTrafficLight ( m_pLastPathNode , m_pNextPathNode ) ) {
SetWaitState ( WAITSTATE_TRAFFIC_LIGHTS , nil ) ;
} else if ( ThePaths . TestCrossesRoad ( m_pLastPathNode , m_pNextPathNode ) ) {
SetWaitState ( WAITSTATE_CROSS_ROAD , nil ) ;
} else if ( m_pNextPathNode = = previousLastNode ) {
SetWaitState ( WAITSTATE_DOUBLEBACK , nil ) ;
Say ( SOUND_PED_WAIT_DOUBLEBACK ) ;
}
}
void
CPed : : Avoid ( void )
{
CPed * nearestPed ;
if ( m_pedStats - > m_temper > m_pedStats - > m_fear & & m_pedStats - > m_temper > 50 )
return ;
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nPedStateTimer ) {
if ( m_nMoveState ! = PEDMOVE_NONE & & m_nMoveState ! = PEDMOVE_STILL ) {
nearestPed = m_nearPeds [ 0 ] ;
if ( nearestPed & & nearestPed - > m_nPedState ! = PED_DEAD & & nearestPed ! = m_pSeekTarget & & nearestPed ! = m_pedInObjective ) {
// Check if this ped wants to avoid the nearest one
if ( CPedType : : GetAvoid ( m_nPedType ) & CPedType : : GetFlag ( nearestPed - > m_nPedType ) ) {
// Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters.
// If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else.
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
// Game converts from radians to degress and back again here, doesn't make much sense
CVector2D forward ( - Sin ( m_fRotationCur ) , Cos ( m_fRotationCur ) ) ;
forward . Normalise ( ) ; // this is kinda pointless
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
// Move forward 1.25 meters
CVector2D testPosition = CVector2D ( GetPosition ( ) ) + forward * 1.25f ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
// Get distance to ped we want to avoid
CVector2D distToPed = CVector2D ( nearestPed - > GetPosition ( ) ) - testPosition ;
if ( distToPed . Magnitude ( ) < = 1.0f & & OurPedCanSeeThisOne ( ( CEntity * ) nearestPed ) ) {
m_nPedStateTimer = CTimer : : GetTimeInMilliseconds ( )
+ 500 + ( m_randomSeed + 3 * CTimer : : GetFrameCounter ( ) )
% 1000 / 5 ;
m_fRotationDest + = DEGTORAD ( 45.0f ) ;
if ( ! bIsLooking ) {
SetLookFlag ( nearestPed , false ) ;
SetLookTimer ( CGeneral : : GetRandomNumberInRange ( 500 , 800 ) ) ;
}
}
2019-09-29 12:44:51 -04:00
}
}
}
}
2020-11-19 14:12:20 -05:00
}
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : SeekFollowingPath ( CVector * unused )
{
return m_nCurPathNode < = m_nPathNodes & & m_nPathNodes ;
}
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : SetFollowPath ( CVector dest )
{
if ( m_nPedState = = PED_FOLLOW_PATH )
return false ;
if ( FindPlayerPed ( ) ! = this )
return false ;
if ( ( dest - GetPosition ( ) ) . Magnitude ( ) < = 2.0f )
return false ;
CVector pointPoses [ 7 ] ;
int16 pointsFound ;
CPedPath : : CalcPedRoute ( 0 , GetPosition ( ) , dest , pointPoses , & pointsFound , 7 ) ;
for ( int i = 0 ; i < pointsFound ; i + + ) {
m_stPathNodeStates [ i ] . x = pointPoses [ i ] . x ;
m_stPathNodeStates [ i ] . y = pointPoses [ i ] . y ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
m_nCurPathNode = 0 ;
m_nPathNodes = pointsFound ;
if ( m_nPathNodes < 1 )
return false ;
2019-09-29 12:44:51 -04:00
2020-11-19 14:12:20 -05:00
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_FOLLOW_PATH ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_WALK ) ;
return true ;
2019-09-29 12:44:51 -04:00
}
2020-11-19 14:12:20 -05:00
void
CPed : : FollowPath ( void )
2019-10-02 21:02:02 -04:00
{
2020-11-19 14:12:20 -05:00
m_vecSeekPos . x = m_stPathNodeStates [ m_nCurPathNode ] . x ;
m_vecSeekPos . y = m_stPathNodeStates [ m_nCurPathNode ] . y ;
m_vecSeekPos . z = GetPosition ( ) . z ;
// Mysterious code
/* int v4 = 0;
int maxNodeIndex = m_nPathNodes - 1 ;
if ( maxNodeIndex > 0 ) {
if ( maxNodeIndex > 8 ) {
while ( v4 < maxNodeIndex - 8 )
v4 + = 8 ;
}
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
while ( v4 < maxNodeIndex )
v4 + + ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
}
*/
if ( Seek ( ) ) {
m_nCurPathNode + + ;
if ( m_nCurPathNode = = m_nPathNodes )
RestorePreviousState ( ) ;
}
}
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetEvasiveStep ( CEntity * reason , uint8 animType )
{
AnimationId stepAnim ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_STEP_AWAY | | ! IsPedInControl ( ) | | ( ( IsPlayer ( ) | | ! bRespondsToThreats ) & & animType = = 0 ) )
return ;
2019-10-05 14:50:02 -04:00
2020-11-19 14:12:20 -05:00
float angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
reason - > GetPosition ( ) . x , reason - > GetPosition ( ) . y ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
angleToFace = CGeneral : : LimitRadianAngle ( angleToFace ) ;
m_fRotationCur = CGeneral : : LimitRadianAngle ( m_fRotationCur ) ;
float neededTurn = Abs ( angleToFace - m_fRotationCur ) ;
bool vehPressedHorn = false ;
if ( neededTurn > PI )
neededTurn = TWOPI - neededTurn ;
CVehicle * veh = ( CVehicle * ) reason ;
if ( reason - > IsVehicle ( ) & & veh - > m_vehType = = VEHICLE_TYPE_CAR ) {
if ( veh - > m_nCarHornTimer ! = 0 ) {
vehPressedHorn = true ;
if ( ! IsPlayer ( ) )
animType = 1 ;
}
}
if ( neededTurn < = DEGTORAD ( 90.0f ) | | veh - > GetModelIndex ( ) = = MI_RCBANDIT | | vehPressedHorn | | animType ! = 0 ) {
SetLookFlag ( veh , true ) ;
if ( ( CGeneral : : GetRandomNumber ( ) & 1 ) & & veh - > GetModelIndex ( ) ! = MI_RCBANDIT & & animType = = 0 ) {
stepAnim = ANIM_IDLE_TAXI ;
} else {
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 - = TWOPI ;
// 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 = vehDirection - HALFPI ;
else
angleToFace = vehDirection + HALFPI ;
stepAnim = NUM_ANIMS ;
if ( animType = = 0 | | animType = = 1 )
stepAnim = ANIM_EV_STEP ;
else if ( animType = = 2 )
stepAnim = ANIM_HANDSCOWER ;
}
if ( ! RpAnimBlendClumpGetAssociation ( GetClump ( ) , stepAnim ) ) {
CAnimBlendAssociation * stepAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , stepAnim , 8.0f ) ;
stepAssoc - > flags & = ~ ASSOC_DELETEFADEDOUT ;
stepAssoc - > SetFinishCallback ( PedEvadeCB , this ) ;
if ( animType = = 0 )
Say ( SOUND_PED_EVADE ) ;
m_fRotationCur = CGeneral : : LimitRadianAngle ( angleToFace ) ;
ClearAimFlag ( ) ;
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_STEP_AWAY ) ;
2019-10-02 21:02:02 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetEvasiveDive ( CPhysical * reason , uint8 onlyRandomJump )
{
if ( ! IsPedInControl ( ) | | ! bRespondsToThreats )
return ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * animAssoc ;
float angleToFace , neededTurn ;
bool handsUp = false ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
angleToFace = m_fRotationCur ;
CVehicle * veh = ( CVehicle * ) reason ;
if ( reason - > IsVehicle ( ) & & veh - > m_vehType = = VEHICLE_TYPE_CAR & & veh - > m_nCarHornTimer ! = 0 & & ! IsPlayer ( ) ) {
onlyRandomJump = true ;
}
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
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.
2020-09-09 20:14:50 -04:00
2020-11-19 14:12:20 -05:00
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_nEvadeAmount = 5 ;
( ( CPlayerPed * ) this ) - > m_pEvadingFrom = reason ;
reason - > RegisterReference ( ( CEntity * * ) & ( ( CPlayerPed * ) this ) - > m_pEvadingFrom ) ;
return ;
}
2020-09-09 20:14:50 -04:00
2020-11-19 14:12:20 -05:00
angleToFace = CGeneral : : GetRadianAngleBetweenPoints (
reason - > GetPosition ( ) . x , reason - > GetPosition ( ) . y ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
angleToFace = CGeneral : : LimitRadianAngle ( angleToFace ) ;
m_fRotationCur = CGeneral : : LimitRadianAngle ( m_fRotationCur ) ;
2020-09-09 20:14:50 -04:00
2020-11-19 14:12:20 -05:00
// 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 ) ;
2020-09-09 20:14:50 -04:00
2020-11-19 14:12:20 -05:00
// Let's turn our back to the "reason"
angleToFace + = PI ;
2020-09-09 20:14:50 -04:00
2020-11-19 14:12:20 -05:00
if ( angleToFace > PI )
angleToFace - = 2 * PI ;
2020-09-09 20:14:50 -04:00
2020-11-19 14:12:20 -05:00
// 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 ;
2019-10-02 21:02:02 -04:00
# endif
2020-11-19 14:12:20 -05:00
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 ;
2019-10-02 21:02:02 -04:00
}
2020-11-19 14:12:20 -05:00
Say ( SOUND_PED_EVADE ) ;
2019-10-02 21:02:02 -04:00
}
2020-11-19 14:12:20 -05:00
if ( handsUp | | ! IsPlayer ( ) & & m_pedStats - > m_flags & STAT_NO_DIVE ) {
m_fRotationCur = angleToFace ;
ClearLookFlag ( ) ;
ClearAimFlag ( ) ;
SetLookFlag ( reason , true ) ;
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_HANDSUP ) ;
if ( animAssoc )
return ;
2019-10-02 21:02:02 -04:00
2020-11-19 14:12:20 -05:00
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_HANDSUP , 8.0f ) ;
animAssoc - > flags & = ~ ASSOC_DELETEFADEDOUT ;
animAssoc - > SetFinishCallback ( PedEvadeCB , this ) ;
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_STEP_AWAY ) ;
2020-11-19 14:12:20 -05:00
} else {
m_fRotationCur = angleToFace ;
ClearLookFlag ( ) ;
ClearAimFlag ( ) ;
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_DIVE_AWAY ) ;
2020-11-19 14:12:20 -05:00
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_EV_DIVE , 8.0f ) ;
animAssoc - > SetFinishCallback ( PedEvadeCB , this ) ;
2019-10-02 21:02:02 -04:00
}
2020-11-19 14:12:20 -05:00
if ( reason - > IsVehicle ( ) & & m_nPedType = = PEDTYPE_COP ) {
if ( veh - > pDriver & & veh - > pDriver - > IsPlayer ( ) ) {
CWanted * wanted = FindPlayerPed ( ) - > m_pWanted ;
wanted - > RegisterCrime_Immediately ( CRIME_RECKLESS_DRIVING , GetPosition ( ) , ( uintptr ) this , false ) ;
wanted - > RegisterCrime_Immediately ( CRIME_SPEEDING , GetPosition ( ) , ( uintptr ) this , false ) ;
2019-10-02 21:02:02 -04:00
}
}
2020-11-19 14:12:20 -05:00
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
else if ( reason - > IsVehicle ( ) ) {
if ( veh - > pDriver & & veh - > pDriver - > IsPlayer ( ) ) {
CWanted * wanted = FindPlayerPed ( ) - > m_pWanted ;
wanted - > RegisterCrime ( CRIME_RECKLESS_DRIVING , GetPosition ( ) , ( uintptr ) this , false ) ;
}
}
# endif
2019-10-02 21:02:02 -04:00
}
2019-10-06 17:39:25 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : PedEvadeCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
if ( ! animAssoc ) {
ped - > ClearLookFlag ( ) ;
if ( ped - > m_nPedState = = PED_DIVE_AWAY | | ped - > m_nPedState = = PED_STEP_AWAY )
ped - > RestorePreviousState ( ) ;
} else if ( animAssoc - > animId = = ANIM_EV_DIVE ) {
ped - > bUpdateAnimHeading = true ;
ped - > ClearLookFlag ( ) ;
if ( ped - > m_nPedState = = PED_DIVE_AWAY )
{
ped - > m_getUpTimer = CTimer : : GetTimeInMilliseconds ( ) + 1 ;
2020-12-14 22:11:02 -05:00
ped - > SetPedState ( PED_FALL ) ;
2020-11-19 14:12:20 -05:00
}
animAssoc - > flags & = ~ ASSOC_FADEOUTWHENDONE ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
} else if ( animAssoc - > flags & ASSOC_FADEOUTWHENDONE ) {
ped - > ClearLookFlag ( ) ;
if ( ped - > m_nPedState = = PED_DIVE_AWAY | | ped - > m_nPedState = = PED_STEP_AWAY )
ped - > RestorePreviousState ( ) ;
} else if ( ped - > m_nPedState ! = PED_ARRESTED ) {
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
if ( animAssoc - > blendDelta > = 0.0f )
animAssoc - > blendDelta = - 4.0f ;
ped - > ClearLookFlag ( ) ;
if ( ped - > m_nPedState = = PED_DIVE_AWAY | | ped - > m_nPedState = = PED_STEP_AWAY ) {
ped - > RestorePreviousState ( ) ;
}
2019-10-06 17:39:25 -04:00
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetDie ( AnimationId animId , float delta , float speed )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
CPlayerPed * player = FindPlayerPed ( ) ;
if ( player = = this ) {
if ( ! player - > m_bCanBeDamaged )
return ;
}
2019-10-06 17:39:25 -04:00
2020-11-19 14:12:20 -05:00
m_threatEntity = nil ;
if ( DyingOrDead ( ) )
return ;
if ( m_nPedState = = PED_FALL | | m_nPedState = = PED_GETUP )
delta * = 0.5f ;
SetStoredState ( ) ;
ClearAll ( ) ;
m_fHealth = 0.0f ;
if ( m_nPedState = = PED_DRIVING ) {
if ( ! IsPlayer ( ) )
FlagToDestroyWhenNextProcessed ( ) ;
} else if ( bInVehicle ) {
if ( m_pVehicleAnim )
m_pVehicleAnim - > blendDelta = - 1000.0f ;
} else if ( EnteringCar ( ) ) {
QuitEnteringCar ( ) ;
2019-10-06 17:39:25 -04:00
}
2020-12-14 22:11:02 -05:00
SetPedState ( PED_DIE ) ;
2020-11-19 14:12:20 -05:00
if ( animId = = NUM_ANIMS ) {
bIsPedDieAnimPlaying = false ;
} else {
CAnimBlendAssociation * dieAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , animId , delta ) ;
if ( speed > 0.0f )
dieAssoc - > speed = speed ;
dieAssoc - > flags & = ~ ASSOC_FADEOUTWHENDONE ;
if ( dieAssoc - > IsRunning ( ) ) {
dieAssoc - > SetFinishCallback ( FinishDieAnimCB , this ) ;
bIsPedDieAnimPlaying = true ;
2019-10-06 17:39:25 -04:00
}
}
2020-11-19 14:12:20 -05:00
Say ( SOUND_PED_DEATH ) ;
if ( m_nLastPedState = = PED_ENTER_CAR | | m_nLastPedState = = PED_CARJACK )
QuitEnteringCar ( ) ;
if ( ! bInVehicle )
StopNonPartialAnims ( ) ;
m_bloodyFootprintCountOrDeathTime = CTimer : : GetTimeInMilliseconds ( ) ;
2019-10-06 17:39:25 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : FinishDieAnimCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
2019-10-06 17:39:25 -04:00
2020-11-19 14:12:20 -05:00
if ( ped - > bIsPedDieAnimPlaying )
ped - > bIsPedDieAnimPlaying = false ;
2019-10-06 17:39:25 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetDead ( void )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
bUsesCollision = false ;
2019-10-06 17:39:25 -04:00
2020-11-19 14:12:20 -05:00
m_fHealth = 0.0f ;
if ( m_nPedState = = PED_DRIVING )
bIsVisible = false ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_DEAD ) ;
2020-11-19 14:12:20 -05:00
m_pVehicleAnim = nil ;
m_pCollidingEntity = nil ;
CWeaponInfo * weapon = CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) ;
RemoveWeaponModel ( weapon - > m_nModelId ) ;
m_currentWeapon = WEAPONTYPE_UNARMED ;
CEventList : : RegisterEvent ( EVENT_INJURED_PED , EVENT_ENTITY_PED , this , nil , 250 ) ;
if ( this ! = FindPlayerPed ( ) ) {
CreateDeadPedWeaponPickups ( ) ;
CreateDeadPedMoney ( ) ;
2019-10-06 17:39:25 -04:00
}
2020-11-19 14:12:20 -05:00
m_bloodyFootprintCountOrDeathTime = CTimer : : GetTimeInMilliseconds ( ) ;
m_deadBleeding = false ;
bDoBloodyFootprints = false ;
bVehExitWillBeInstant = false ;
CEventList : : RegisterEvent ( EVENT_DEAD_PED , EVENT_ENTITY_PED , this , nil , 1000 ) ;
2019-10-06 17:39:25 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : Die ( void )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
// UNUSED: This is a perfectly empty function.
2019-10-06 17:39:25 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetChat ( CEntity * chatWith , uint32 time )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
if ( m_nPedState ! = PED_CHAT )
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_CHAT ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_STILL ) ;
# if defined VC_PED_PORTS || defined FIX_BUGS
m_lookTimer = 0 ;
# endif
SetLookFlag ( chatWith , true ) ;
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + time ;
2020-11-19 14:12:20 -05:00
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 3000 ;
2019-10-06 17:39:25 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : Chat ( void )
2019-10-06 17:39:25 -04:00
{
2020-11-19 14:12:20 -05:00
// We're already looking to our partner
if ( bIsLooking & & TurnBody ( ) )
ClearLookFlag ( ) ;
2019-10-06 17:39:25 -04:00
2020-11-19 14:12:20 -05:00
if ( ! m_pLookTarget | | ! m_pLookTarget - > IsPed ( ) ) {
ClearChat ( ) ;
2019-10-06 17:39:25 -04:00
return ;
2020-11-19 14:12:20 -05:00
}
2019-10-06 17:39:25 -04:00
2020-11-19 14:12:20 -05:00
CPed * partner = ( CPed * ) m_pLookTarget ;
if ( partner - > m_nPedState ! = PED_CHAT ) {
ClearChat ( ) ;
if ( partner - > m_pedInObjective ) {
if ( partner - > m_objective = = OBJECTIVE_KILL_CHAR_ON_FOOT | |
partner - > m_objective = = OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE )
ReactToAttack ( partner - > m_pedInObjective ) ;
2019-10-06 17:39:25 -04:00
}
2020-11-19 14:12:20 -05:00
return ;
}
if ( bIsTalking ) {
if ( CGeneral : : GetRandomNumber ( ) < 512 ) {
CAnimBlendAssociation * chatAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_CHAT ) ;
if ( chatAssoc ) {
chatAssoc - > blendDelta = - 4.0f ;
chatAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
bIsTalking = false ;
} else
Say ( SOUND_PED_CHAT ) ;
2019-10-06 17:39:25 -04:00
} else {
2020-11-19 14:12:20 -05:00
if ( CGeneral : : GetRandomNumber ( ) < 20 & & ! RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) , ASSOC_IDLE ) ) {
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_XPRESS_SCRATCH , 4.0f ) ;
}
if ( ! bIsTalking & & ! RpAnimBlendClumpGetFirstAssociation ( GetClump ( ) , ASSOC_IDLE ) ) {
CAnimBlendAssociation * chatAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_CHAT , 4.0f ) ;
float chatTime = CGeneral : : GetRandomNumberInRange ( 0.0f , 3.0f ) ;
chatAssoc - > SetCurrentTime ( chatTime ) ;
bIsTalking = true ;
Say ( SOUND_PED_CHAT ) ;
2019-10-06 17:39:25 -04:00
}
}
2021-01-13 07:41:24 -05:00
if ( m_chatTimer & & CTimer : : GetTimeInMilliseconds ( ) > m_chatTimer ) {
2020-11-19 14:12:20 -05:00
ClearChat ( ) ;
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 30000 ;
2019-10-06 17:39:25 -04:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : ClearChat ( void )
2019-10-12 10:03:32 -04:00
{
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_CHAT ) ;
if ( animAssoc ) {
animAssoc - > blendDelta = - 8.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
bIsTalking = false ;
ClearLookFlag ( ) ;
RestorePreviousState ( ) ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
2019-10-13 00:05:08 -04:00
void
2020-11-19 14:12:20 -05:00
ReportPhonePickUpCB ( CAnimBlendAssociation * assoc , void * arg )
2019-10-13 00:05:08 -04:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
ped - > m_nMoveState = PEDMOVE_STILL ;
CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_STANCE , 8.0f ) ;
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
if ( assoc - > blendAmount > 0.5f & & ped ) {
CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_PHONE_TALK , 8.0f ) ;
}
}
2020-04-23 16:25:18 -04:00
2020-11-19 14:12:20 -05:00
void
ReportPhonePutDownCB ( CAnimBlendAssociation * assoc , void * arg )
{
assoc - > flags | = ASSOC_DELETEFADEDOUT ;
assoc - > blendDelta = - 1000.0f ;
CPed * ped = ( CPed * ) arg ;
if ( ped - > m_phoneId ! = - 1 & & crimeReporters [ ped - > m_phoneId ] = = ped ) {
crimeReporters [ ped - > m_phoneId ] = nil ;
gPhoneInfo . m_aPhones [ ped - > m_phoneId ] . m_nState = PHONE_STATE_FREE ;
ped - > m_phoneId = - 1 ;
2020-04-23 16:25:18 -04:00
}
2020-11-19 14:12:20 -05:00
if ( assoc - > blendAmount > 0.5f )
ped - > bUpdateAnimHeading = true ;
ped - > SetWanderPath ( CGeneral : : GetRandomNumber ( ) & 7 ) ;
}
2020-04-23 16:25:18 -04:00
# endif
2020-11-19 14:12:20 -05:00
bool
CPed : : FacePhone ( void )
{
// This function was broken since it's left unused early in development.
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
float phoneDir = CGeneral : : GetRadianAngleBetweenPoints (
gPhoneInfo . m_aPhones [ m_phoneId ] . m_vecPos . x , gPhoneInfo . m_aPhones [ m_phoneId ] . m_vecPos . y ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
if ( m_facePhoneStart ) {
m_lookTimer = 0 ;
SetLookFlag ( phoneDir , true ) ;
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 3000 ;
m_facePhoneStart = false ;
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
if ( bIsLooking & & TurnBody ( ) ) {
ClearLookFlag ( ) ;
SetIdle ( ) ;
m_phoneTalkTimer = CTimer : : GetTimeInMilliseconds ( ) + 10000 ;
CAnimBlendAssociation * assoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_PHONE_IN , 4.0f ) ;
assoc - > SetFinishCallback ( ReportPhonePickUpCB , this ) ;
return true ;
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
return false ;
# else
float currentRot = RADTODEG ( m_fRotationCur ) ;
float phoneDir = CGeneral : : GetRadianAngleBetweenPoints (
gPhoneInfo . m_aPhones [ m_phoneId ] . m_vecPos . x ,
gPhoneInfo . m_aPhones [ m_phoneId ] . m_vecPos . y ,
GetPosition ( ) . x ,
GetPosition ( ) . y ) ;
SetLookFlag ( phoneDir , false ) ;
phoneDir = CGeneral : : LimitAngle ( phoneDir ) ;
m_moved = CVector2D ( 0.0f , 0.0f ) ;
if ( currentRot - 180.0f > phoneDir )
phoneDir + = 2 * 180.0f ;
else if ( 180.0f + currentRot < phoneDir )
phoneDir - = 2 * 180.0f ;
float neededTurn = currentRot - phoneDir ;
if ( Abs ( neededTurn ) < = 0.75f ) {
SetIdle ( ) ;
ClearLookFlag ( ) ;
m_phoneTalkTimer = CTimer : : GetTimeInMilliseconds ( ) + 10000 ;
return true ;
} else {
m_fRotationCur = DEGTORAD ( currentRot - neededTurn * 0.2f ) ;
return false ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
# endif
}
bool
CPed : : MakePhonecall ( void )
{
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
if ( ! IsPlayer ( ) & & CTimer : : GetTimeInMilliseconds ( ) > m_phoneTalkTimer - 7000 & & bRunningToPhone ) {
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
FindPlayerPed ( ) - > m_pWanted - > RegisterCrime_Immediately ( m_crimeToReportOnPhone , GetPosition ( ) ,
( m_crimeToReportOnPhone = = CRIME_POSSESSION_GUN ? ( uintptr ) m_threatEntity : ( uintptr ) m_victimOfPlayerCrime ) , false ) ;
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
if ( m_crimeToReportOnPhone ! = CRIME_POSSESSION_GUN )
FindPlayerPed ( ) - > m_pWanted - > SetWantedLevelNoDrop ( 1 ) ;
bRunningToPhone = false ;
}
# endif
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_phoneTalkTimer )
return false ;
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
CAnimBlendAssociation * talkAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_PHONE_TALK ) ;
if ( talkAssoc & & talkAssoc - > blendAmount > 0.5f ) {
CAnimBlendAssociation * endAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_PHONE_OUT , 8.0f ) ;
endAssoc - > flags & = ~ ASSOC_DELETEFADEDOUT ;
endAssoc - > SetFinishCallback ( ReportPhonePutDownCB , this ) ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
# endif
SetIdle ( ) ;
gPhoneInfo . m_aPhones [ m_phoneId ] . m_nState = PHONE_STATE_FREE ;
# ifndef PEDS_REPORT_CRIMES_ON_PHONE
m_phoneId = - 1 ;
# endif
// Because SetWanderPath is now done async in ReportPhonePutDownCB
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
return false ;
# else
return true ;
# endif
2019-10-13 00:05:08 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : Teleport ( CVector pos )
2019-10-13 00:05:08 -04:00
{
2020-11-19 14:12:20 -05:00
CWorld : : Remove ( this ) ;
SetPosition ( pos ) ;
bIsStanding = false ;
m_nPedStateTimer = 0 ;
m_actionX = 0.0f ;
m_actionY = 0.0f ;
m_pDamageEntity = nil ;
CWorld : : Add ( this ) ;
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetSeekCar ( CVehicle * car , uint32 doorNode )
{
if ( m_nPedState = = PED_SEEK_CAR )
2019-10-13 00:05:08 -04:00
return ;
2020-11-19 14:12:20 -05:00
# ifdef VC_PED_PORTS
if ( ! CanSetPedState ( ) | | m_nPedState = = PED_DRIVING )
return ;
# endif
SetStoredState ( ) ;
m_pSeekTarget = car ;
m_pSeekTarget - > RegisterReference ( ( CEntity * * ) & m_pSeekTarget ) ;
m_carInObjective = car ;
m_carInObjective - > RegisterReference ( ( CEntity * * ) & m_carInObjective ) ;
m_pMyVehicle = car ;
m_pMyVehicle - > RegisterReference ( ( CEntity * * ) & m_pMyVehicle ) ;
// m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
2021-01-13 07:01:11 -05:00
m_vehDoor = doorNode ;
2020-11-19 14:12:20 -05:00
m_distanceToCountSeekDone = 0.5f ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_SEEK_CAR ) ;
2020-11-19 14:12:20 -05:00
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : SeekCar ( void )
{
CVehicle * vehToSeek = m_carInObjective ;
CVector dest ( 0.0f , 0.0f , 0.0f ) ;
if ( ! vehToSeek ) {
RestorePreviousState ( ) ;
return ;
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective ! = OBJECTIVE_ENTER_CAR_AS_PASSENGER ) {
2021-01-13 07:01:11 -05:00
if ( m_vehDoor & & m_objective ! = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
2020-11-19 14:12:20 -05:00
if ( IsRoomToBeCarJacked ( ) ) {
2021-01-13 07:01:11 -05:00
dest = GetPositionToOpenCarDoor ( vehToSeek , m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
} else if ( m_nPedType = = PEDTYPE_COP ) {
dest = GetPositionToOpenCarDoor ( vehToSeek , CAR_DOOR_RF ) ;
} else {
SetMoveState ( PEDMOVE_STILL ) ;
}
} else
GetNearestDoor ( vehToSeek , dest ) ;
} else {
2021-01-13 07:41:24 -05:00
if ( m_carJackTimer > CTimer : : GetTimeInMilliseconds ( ) ) {
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_STILL ) ;
2019-10-13 00:05:08 -04:00
return ;
}
2020-11-19 14:12:20 -05:00
if ( vehToSeek - > GetModelIndex ( ) = = MI_COACH ) {
GetNearestDoor ( vehToSeek , dest ) ;
} else {
if ( vehToSeek - > IsTrain ( ) ) {
if ( vehToSeek - > GetStatus ( ) ! = STATUS_TRAIN_NOT_MOVING ) {
RestorePreviousObjective ( ) ;
RestorePreviousState ( ) ;
return ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ! GetNearestTrainDoor ( vehToSeek , dest ) ) {
RestorePreviousObjective ( ) ;
RestorePreviousState ( ) ;
return ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
if ( ! GetNearestPassengerDoor ( vehToSeek , dest ) ) {
if ( vehToSeek - > m_nNumPassengers = = vehToSeek - > m_nNumMaxPassengers ) {
RestorePreviousObjective ( ) ;
RestorePreviousState ( ) ;
} else {
SetMoveState ( PEDMOVE_STILL ) ;
}
bVehEnterDoorIsBlocked = true ;
return ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
bVehEnterDoorIsBlocked = false ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
}
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
if ( dest . x = = 0.0f & & dest . y = = 0.0f ) {
# ifdef FIX_BUGS
if ( ( ! IsPlayer ( ) & & CharCreatedBy ! = MISSION_CHAR ) | | vehToSeek - > VehicleCreatedBy ! = MISSION_VEHICLE | | vehToSeek - > pDriver | | ! vehToSeek - > CanPedOpenLocks ( this ) ) {
2020-04-23 04:24:03 -04:00
# else
2020-11-19 14:12:20 -05:00
if ( ( ! IsPlayer ( ) & & CharCreatedBy ! = MISSION_CHAR ) | | vehToSeek - > VehicleCreatedBy ! = MISSION_VEHICLE | | vehToSeek - > pDriver ) {
2020-04-23 04:24:03 -04:00
# endif
2020-11-19 14:12:20 -05:00
RestorePreviousState ( ) ;
if ( IsPlayer ( ) ) {
ClearObjective ( ) ;
} else if ( CharCreatedBy = = RANDOM_CHAR ) {
2021-01-13 07:41:24 -05:00
m_carJackTimer = CTimer : : GetTimeInMilliseconds ( ) + 30000 ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_STILL ) ;
TheCamera . ClearPlayerWeaponMode ( ) ;
CCarCtrl : : RemoveFromInterestingVehicleList ( vehToSeek ) ;
return ;
}
dest = vehToSeek - > GetPosition ( ) ;
if ( bCollidedWithMyVehicle ) {
WarpPedIntoCar ( m_pMyVehicle ) ;
return ;
2019-10-13 00:05:08 -04:00
}
}
2020-11-19 14:12:20 -05:00
bool foundBetterPosToSeek = PossiblyFindBetterPosToSeekCar ( & dest , vehToSeek ) ;
m_vecSeekPos = dest ;
float distToDestSqr = ( m_vecSeekPos - GetPosition ( ) ) . MagnitudeSqr ( ) ;
# ifndef VC_PED_PORTS
if ( bIsRunning )
SetMoveState ( PEDMOVE_RUN ) ;
2020-04-23 04:24:03 -04:00
# else
2020-11-19 14:12:20 -05:00
if ( bIsRunning | |
vehToSeek - > pDriver & & distToDestSqr > sq ( 2.0f ) & & ( Abs ( vehToSeek - > m_vecMoveSpeed . x ) > 0.01f | | Abs ( vehToSeek - > m_vecMoveSpeed . y ) > 0.01f ) )
SetMoveState ( PEDMOVE_RUN ) ;
2020-04-23 04:24:03 -04:00
# endif
2020-11-19 14:12:20 -05:00
else if ( distToDestSqr < sq ( 2.0f ) )
SetMoveState ( PEDMOVE_WALK ) ;
if ( distToDestSqr > = 1.0f )
bCanPedEnterSeekedCar = false ;
else if ( 2.0f * vehToSeek - > GetColModel ( ) - > boundingBox . max . x > distToDestSqr )
bCanPedEnterSeekedCar = true ;
2021-01-13 07:01:11 -05:00
if ( vehToSeek - > m_nGettingInFlags & GetCarDoorFlag ( m_vehDoor ) )
2020-11-19 14:12:20 -05:00
bVehEnterDoorIsBlocked = true ;
else
bVehEnterDoorIsBlocked = false ;
// Arrived to the car
if ( Seek ( ) ) {
if ( ! foundBetterPosToSeek ) {
if ( 1.5f + GetPosition ( ) . z > dest . z & & GetPosition ( ) . z - 0.5f < dest . z ) {
if ( vehToSeek - > IsTrain ( ) ) {
2021-01-13 07:01:11 -05:00
SetEnterTrain ( vehToSeek , m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
} else {
m_fRotationCur = m_fRotationDest ;
if ( ! bVehEnterDoorIsBlocked ) {
vehToSeek - > SetIsStatic ( false ) ;
if ( m_objective = = OBJECTIVE_SOLICIT_VEHICLE ) {
SetSolicit ( 1000 ) ;
} else if ( m_objective = = OBJECTIVE_BUY_ICE_CREAM ) {
SetBuyIceCream ( ) ;
} else if ( vehToSeek - > m_nNumGettingIn < vehToSeek - > m_nNumMaxPassengers + 1
& & vehToSeek - > CanPedEnterCar ( ) ) {
switch ( vehToSeek - > GetStatus ( ) ) {
case STATUS_PLAYER :
case STATUS_SIMPLE :
case STATUS_PHYSICS :
case STATUS_PLAYER_DISABLED :
if ( ! vehToSeek - > bIsBus & & ( ! m_leader | | m_leader ! = vehToSeek - > pDriver ) & &
2021-01-13 07:01:11 -05:00
( m_vehDoor = = CAR_DOOR_LF & & vehToSeek - > pDriver | | m_vehDoor = = CAR_DOOR_RF & & vehToSeek - > pPassengers [ 0 ] | | m_vehDoor = = CAR_DOOR_LR & & vehToSeek - > pPassengers [ 1 ] | | m_vehDoor = = CAR_DOOR_RR & & vehToSeek - > pPassengers [ 2 ] ) ) {
2020-11-19 14:12:20 -05:00
SetCarJack ( vehToSeek ) ;
2021-01-13 07:01:11 -05:00
if ( m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER & & m_vehDoor ! = CAR_DOOR_LF )
2020-11-19 14:12:20 -05:00
vehToSeek - > pDriver - > bFleeAfterExitingCar = true ;
} else {
2021-01-13 07:01:11 -05:00
SetEnterCar ( vehToSeek , m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
}
break ;
case STATUS_ABANDONED :
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_RF & & vehToSeek - > pPassengers [ 0 ] ) {
2020-11-19 14:12:20 -05:00
if ( vehToSeek - > pPassengers [ 0 ] - > bDontDragMeOutCar ) {
if ( IsPlayer ( ) )
2021-01-13 07:01:11 -05:00
SetEnterCar ( vehToSeek , m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
} else {
SetCarJack ( vehToSeek ) ;
}
} else {
2021-01-13 07:01:11 -05:00
SetEnterCar ( vehToSeek , m_vehDoor ) ;
2020-11-19 14:12:20 -05:00
}
break ;
case STATUS_WRECKED :
SetIdle ( ) ;
break ;
default :
return ;
}
} else {
RestorePreviousState ( ) ;
}
} else {
SetMoveState ( PEDMOVE_STILL ) ;
}
}
}
2019-10-13 00:05:08 -04:00
}
}
}
2020-11-19 14:12:20 -05:00
bool
CPed : : CheckForExplosions ( CVector2D & area )
2019-10-13 00:05:08 -04:00
{
2020-11-19 14:12:20 -05:00
int event = 0 ;
if ( CEventList : : FindClosestEvent ( EVENT_EXPLOSION , GetPosition ( ) , & event ) ) {
area . x = gaEvent [ event ] . posn . x ;
area . y = gaEvent [ event ] . posn . y ;
CEntity * actualEntity = nil ;
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
switch ( gaEvent [ event ] . entityType ) {
case EVENT_ENTITY_PED :
actualEntity = CPools : : GetPed ( gaEvent [ event ] . entityRef ) ;
break ;
case EVENT_ENTITY_VEHICLE :
actualEntity = CPools : : GetVehicle ( gaEvent [ event ] . entityRef ) ;
break ;
case EVENT_ENTITY_OBJECT :
actualEntity = CPools : : GetObject ( gaEvent [ event ] . entityRef ) ;
break ;
default :
break ;
2019-10-13 00:05:08 -04:00
}
2020-11-19 14:12:20 -05:00
if ( actualEntity ) {
m_pEventEntity = actualEntity ;
m_pEventEntity - > RegisterReference ( ( CEntity * * ) & m_pEventEntity ) ;
bGonnaInvestigateEvent = true ;
} else
bGonnaInvestigateEvent = false ;
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
CEventList : : ClearEvent ( event ) ;
return true ;
} else if ( CEventList : : FindClosestEvent ( EVENT_FIRE , GetPosition ( ) , & event ) ) {
area . x = gaEvent [ event ] . posn . x ;
area . y = gaEvent [ event ] . posn . y ;
CEventList : : ClearEvent ( event ) ;
bGonnaInvestigateEvent = false ;
return true ;
}
2019-10-13 00:05:08 -04:00
2020-11-19 14:12:20 -05:00
bGonnaInvestigateEvent = false ;
return false ;
}
CPed *
CPed : : CheckForGunShots ( void )
{
int event ;
if ( CEventList : : FindClosestEvent ( EVENT_GUNSHOT , GetPosition ( ) , & event ) ) {
if ( gaEvent [ event ] . entityType = = EVENT_ENTITY_PED ) {
// Probably due to we don't want peds to go gunshot area? (same on VC)
bGonnaInvestigateEvent = false ;
return CPools : : GetPed ( gaEvent [ event ] . entityRef ) ;
2019-10-13 00:05:08 -04:00
}
}
2020-11-19 14:12:20 -05:00
bGonnaInvestigateEvent = false ;
return nil ;
2019-10-12 10:03:32 -04:00
}
2020-11-19 14:12:20 -05:00
CPed *
CPed : : CheckForDeadPeds ( void )
2019-10-13 17:33:18 -04:00
{
2020-11-19 14:12:20 -05:00
int event ;
if ( CEventList : : FindClosestEvent ( EVENT_DEAD_PED , GetPosition ( ) , & event ) ) {
int pedHandle = gaEvent [ event ] . entityRef ;
if ( pedHandle & & gaEvent [ event ] . entityType = = EVENT_ENTITY_PED ) {
bGonnaInvestigateEvent = true ;
return CPools : : GetPed ( pedHandle ) ;
}
2019-10-13 17:33:18 -04:00
}
2020-11-19 14:12:20 -05:00
bGonnaInvestigateEvent = false ;
return nil ;
}
2019-10-13 17:33:18 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : IsPlayer ( void ) const
{
return m_nPedType = = PEDTYPE_PLAYER1 | | m_nPedType = = PEDTYPE_PLAYER2 | |
m_nPedType = = PEDTYPE_PLAYER3 | | m_nPedType = = PEDTYPE_PLAYER4 ;
}
2019-10-13 17:33:18 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : IsGangMember ( void ) const
{
return m_nPedType > = PEDTYPE_GANG1 & & m_nPedType < = PEDTYPE_GANG9 ;
2019-10-12 10:03:32 -04:00
}
2020-11-19 14:12:20 -05:00
bool
CPed : : IsPointerValid ( void )
2019-10-15 19:00:09 -04:00
{
2020-11-19 14:12:20 -05:00
int pedIndex = CPools : : GetPedPool ( ) - > GetIndex ( this ) > > 8 ;
if ( pedIndex < 0 | | pedIndex > = NUMPEDS )
return false ;
2019-10-15 19:00:09 -04:00
2020-11-19 14:12:20 -05:00
if ( m_entryInfoList . first | | FindPlayerPed ( ) = = this )
return true ;
return false ;
2019-10-15 19:00:09 -04:00
}
void
2020-11-19 14:12:20 -05:00
CPed : : SetPedPositionInCar ( void )
2019-10-15 19:00:09 -04:00
{
2020-11-19 14:12:20 -05:00
if ( CReplay : : IsPlayingBack ( ) )
2019-10-15 19:00:09 -04:00
return ;
2020-11-19 14:12:20 -05:00
if ( bChangedSeat ) {
bool notYet = false ;
if ( RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_GETIN_LHS )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_GETIN_LOW_LHS )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_CLOSEDOOR_LHS )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_CLOSEDOOR_LOW_LHS )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_SHUFFLE_RHS )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_LSHUFFLE_RHS )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_VAN_CLOSE_L )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_VAN_CLOSE )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_VAN_GETIN_L )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_VAN_GETIN )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_COACH_IN_L )
| | RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_COACH_IN_R ) ) {
notYet = true ;
}
if ( notYet ) {
LineUpPedWithCar ( LINE_UP_TO_CAR_START ) ;
bChangedSeat = false ;
return ;
2019-10-15 19:00:09 -04:00
}
}
2020-11-19 14:12:20 -05:00
CVehicleModelInfo * vehModel = ( CVehicleModelInfo * ) CModelInfo : : GetModelInfo ( m_pMyVehicle - > GetModelIndex ( ) ) ;
CMatrix newMat ( m_pMyVehicle - > GetMatrix ( ) ) ;
CVector seatPos ;
if ( m_pMyVehicle - > pDriver = = this ) {
seatPos = vehModel - > GetFrontSeatPosn ( ) ;
if ( ! m_pMyVehicle - > IsBoat ( ) & & m_pMyVehicle - > m_vehType ! = VEHICLE_TYPE_BIKE )
seatPos . x = - seatPos . x ;
2019-10-15 19:00:09 -04:00
2020-11-19 14:12:20 -05:00
} else if ( m_pMyVehicle - > pPassengers [ 0 ] = = this ) {
seatPos = vehModel - > GetFrontSeatPosn ( ) ;
} else if ( m_pMyVehicle - > pPassengers [ 1 ] = = this ) {
seatPos = vehModel - > m_positions [ CAR_POS_BACKSEAT ] ;
seatPos . x = - seatPos . x ;
} else {
if ( m_pMyVehicle - > pPassengers [ 2 ] = = this ) {
seatPos = vehModel - > m_positions [ CAR_POS_BACKSEAT ] ;
2019-10-15 19:00:09 -04:00
} else {
2020-11-19 14:12:20 -05:00
seatPos = vehModel - > GetFrontSeatPosn ( ) ;
2019-10-15 19:00:09 -04:00
}
2020-11-19 14:12:20 -05:00
}
newMat . GetPosition ( ) + = Multiply3x3 ( newMat , seatPos ) ;
// Already done below (SetTranslate(0.0f, 0.0f, 0.0f))
// tempMat.SetUnity();
2019-10-15 19:00:09 -04:00
2020-11-19 14:12:20 -05:00
// Rear seats on vans don't face to front, so rotate them HALFPI.
if ( m_pMyVehicle - > bIsVan ) {
CMatrix tempMat ;
if ( m_pMyVehicle - > pPassengers [ 1 ] = = this ) {
m_fRotationCur = m_pMyVehicle - > GetForward ( ) . Heading ( ) - HALFPI ;
tempMat . SetTranslate ( 0.0f , 0.0f , 0.0f ) ;
tempMat . RotateZ ( - HALFPI ) ;
newMat = newMat * tempMat ;
} else if ( m_pMyVehicle - > pPassengers [ 2 ] = = this ) {
m_fRotationCur = m_pMyVehicle - > GetForward ( ) . Heading ( ) + HALFPI ;
tempMat . SetTranslate ( 0.0f , 0.0f , 0.0f ) ;
tempMat . RotateZ ( HALFPI ) ;
newMat = newMat * tempMat ;
2019-10-15 19:00:09 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_fRotationCur = m_pMyVehicle - > GetForward ( ) . Heading ( ) ;
}
} else {
m_fRotationCur = m_pMyVehicle - > GetForward ( ) . Heading ( ) ;
}
GetMatrix ( ) = newMat ;
}
2019-10-15 19:00:09 -04:00
2020-11-19 14:12:20 -05:00
void
CPed : : LookForSexyPeds ( void )
{
if ( ( ! IsPedInControl ( ) & & m_nPedState ! = PED_DRIVING )
| | m_lookTimer > = CTimer : : GetTimeInMilliseconds ( ) | | m_nPedType ! = PEDTYPE_CIVMALE )
return ;
2019-10-15 19:00:09 -04:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < m_numNearPeds ; i + + ) {
if ( CanSeeEntity ( m_nearPeds [ i ] ) ) {
if ( ( GetPosition ( ) - m_nearPeds [ i ] - > GetPosition ( ) ) . Magnitude ( ) < 10.0f ) {
CPed * nearPed = m_nearPeds [ i ] ;
if ( ( nearPed - > m_pedStats - > m_sexiness > m_pedStats - > m_sexiness )
& & nearPed - > m_nPedType = = PEDTYPE_CIVFEMALE ) {
SetLookFlag ( nearPed , true ) ;
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 4000 ;
Say ( SOUND_PED_CHAT_SEXY ) ;
return ;
2019-10-15 19:00:09 -04:00
}
}
}
}
2020-11-19 14:12:20 -05:00
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 10000 ;
2019-10-15 19:00:09 -04:00
}
2019-10-24 19:25:11 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : LookForSexyCars ( void )
2019-10-24 19:25:11 -04:00
{
2020-11-19 14:12:20 -05:00
CEntity * vehicles [ 8 ] ;
CVehicle * veh ;
int foundVehId = 0 ;
int bestPriceYet = 0 ;
int16 lastVehicle ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
if ( ! IsPedInControl ( ) & & m_nPedState ! = PED_DRIVING )
2019-10-24 19:25:11 -04:00
return ;
2020-11-19 14:12:20 -05:00
if ( m_lookTimer < CTimer : : GetTimeInMilliseconds ( ) ) {
CWorld : : FindObjectsInRange ( GetPosition ( ) , 10.0f , true , & lastVehicle , 6 , vehicles , false , true , false , false , false ) ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
for ( int vehId = 0 ; vehId < lastVehicle ; vehId + + ) {
veh = ( CVehicle * ) vehicles [ vehId ] ;
if ( veh ! = m_pMyVehicle & & bestPriceYet < veh - > pHandling - > nMonetaryValue ) {
foundVehId = vehId ;
bestPriceYet = veh - > pHandling - > nMonetaryValue ;
}
}
if ( lastVehicle > 0 & & bestPriceYet > 40000 )
SetLookFlag ( vehicles [ foundVehId ] , false ) ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 10000 ;
}
}
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
bool
CPed : : LookForInterestingNodes ( void )
{
CBaseModelInfo * model ;
CPtrNode * ptrNode ;
CVector effectDist ;
C2dEffect * effect ;
CMatrix * objMat ;
2019-10-24 19:25:11 -04:00
2021-01-13 07:41:24 -05:00
if ( ( CTimer : : GetFrameCounter ( ) + ( m_randomSeed % 256 ) ) & 7 | | CTimer : : GetTimeInMilliseconds ( ) < = m_chatTimer ) {
2020-11-19 14:12:20 -05:00
return false ;
}
bool found = false ;
uint8 randVal = CGeneral : : GetRandomNumber ( ) % 256 ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
int minX = CWorld : : GetSectorIndexX ( GetPosition ( ) . x - CHECK_NEARBY_THINGS_MAX_DIST ) ;
if ( minX < 0 ) minX = 0 ;
int minY = CWorld : : GetSectorIndexY ( GetPosition ( ) . y - CHECK_NEARBY_THINGS_MAX_DIST ) ;
if ( minY < 0 ) minY = 0 ;
int maxX = CWorld : : GetSectorIndexX ( GetPosition ( ) . x + CHECK_NEARBY_THINGS_MAX_DIST ) ;
# ifdef FIX_BUGS
if ( maxX > = NUMSECTORS_X ) maxX = NUMSECTORS_X - 1 ;
# else
if ( maxX > = NUMSECTORS_X ) maxX = NUMSECTORS_X ;
# endif
2020-11-18 06:38:47 -05:00
2020-11-19 14:12:20 -05:00
int maxY = CWorld : : GetSectorIndexY ( GetPosition ( ) . y + CHECK_NEARBY_THINGS_MAX_DIST ) ;
# ifdef FIX_BUGS
if ( maxY > = NUMSECTORS_Y ) maxY = NUMSECTORS_Y - 1 ;
# else
if ( maxY > = NUMSECTORS_Y ) maxY = NUMSECTORS_Y ;
# endif
2020-11-18 06:38:47 -05:00
2020-11-19 14:12:20 -05:00
for ( int curY = minY ; curY < = maxY & & ! found ; curY + + ) {
for ( int curX = minX ; curX < = maxX & & ! found ; curX + + ) {
CSector * sector = CWorld : : GetSector ( curX , curY ) ;
for ( ptrNode = sector - > m_lists [ ENTITYLIST_VEHICLES ] . first ; ptrNode & & ! found ; ptrNode = ptrNode - > next ) {
CVehicle * veh = ( CVehicle * ) ptrNode - > item ;
model = veh - > GetModelInfo ( ) ;
if ( model - > GetNum2dEffects ( ) ! = 0 ) {
for ( int e = 0 ; e < model - > GetNum2dEffects ( ) ; e + + ) {
effect = model - > Get2dEffect ( e ) ;
if ( effect - > type = = EFFECT_ATTRACTOR & & effect - > attractor . probability > = randVal ) {
objMat = & veh - > GetMatrix ( ) ;
CVector effectPos = veh - > GetMatrix ( ) * effect - > pos ;
effectDist = effectPos - GetPosition ( ) ;
if ( effectDist . MagnitudeSqr ( ) < sq ( 8.0f ) ) {
found = true ;
break ;
}
}
}
2020-11-18 06:38:47 -05:00
}
}
2020-11-19 14:12:20 -05:00
for ( ptrNode = sector - > m_lists [ ENTITYLIST_OBJECTS ] . first ; ptrNode & & ! found ; ptrNode = ptrNode - > next ) {
CObject * obj = ( CObject * ) ptrNode - > item ;
model = CModelInfo : : GetModelInfo ( obj - > GetModelIndex ( ) ) ;
if ( model - > GetNum2dEffects ( ) ! = 0 ) {
for ( int e = 0 ; e < model - > GetNum2dEffects ( ) ; e + + ) {
effect = model - > Get2dEffect ( e ) ;
if ( effect - > type = = EFFECT_ATTRACTOR & & effect - > attractor . probability > = randVal ) {
objMat = & obj - > GetMatrix ( ) ;
CVector effectPos = obj - > GetMatrix ( ) * effect - > pos ;
effectDist = effectPos - GetPosition ( ) ;
if ( effectDist . MagnitudeSqr ( ) < sq ( 8.0f ) ) {
found = true ;
break ;
}
2019-10-24 19:25:11 -04:00
}
}
}
}
2020-11-19 14:12:20 -05:00
for ( ptrNode = sector - > m_lists [ ENTITYLIST_BUILDINGS ] . first ; ptrNode & & ! found ; ptrNode = ptrNode - > next ) {
CBuilding * building = ( CBuilding * ) ptrNode - > item ;
model = CModelInfo : : GetModelInfo ( building - > GetModelIndex ( ) ) ;
if ( model - > GetNum2dEffects ( ) ! = 0 ) {
for ( int e = 0 ; e < model - > GetNum2dEffects ( ) ; e + + ) {
effect = model - > Get2dEffect ( e ) ;
if ( effect - > type = = EFFECT_ATTRACTOR & & effect - > attractor . probability > = randVal ) {
objMat = & building - > GetMatrix ( ) ;
CVector effectPos = building - > GetMatrix ( ) * effect - > pos ;
effectDist = effectPos - GetPosition ( ) ;
if ( effectDist . MagnitudeSqr ( ) < sq ( 8.0f ) ) {
found = true ;
break ;
}
2019-10-24 19:25:11 -04:00
}
}
}
}
2020-11-19 14:12:20 -05:00
for ( ptrNode = sector - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] . first ; ptrNode & & ! found ; ptrNode = ptrNode - > next ) {
CBuilding * building = ( CBuilding * ) ptrNode - > item ;
model = CModelInfo : : GetModelInfo ( building - > GetModelIndex ( ) ) ;
if ( model - > GetNum2dEffects ( ) ! = 0 ) {
for ( int e = 0 ; e < model - > GetNum2dEffects ( ) ; e + + ) {
effect = model - > Get2dEffect ( e ) ;
if ( effect - > type = = EFFECT_ATTRACTOR & & effect - > attractor . probability > = randVal ) {
objMat = & building - > GetMatrix ( ) ;
CVector effectPos = building - > GetMatrix ( ) * effect - > pos ;
effectDist = effectPos - GetPosition ( ) ;
if ( effectDist . MagnitudeSqr ( ) < sq ( 8.0f ) ) {
found = true ;
break ;
}
}
2019-10-24 19:25:11 -04:00
}
}
}
}
}
2020-11-19 14:12:20 -05:00
if ( ! found )
return false ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
CVector effectFrontLocal = Multiply3x3 ( * objMat , effect - > attractor . dir ) ;
float angleToFace = CGeneral : : GetRadianAngleBetweenPoints ( effectFrontLocal . x , effectFrontLocal . y , 0.0f , 0.0f ) ;
randVal = CGeneral : : GetRandomNumber ( ) % 256 ;
if ( randVal < = m_randomSeed % 256 ) {
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 2000 ;
2020-11-19 14:12:20 -05:00
SetLookFlag ( angleToFace , true ) ;
SetLookTimer ( 1000 ) ;
return false ;
}
CVector2D effectPos = * objMat * effect - > pos ;
switch ( effect - > attractor . type ) {
case ATTRACTORTYPE_ICECREAM :
SetInvestigateEvent ( EVENT_ICECREAM , effectPos , 0.1f , 15000 , angleToFace ) ;
break ;
case ATTRACTORTYPE_STARE :
SetInvestigateEvent ( EVENT_SHOPSTALL , effectPos , 1.0f ,
CGeneral : : GetRandomNumberInRange ( 8000 , 10 * effect - > attractor . probability + 8500 ) ,
angleToFace ) ;
break ;
default :
return true ;
2019-10-24 19:25:11 -04:00
}
2020-11-19 14:12:20 -05:00
return true ;
2019-10-24 19:25:11 -04:00
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetWaitState ( eWaitState state , void * time )
2019-10-24 19:25:11 -04:00
{
2020-11-19 14:12:20 -05:00
AnimationId waitAnim = NUM_ANIMS ;
CAnimBlendAssociation * animAssoc ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
if ( ! IsPedInControl ( ) )
return ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
if ( state ! = m_nWaitState )
FinishedWaitCB ( nil , this ) ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
switch ( state ) {
case WAITSTATE_TRAFFIC_LIGHTS :
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 500 ;
SetMoveState ( PEDMOVE_STILL ) ;
break ;
case WAITSTATE_CROSS_ROAD :
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 1000 ;
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_HBHB , 4.0f ) ;
break ;
case WAITSTATE_CROSS_ROAD_LOOK :
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_ROAD_CROSS , 8.0f ) ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
if ( time )
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + * ( int * ) time ;
else
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + CGeneral : : GetRandomNumberInRange ( 2000 , 5000 ) ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
break ;
case WAITSTATE_LOOK_PED :
case WAITSTATE_LOOK_SHOP :
case WAITSTATE_LOOK_ACCIDENT :
case WAITSTATE_FACEOFF_GANG :
break ;
case WAITSTATE_DOUBLEBACK :
m_headingRate = 0.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 3500 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_HBHB , 4.0f ) ;
2019-10-24 19:25:11 -04:00
# ifdef FIX_BUGS
2020-11-19 14:12:20 -05:00
animAssoc - > SetFinishCallback ( RestoreHeadingRateCB , this ) ;
2019-10-24 19:25:11 -04:00
# endif
2020-11-19 14:12:20 -05:00
break ;
case WAITSTATE_HITWALL :
m_headingRate = 2.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_HIT_WALL , 16.0f ) ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
animAssoc - > flags | = ASSOC_FADEOUTWHENDONE ;
animAssoc - > SetDeleteCallback ( FinishedWaitCB , this ) ;
2019-10-24 19:25:11 -04:00
2020-11-19 14:12:20 -05:00
if ( m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER & & CharCreatedBy = = RANDOM_CHAR & & m_nPedState = = PED_SEEK_CAR ) {
ClearObjective ( ) ;
RestorePreviousState ( ) ;
2021-01-13 07:41:24 -05:00
m_carJackTimer = CTimer : : GetTimeInMilliseconds ( ) + 30000 ;
2019-10-24 19:25:11 -04:00
}
2020-11-19 14:12:20 -05:00
break ;
case WAITSTATE_TURN180 :
m_headingRate = 0.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_TURN_180 , 4.0f ) ;
animAssoc - > SetFinishCallback ( FinishedWaitCB , this ) ;
animAssoc - > SetDeleteCallback ( RestoreHeadingRateCB , this ) ;
break ;
case WAITSTATE_SURPRISE :
m_headingRate = 0.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 2000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_HIT_WALL , 4.0f ) ;
animAssoc - > SetFinishCallback ( FinishedWaitCB , this ) ;
break ;
case WAITSTATE_STUCK :
SetMoveState ( PEDMOVE_STILL ) ;
SetMoveAnim ( ) ;
m_headingRate = 0.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_TIRED , 4.0f ) ;
# ifdef FIX_BUGS
animAssoc - > SetFinishCallback ( RestoreHeadingRateCB , this ) ;
2019-10-24 19:25:11 -04:00
# endif
2020-11-19 14:12:20 -05:00
if ( m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER & & CharCreatedBy = = RANDOM_CHAR & & m_nPedState = = PED_SEEK_CAR ) {
ClearObjective ( ) ;
RestorePreviousState ( ) ;
2021-01-13 07:41:24 -05:00
m_carJackTimer = CTimer : : GetTimeInMilliseconds ( ) + 30000 ;
2020-11-19 14:12:20 -05:00
}
break ;
case WAITSTATE_LOOK_ABOUT :
SetMoveState ( PEDMOVE_STILL ) ;
SetMoveAnim ( ) ;
m_headingRate = 0.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_HBHB , 4.0f ) ;
2019-10-24 19:25:11 -04:00
# ifdef FIX_BUGS
2020-11-19 14:12:20 -05:00
animAssoc - > SetFinishCallback ( RestoreHeadingRateCB , this ) ;
2019-10-24 19:25:11 -04:00
# endif
2020-11-19 14:12:20 -05:00
break ;
case WAITSTATE_PLAYANIM_COWER :
waitAnim = ANIM_HANDSCOWER ;
case WAITSTATE_PLAYANIM_HANDSUP :
if ( waitAnim = = NUM_ANIMS )
waitAnim = ANIM_HANDSUP ;
case WAITSTATE_PLAYANIM_HANDSCOWER :
if ( waitAnim = = NUM_ANIMS )
waitAnim = ANIM_HANDSCOWER ;
m_headingRate = 0.0f ;
if ( time )
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + * ( int * ) time ;
else
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 3000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , waitAnim , 4.0f ) ;
animAssoc - > SetDeleteCallback ( FinishedWaitCB , this ) ;
break ;
case WAITSTATE_PLAYANIM_DUCK :
waitAnim = ANIM_DUCK_DOWN ;
case WAITSTATE_PLAYANIM_TAXI :
if ( waitAnim = = NUM_ANIMS )
waitAnim = ANIM_IDLE_TAXI ;
case WAITSTATE_PLAYANIM_CHAT :
if ( waitAnim = = NUM_ANIMS )
waitAnim = ANIM_IDLE_CHAT ;
if ( time )
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + * ( int * ) time ;
else
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 3000 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , waitAnim , 4.0f ) ;
animAssoc - > flags & = ~ ASSOC_FADEOUTWHENDONE ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
animAssoc - > SetDeleteCallback ( FinishedWaitCB , this ) ;
break ;
case WAITSTATE_FINISH_FLEE :
SetMoveState ( PEDMOVE_STILL ) ;
SetMoveAnim ( ) ;
m_headingRate = 0.0f ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 2500 ;
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_IDLE_TIRED , 4.0f ) ;
2019-10-24 19:25:11 -04:00
# ifdef FIX_BUGS
2020-11-19 14:12:20 -05:00
animAssoc - > SetFinishCallback ( RestoreHeadingRateCB , this ) ;
2019-10-24 19:25:11 -04:00
# endif
2020-11-19 14:12:20 -05:00
break ;
default :
m_nWaitState = WAITSTATE_FALSE ;
RestoreHeadingRate ( ) ;
return ;
2019-10-24 19:25:11 -04:00
}
2020-11-19 14:12:20 -05:00
m_nWaitState = state ;
2019-10-24 19:25:11 -04:00
}
2019-10-26 11:41:04 -04:00
void
2020-11-19 14:12:20 -05:00
CPed : : Wait ( void )
2019-10-26 11:41:04 -04:00
{
2020-11-19 14:12:20 -05:00
AnimationId mustHaveAnim = NUM_ANIMS ;
CAnimBlendAssociation * animAssoc ;
CPed * pedWeLook ;
if ( DyingOrDead ( ) ) {
m_nWaitState = WAITSTATE_FALSE ;
RestoreHeadingRate ( ) ;
2019-10-26 11:41:04 -04:00
return ;
}
2020-11-19 14:12:20 -05:00
switch ( m_nWaitState ) {
2019-10-26 11:41:04 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_TRAFFIC_LIGHTS :
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
if ( CTrafficLights : : LightForPeds ( ) = = PED_LIGHTS_WALK ) {
m_nWaitState = WAITSTATE_FALSE ;
SetMoveState ( PEDMOVE_WALK ) ;
}
2019-10-26 11:41:04 -04:00
}
2020-11-19 14:12:20 -05:00
break ;
2019-10-26 11:41:04 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_CROSS_ROAD :
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
if ( CGeneral : : GetRandomNumber ( ) & 1 | | ! m_nWaitTimer )
m_nWaitState = WAITSTATE_FALSE ;
else
SetWaitState ( WAITSTATE_CROSS_ROAD_LOOK , nil ) ;
2019-10-26 11:41:04 -04:00
2020-11-19 14:12:20 -05:00
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_HBHB ) ;
if ( animAssoc ) {
animAssoc - > blendDelta = - 8.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
}
break ;
case WAITSTATE_CROSS_ROAD_LOOK :
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
m_nWaitState = WAITSTATE_FALSE ;
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_ROAD_CROSS ) ;
if ( animAssoc ) {
animAssoc - > blendDelta = - 8.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-10-26 11:41:04 -04:00
}
}
2020-11-19 14:12:20 -05:00
break ;
2019-10-26 11:41:04 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_DOUBLEBACK :
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_nWaitTimer ) {
uint32 timeLeft = m_nWaitTimer - CTimer : : GetTimeInMilliseconds ( ) ;
if ( timeLeft < 2500 & & timeLeft > 2000 ) {
m_nWaitTimer - = 500 ;
CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_XPRESS_SCRATCH , 4.0f ) ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
m_nWaitState = WAITSTATE_FALSE ;
SetMoveState ( PEDMOVE_WALK ) ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
break ;
case WAITSTATE_HITWALL :
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_nWaitTimer ) {
if ( m_collidingThingTimer > CTimer : : GetTimeInMilliseconds ( ) ) {
m_collidingThingTimer = CTimer : : GetTimeInMilliseconds ( ) + 2500 ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
} else {
m_nWaitState = WAITSTATE_FALSE ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
break ;
case WAITSTATE_TURN180 :
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
m_nWaitState = WAITSTATE_FALSE ;
SetMoveState ( PEDMOVE_WALK ) ;
m_fRotationCur = m_fRotationCur + PI ;
if ( m_nPedState = = PED_INVESTIGATE )
ClearInvestigateEvent ( ) ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
if ( m_collidingThingTimer > CTimer : : GetTimeInMilliseconds ( ) ) {
m_collidingThingTimer = CTimer : : GetTimeInMilliseconds ( ) + 2500 ;
}
break ;
case WAITSTATE_SURPRISE :
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
if ( RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_HIT_WALL ) ) {
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_XPRESS_SCRATCH , 4.0f ) ;
animAssoc - > SetFinishCallback ( FinishedWaitCB , this ) ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + 5000 ;
2019-10-29 19:37:05 -04:00
} else {
2020-11-19 14:12:20 -05:00
m_nWaitState = WAITSTATE_FALSE ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
}
break ;
case WAITSTATE_STUCK :
if ( CTimer : : GetTimeInMilliseconds ( ) < = m_nWaitTimer )
break ;
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_TIRED ) ;
if ( ! animAssoc )
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_TURN_180 ) ;
if ( ! animAssoc )
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_XPRESS_SCRATCH ) ;
if ( ! animAssoc )
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_ROAD_CROSS ) ;
if ( animAssoc ) {
if ( animAssoc - > IsPartial ( ) ) {
animAssoc - > blendDelta = - 8.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-10-29 19:37:05 -04:00
} else {
2020-11-19 14:12:20 -05:00
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
CAnimManager : : BlendAnimation ( GetClump ( ) , m_animGroup , ANIM_IDLE_STANCE , 4.0f ) ;
}
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
if ( animAssoc - > animId = = ANIM_TURN_180 ) {
m_fRotationCur = CGeneral : : LimitRadianAngle ( PI + m_fRotationCur ) ;
m_nWaitState = WAITSTATE_FALSE ;
SetMoveState ( PEDMOVE_WALK ) ;
m_nStoredMoveState = PEDMOVE_NONE ;
m_panicCounter = 0 ;
return ;
2019-10-29 19:37:05 -04:00
}
}
2020-11-19 14:12:20 -05:00
AnimationId animToPlay ;
switch ( CGeneral : : GetRandomNumber ( ) & 3 ) {
case 0 :
animToPlay = ANIM_ROAD_CROSS ;
2019-10-29 19:37:05 -04:00
break ;
2020-11-19 14:12:20 -05:00
case 1 :
animToPlay = ANIM_IDLE_TIRED ;
2019-10-29 19:37:05 -04:00
break ;
2020-11-19 14:12:20 -05:00
case 2 :
animToPlay = ANIM_XPRESS_SCRATCH ;
break ;
case 3 :
animToPlay = ANIM_TURN_180 ;
2019-10-29 19:37:05 -04:00
break ;
default :
break ;
}
2020-11-19 14:12:20 -05:00
animAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , animToPlay , 4.0f ) ;
if ( animToPlay = = ANIM_TURN_180 )
animAssoc - > SetFinishCallback ( FinishedWaitCB , this ) ;
m_nWaitTimer = CTimer : : GetTimeInMilliseconds ( ) + CGeneral : : GetRandomNumberInRange ( 1500 , 5000 ) ;
break ;
case WAITSTATE_LOOK_ABOUT :
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
m_nWaitState = WAITSTATE_FALSE ;
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_HBHB ) ;
if ( animAssoc ) {
animAssoc - > blendDelta = - 8.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-10-29 19:37:05 -04:00
}
}
2020-11-19 14:12:20 -05:00
break ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_PLAYANIM_HANDSUP :
mustHaveAnim = ANIM_HANDSUP ;
case WAITSTATE_PLAYANIM_HANDSCOWER :
if ( mustHaveAnim = = NUM_ANIMS )
mustHaveAnim = ANIM_HANDSCOWER ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , mustHaveAnim ) ;
pedWeLook = ( CPed * ) m_pLookTarget ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
if ( ( ! m_pLookTarget | | ! m_pLookTarget - > IsPed ( ) | | pedWeLook - > m_pPointGunAt )
& & m_nPedState ! = PED_FLEE_ENTITY
& & m_nPedState ! = PED_ATTACK
& & CTimer : : GetTimeInMilliseconds ( ) < = m_nWaitTimer
& & animAssoc ) {
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
TurnBody ( ) ;
} else {
m_nWaitState = WAITSTATE_FALSE ;
m_nWaitTimer = 0 ;
if ( m_pLookTarget & & m_pLookTarget - > IsPed ( ) ) {
if ( m_nPedState ! = PED_FLEE_ENTITY & & m_nPedState ! = PED_ATTACK ) {
if ( m_pedStats - > m_fear < = 100 - pedWeLook - > m_pedStats - > m_temper ) {
if ( GetWeapon ( ) - > IsTypeMelee ( ) ) {
# ifdef VC_PED_PORTS
if ( m_pedStats - > m_flags & STAT_GUN_PANIC ) {
# endif
SetObjective ( OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE , m_pLookTarget ) ;
if ( m_nPedState = = PED_FLEE_ENTITY | | m_nPedState = = PED_FLEE_POS ) {
bUsePedNodeSeek = true ;
m_pNextPathNode = nil ;
}
if ( m_nMoveState ! = PEDMOVE_RUN )
SetMoveState ( PEDMOVE_WALK ) ;
if ( m_nPedType ! = PEDTYPE_COP ) {
ProcessObjective ( ) ;
SetMoveState ( PEDMOVE_WALK ) ;
}
# ifdef VC_PED_PORTS
} else {
SetObjective ( OBJECTIVE_NONE ) ;
SetWanderPath ( CGeneral : : GetRandomNumberInRange ( 0.0f , 8.0f ) ) ;
}
# endif
} else {
SetObjective ( OBJECTIVE_KILL_CHAR_ON_FOOT , m_pLookTarget ) ;
SetObjectiveTimer ( 20000 ) ;
}
} else {
SetObjective ( OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE , m_pLookTarget ) ;
if ( m_nPedState = = PED_FLEE_ENTITY | | m_nPedState = = PED_FLEE_POS )
{
bUsePedNodeSeek = true ;
m_pNextPathNode = nil ;
}
SetMoveState ( PEDMOVE_RUN ) ;
Say ( SOUND_PED_FLEE_RUN ) ;
}
}
}
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , mustHaveAnim ) ;
if ( animAssoc ) {
animAssoc - > blendDelta = - 4.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
}
}
break ;
case WAITSTATE_PLAYANIM_COWER :
mustHaveAnim = ANIM_HANDSCOWER ;
case WAITSTATE_PLAYANIM_DUCK :
if ( mustHaveAnim = = NUM_ANIMS )
mustHaveAnim = ANIM_DUCK_DOWN ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_PLAYANIM_TAXI :
if ( mustHaveAnim = = NUM_ANIMS )
mustHaveAnim = ANIM_IDLE_TAXI ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_PLAYANIM_CHAT :
if ( mustHaveAnim = = NUM_ANIMS )
mustHaveAnim = ANIM_IDLE_CHAT ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , mustHaveAnim ) ;
if ( animAssoc ) {
animAssoc - > blendDelta = - 4.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
m_nWaitState = WAITSTATE_FALSE ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
# ifdef VC_PED_PORTS
else if ( m_nWaitState = = WAITSTATE_PLAYANIM_TAXI ) {
if ( m_pedInObjective ) {
if ( m_objective = = OBJECTIVE_GOTO_CHAR_ON_FOOT | | m_objective = = OBJECTIVE_KILL_CHAR_ON_FOOT ) {
// VC also calls CleanUpOldReference here for old LookTarget.
m_pLookTarget = m_pedInObjective ;
2020-11-18 06:38:47 -05:00
m_pLookTarget - > RegisterReference ( ( CEntity * * ) & m_pLookTarget ) ;
TurnBody ( ) ;
2019-10-29 19:37:05 -04:00
}
}
}
# endif
2020-11-19 14:12:20 -05:00
break ;
2019-10-29 19:37:05 -04:00
2020-11-19 14:12:20 -05:00
case WAITSTATE_FINISH_FLEE :
animAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_IDLE_TIRED ) ;
if ( animAssoc ) {
if ( CTimer : : GetTimeInMilliseconds ( ) > m_nWaitTimer ) {
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
CAnimManager : : BlendAnimation ( GetClump ( ) , m_animGroup , ANIM_IDLE_STANCE , 4.0f ) ;
int timer = 2000 ;
m_nWaitState = WAITSTATE_FALSE ;
SetWaitState ( WAITSTATE_CROSS_ROAD_LOOK , & timer ) ;
}
} else {
m_nWaitState = WAITSTATE_FALSE ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
break ;
default :
break ;
2019-10-29 19:37:05 -04:00
}
2020-11-19 14:12:20 -05:00
if ( ! m_nWaitState )
RestoreHeadingRate ( ) ;
2019-10-29 19:37:05 -04:00
}
2019-11-04 18:04:26 -05:00
void
2020-11-19 14:12:20 -05:00
CPed : : FinishedWaitCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-11-04 18:04:26 -05:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
ped - > m_nWaitTimer = 0 ;
ped - > RestoreHeadingRate ( ) ;
ped - > Wait ( ) ;
}
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : RestoreHeadingRate ( void )
{
m_headingRate = m_pedStats - > m_headingChangeRate ;
}
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : RestoreHeadingRateCB ( CAnimBlendAssociation * assoc , void * arg )
{
( ( CPed * ) arg ) - > m_headingRate = ( ( CPed * ) arg ) - > m_pedStats - > m_headingChangeRate ;
}
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : FlagToDestroyWhenNextProcessed ( void )
{
bRemoveFromWorld = true ;
if ( ! InVehicle ( ) )
return ;
if ( m_pMyVehicle - > pDriver = = this ) {
m_pMyVehicle - > pDriver = nil ;
if ( IsPlayer ( ) & & m_pMyVehicle - > GetStatus ( ) ! = STATUS_WRECKED )
m_pMyVehicle - > SetStatus ( STATUS_ABANDONED ) ;
} else {
m_pMyVehicle - > RemovePassenger ( this ) ;
}
bInVehicle = false ;
m_pMyVehicle = nil ;
2020-12-14 22:11:02 -05:00
2020-11-19 14:12:20 -05:00
if ( CharCreatedBy = = MISSION_CHAR )
2020-12-14 22:11:02 -05:00
SetPedState ( PED_DEAD ) ;
2020-11-19 14:12:20 -05:00
else
2020-12-14 22:11:02 -05:00
SetPedState ( PED_NONE ) ;
2020-11-19 14:12:20 -05:00
m_pVehicleAnim = nil ;
}
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetSolicit ( uint32 time )
{
if ( m_nPedState = = PED_SOLICIT | | ! IsPedInControl ( ) | | ! m_carInObjective )
return ;
if ( CharCreatedBy ! = MISSION_CHAR & & m_carInObjective - > m_nNumGettingIn = = 0
& & CTimer : : GetTimeInMilliseconds ( ) < m_objectiveTimer ) {
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_LF ) {
2020-11-19 14:12:20 -05:00
m_fRotationDest = m_carInObjective - > GetForward ( ) . Heading ( ) - HALFPI ;
2019-11-04 18:04:26 -05:00
} else {
2020-11-19 14:12:20 -05:00
m_fRotationDest = m_carInObjective - > GetForward ( ) . Heading ( ) + HALFPI ;
2019-11-04 18:04:26 -05:00
}
2020-11-19 14:12:20 -05:00
if ( Abs ( m_fRotationDest - m_fRotationCur ) < HALFPI ) {
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + time ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
if ( ! m_carInObjective - > bIsVan & & ! m_carInObjective - > bIsBus )
m_pVehicleAnim = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_HOOKERTALK , 4.0f ) ;
2019-11-04 18:04:26 -05:00
2020-12-14 22:11:02 -05:00
SetPedState ( PED_SOLICIT ) ;
2019-11-04 18:04:26 -05:00
}
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : Solicit ( void )
2019-11-04 18:04:26 -05:00
{
2021-01-13 07:41:24 -05:00
if ( m_chatTimer > = CTimer : : GetTimeInMilliseconds ( ) & & m_carInObjective ) {
2021-01-13 07:01:11 -05:00
CVector doorPos = GetPositionToOpenCarDoor ( m_carInObjective , m_vehDoor , 0.0f ) ;
2020-11-19 14:12:20 -05:00
SetMoveState ( PEDMOVE_STILL ) ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
// Game uses GetAngleBetweenPoints and converts it to radian
m_fRotationDest = CGeneral : : GetRadianAngleBetweenPoints (
doorPos . x , doorPos . y ,
GetPosition ( ) . x , GetPosition ( ) . y ) ;
if ( m_fRotationDest < 0.0f ) {
m_fRotationDest = m_fRotationDest + TWOPI ;
} else if ( m_fRotationDest > TWOPI ) {
m_fRotationDest = m_fRotationDest - TWOPI ;
}
if ( ( GetPosition ( ) - doorPos ) . MagnitudeSqr ( ) < = 1.0f )
return ;
CAnimBlendAssociation * talkAssoc = RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_CAR_HOOKERTALK ) ;
if ( talkAssoc ) {
talkAssoc - > blendDelta = - 1000.0f ;
talkAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-11-04 18:04:26 -05:00
}
2020-11-19 14:12:20 -05:00
RestorePreviousState ( ) ;
RestorePreviousObjective ( ) ;
SetObjectiveTimer ( 10000 ) ;
} else if ( ! m_carInObjective ) {
RestorePreviousState ( ) ;
RestorePreviousObjective ( ) ;
SetObjectiveTimer ( 10000 ) ;
} else if ( CWorld : : Players [ CWorld : : PlayerInFocus ] . m_nMoney < = 100 ) {
m_carInObjective = nil ;
2019-11-04 18:04:26 -05:00
} else {
2020-11-19 14:12:20 -05:00
m_pVehicleAnim = nil ;
SetLeader ( m_carInObjective - > pDriver ) ;
2019-11-04 18:04:26 -05:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetBuyIceCream ( void )
2019-11-04 18:04:26 -05:00
{
2020-11-19 14:12:20 -05:00
if ( m_nPedState = = PED_BUY_ICECREAM | | ! IsPedInControl ( ) )
return ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
if ( ! m_carInObjective )
return ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
# ifdef FIX_ICECREAM
2020-04-23 16:25:18 -04:00
2020-11-19 14:12:20 -05:00
// Simulating BuyIceCream
CPed * driver = m_carInObjective - > pDriver ;
if ( driver ) {
2020-12-14 22:11:02 -05:00
SetPedState ( PED_BUY_ICECREAM ) ;
2020-11-19 14:12:20 -05:00
bFindNewNodeAfterStateRestore = true ;
SetObjectiveTimer ( 8000 ) ;
SetChat ( driver , 8000 ) ;
driver - > SetChat ( this , 8000 ) ;
return ;
2019-11-04 18:04:26 -05:00
}
2020-11-19 14:12:20 -05:00
# endif
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
// Side of the Ice Cream van
m_fRotationDest = m_carInObjective - > GetForward ( ) . Heading ( ) - HALFPI ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
if ( Abs ( m_fRotationDest - m_fRotationCur ) < HALFPI ) {
2021-01-13 07:41:24 -05:00
m_chatTimer = CTimer : : GetTimeInMilliseconds ( ) + 3000 ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_BUY_ICECREAM ) ;
2019-11-04 18:04:26 -05:00
}
}
2020-11-19 14:12:20 -05:00
bool
CPed : : PossiblyFindBetterPosToSeekCar ( CVector * pos , CVehicle * veh )
2019-11-04 18:04:26 -05:00
{
2020-11-19 14:12:20 -05:00
bool foundIt = false ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
CVector helperPos = GetPosition ( ) ;
helperPos . z = pos - > z - 0.5f ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
CVector foundPos = * pos ;
foundPos . z - = 0.5f ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
// If there is another car between target car and us.
if ( CWorld : : TestSphereAgainstWorld ( ( foundPos + helperPos ) / 2.0f , 0.25f , veh , false , true , false , false , false , false ) ) {
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
CColModel * vehCol = veh - > GetModelInfo ( ) - > GetColModel ( ) ;
CVector * colMin = & vehCol - > boundingBox . min ;
CVector * colMax = & vehCol - > boundingBox . max ;
2020-02-29 20:43:30 -05:00
2020-11-19 14:12:20 -05:00
CVector leftRearPos = CVector ( colMin - > x - 0.5f , colMin - > y - 0.5f , 0.0f ) ;
CVector rightRearPos = CVector ( 0.5f + colMax - > x , colMin - > y - 0.5f , 0.0f ) ;
CVector leftFrontPos = CVector ( colMin - > x - 0.5f , 0.5f + colMax - > y , 0.0f ) ;
CVector rightFrontPos = CVector ( 0.5f + colMax - > x , 0.5f + colMax - > y , 0.0f ) ;
2020-02-29 20:43:30 -05:00
2020-11-19 14:12:20 -05:00
leftRearPos = veh - > GetMatrix ( ) * leftRearPos ;
rightRearPos = veh - > GetMatrix ( ) * rightRearPos ;
leftFrontPos = veh - > GetMatrix ( ) * leftFrontPos ;
rightFrontPos = veh - > GetMatrix ( ) * rightFrontPos ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
// Makes helperPos veh-ped distance vector.
helperPos - = veh - > GetPosition ( ) ;
// ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour.
// On every run it returns another pos. for ped, with same distance to the veh.
// Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't)
helperPos = veh - > GetMatrix ( ) * helperPos ;
float vehForwardHeading = veh - > GetForward ( ) . Heading ( ) ;
// I'm absolutely not sure about these namings.
// NTVF = needed turn if we're looking to vehicle front and wanna look to...
float potentialLrHeading = Atan2 ( leftRearPos . x - helperPos . x , leftRearPos . y - helperPos . y ) ;
float NTVF_LR = CGeneral : : LimitRadianAngle ( potentialLrHeading - vehForwardHeading ) ;
float potentialRrHeading = Atan2 ( rightRearPos . x - helperPos . x , rightRearPos . y - helperPos . y ) ;
float NTVF_RR = CGeneral : : LimitRadianAngle ( potentialRrHeading - vehForwardHeading ) ;
float potentialLfHeading = Atan2 ( leftFrontPos . x - helperPos . x , leftFrontPos . y - helperPos . y ) ;
float NTVF_LF = CGeneral : : LimitRadianAngle ( potentialLfHeading - vehForwardHeading ) ;
float potentialRfHeading = Atan2 ( rightFrontPos . x - helperPos . x , rightFrontPos . y - helperPos . y ) ;
float NTVF_RF = CGeneral : : LimitRadianAngle ( potentialRfHeading - vehForwardHeading ) ;
bool canHeadToLr = NTVF_LR < = - PI | | NTVF_LR > = - HALFPI ;
bool canHeadToRr = NTVF_RR < = HALFPI | | NTVF_RR > = PI ;
bool canHeadToLf = NTVF_LF > = 0.0f | | NTVF_LF < = - HALFPI ;
bool canHeadToRf = NTVF_RF < = 0.0f | | NTVF_RF > = HALFPI ;
// Only order of conditions are different among enterTypes.
2021-01-13 07:01:11 -05:00
if ( m_vehDoor = = CAR_DOOR_RR ) {
2020-11-19 14:12:20 -05:00
if ( canHeadToRr ) {
foundPos = rightRearPos ;
foundIt = true ;
} else if ( canHeadToRf ) {
foundPos = rightFrontPos ;
foundIt = true ;
} else if ( canHeadToLr ) {
foundPos = leftRearPos ;
foundIt = true ;
} else if ( canHeadToLf ) {
foundPos = leftFrontPos ;
foundIt = true ;
}
2021-01-13 07:01:11 -05:00
} else if ( m_vehDoor = = CAR_DOOR_RF ) {
2020-11-19 14:12:20 -05:00
if ( canHeadToRf ) {
foundPos = rightFrontPos ;
foundIt = true ;
} else if ( canHeadToRr ) {
foundPos = rightRearPos ;
foundIt = true ;
} else if ( canHeadToLf ) {
foundPos = leftFrontPos ;
foundIt = true ;
} else if ( canHeadToLr ) {
foundPos = leftRearPos ;
foundIt = true ;
}
2021-01-13 07:01:11 -05:00
} else if ( m_vehDoor = = CAR_DOOR_LF ) {
2020-11-19 14:12:20 -05:00
if ( canHeadToLf ) {
foundPos = leftFrontPos ;
foundIt = true ;
} else if ( canHeadToLr ) {
foundPos = leftRearPos ;
foundIt = true ;
} else if ( canHeadToRf ) {
foundPos = rightFrontPos ;
foundIt = true ;
} else if ( canHeadToRr ) {
foundPos = rightRearPos ;
foundIt = true ;
}
2021-01-13 07:01:11 -05:00
} else if ( m_vehDoor = = CAR_DOOR_LR ) {
2020-11-19 14:12:20 -05:00
if ( canHeadToLr ) {
foundPos = leftRearPos ;
foundIt = true ;
} else if ( canHeadToLf ) {
foundPos = leftFrontPos ;
foundIt = true ;
} else if ( canHeadToRr ) {
foundPos = rightRearPos ;
foundIt = true ;
} else if ( canHeadToRf ) {
foundPos = rightFrontPos ;
foundIt = true ;
}
}
2019-11-04 18:04:26 -05:00
}
2020-11-19 14:12:20 -05:00
if ( ! foundIt )
return false ;
2020-02-29 20:43:30 -05:00
2020-11-19 14:12:20 -05:00
helperPos = GetPosition ( ) - foundPos ;
helperPos . z = 0.0f ;
if ( helperPos . MagnitudeSqr ( ) < = sq ( 0.5f ) )
return false ;
2019-11-04 18:04:26 -05:00
2020-11-19 14:12:20 -05:00
pos - > x = foundPos . x ;
pos - > y = foundPos . y ;
return true ;
2019-11-04 18:04:26 -05:00
}
2019-11-09 10:17:54 -05:00
void
2020-11-19 14:12:20 -05:00
CPed : : SetLeader ( CEntity * leader )
2019-11-09 10:17:54 -05:00
{
2020-11-19 14:12:20 -05:00
m_leader = ( CPed * ) leader ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
if ( m_leader )
m_leader - > RegisterReference ( ( CEntity * * ) & m_leader ) ;
}
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
# ifdef VC_PED_PORTS
bool
CPed : : CanPedJumpThis ( CEntity * unused , CVector * damageNormal )
{
if ( m_nSurfaceTouched = = SURFACE_WATER )
return true ;
CVector pos = GetPosition ( ) ;
CVector forwardOffset = GetForward ( ) ;
if ( damageNormal & & damageNormal - > z > 0.17f ) {
if ( damageNormal - > z > 0.9f )
return false ;
CColModel * ourCol = CModelInfo : : GetModelInfo ( m_modelIndex ) - > GetColModel ( ) ;
pos . z = ourCol - > spheres - > center . z - ourCol - > spheres - > radius * damageNormal - > z + pos . z ;
pos . z = pos . z + 0.05f ;
float collPower = damageNormal - > Magnitude2D ( ) ;
if ( damageNormal - > z > 0.5f ) {
CVector invDamageNormal ( - damageNormal - > x , - damageNormal - > y , 0.0f ) ;
invDamageNormal * = 1.0f / collPower ;
CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol - > spheres - > radius ;
forwardOffset = estimatedJumpDist * Min ( 2.0f / collPower , 4.0f ) ;
} else {
forwardOffset + = collPower * ourCol - > spheres - > radius * forwardOffset ;
2019-11-09 10:17:54 -05:00
}
2020-11-19 14:12:20 -05:00
} else {
pos . z - = 0.15f ;
2019-11-09 10:17:54 -05:00
}
2020-11-19 14:12:20 -05:00
CVector forwardPos = pos + forwardOffset ;
return CWorld : : GetIsLineOfSightClear ( pos , forwardPos , true , false , false , true , false , false , false ) ;
}
# else
bool
CPed : : CanPedJumpThis ( CEntity * unused )
{
CVector2D forward ( - Sin ( m_fRotationCur ) , Cos ( m_fRotationCur ) ) ;
CVector pos = GetPosition ( ) ;
CVector forwardPos (
forward . x + pos . x ,
forward . y + pos . y ,
pos . z ) ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
return CWorld : : GetIsLineOfSightClear ( pos , forwardPos , true , false , false , true , false , false , false ) ;
}
# endif
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : SetJump ( void )
{
if ( ! bInVehicle & &
# if defined VC_PED_PORTS || defined FIX_BUGS
m_nPedState ! = PED_JUMP & & ! RpAnimBlendClumpGetAssociation ( GetClump ( ) , ANIM_JUMP_LAUNCH ) & &
# endif
( m_nSurfaceTouched ! = SURFACE_STEEP_CLIFF | | DotProduct ( GetForward ( ) , m_vecDamageNormal ) > = 0.0f ) ) {
SetStoredState ( ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_JUMP ) ;
2020-11-19 14:12:20 -05:00
CAnimBlendAssociation * jumpAssoc = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_JUMP_LAUNCH , 8.0f ) ;
jumpAssoc - > SetFinishCallback ( FinishLaunchCB , this ) ;
m_fRotationDest = m_fRotationCur ;
2019-11-09 10:17:54 -05:00
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : FinishLaunchCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-11-09 10:17:54 -05:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedState ! = PED_JUMP )
2019-11-09 10:17:54 -05:00
return ;
2020-11-19 14:12:20 -05:00
CVector forward ( 0.15f * ped - > GetForward ( ) + ped - > GetPosition ( ) ) ;
forward . z + = CModelInfo : : GetModelInfo ( ped - > GetModelIndex ( ) ) - > GetColModel ( ) - > spheres - > center . z + 0.25f ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
CEntity * obstacle = CWorld : : TestSphereAgainstWorld ( forward , 0.25f , nil , true , true , false , true , false , false ) ;
if ( ! obstacle ) {
// Forward of forward
forward + = 0.15f * ped - > GetForward ( ) ;
forward . z + = 0.15f ;
obstacle = CWorld : : TestSphereAgainstWorld ( forward , 0.25f , nil , true , true , false , true , false , false ) ;
2019-11-09 10:17:54 -05:00
}
2020-11-19 14:12:20 -05:00
if ( obstacle ) {
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
// ANIM_HIT_WALL in VC (which makes more sense)
CAnimBlendAssociation * handsCoverAssoc = CAnimManager : : BlendAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_HANDSCOWER , 8.0f ) ;
handsCoverAssoc - > flags & = ~ ASSOC_FADEOUTWHENDONE ;
handsCoverAssoc - > SetFinishCallback ( FinishHitHeadCB , ped ) ;
ped - > bIsLanding = true ;
return ;
}
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
float velocityFromAnim = 0.1f ;
CAnimBlendAssociation * sprintAssoc = RpAnimBlendClumpGetAssociation ( ped - > GetClump ( ) , ANIM_SPRINT ) ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
if ( sprintAssoc ) {
velocityFromAnim = 0.05f * sprintAssoc - > blendAmount + 0.17f ;
} else {
CAnimBlendAssociation * runAssoc = RpAnimBlendClumpGetAssociation ( ped - > GetClump ( ) , ANIM_RUN ) ;
if ( runAssoc ) {
velocityFromAnim = 0.07f * runAssoc - > blendAmount + 0.1f ;
2019-11-09 10:17:54 -05:00
}
}
2020-11-19 14:12:20 -05:00
if ( ped - > IsPlayer ( )
# ifdef VC_PED_PORTS
| | ped - > m_pedInObjective & & ped - > m_pedInObjective - > IsPlayer ( )
# endif
)
ped - > ApplyMoveForce ( 0.0f , 0.0f , 8.5f ) ;
else
ped - > ApplyMoveForce ( 0.0f , 0.0f , 4.5f ) ;
if ( sq ( velocityFromAnim ) > ped - > m_vecMoveSpeed . MagnitudeSqr2D ( )
# ifdef VC_PED_PORTS
| | ped - > m_pCurrentPhysSurface
# endif
) {
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
# ifdef FREE_CAM
if ( TheCamera . Cams [ 0 ] . Using3rdPersonMouseCam ( ) & & ! CCamera : : bFreeCam ) {
# else
if ( TheCamera . Cams [ 0 ] . Using3rdPersonMouseCam ( ) ) {
# endif
float fpsAngle = ped - > WorkOutHeadingForMovingFirstPerson ( ped - > m_fRotationCur ) ;
ped - > m_vecMoveSpeed . x = - velocityFromAnim * Sin ( fpsAngle ) ;
ped - > m_vecMoveSpeed . y = velocityFromAnim * Cos ( fpsAngle ) ;
} else {
ped - > m_vecMoveSpeed . x = - velocityFromAnim * Sin ( ped - > m_fRotationCur ) ;
ped - > m_vecMoveSpeed . y = velocityFromAnim * Cos ( ped - > m_fRotationCur ) ;
}
# ifdef VC_PED_PORTS
if ( ped - > m_pCurrentPhysSurface ) {
ped - > m_vecMoveSpeed . x + = ped - > m_pCurrentPhysSurface - > m_vecMoveSpeed . x ;
ped - > m_vecMoveSpeed . y + = ped - > m_pCurrentPhysSurface - > m_vecMoveSpeed . y ;
}
# endif
2019-11-09 10:17:54 -05:00
}
2020-11-19 14:12:20 -05:00
ped - > bIsStanding = false ;
ped - > bIsInTheAir = true ;
animAssoc - > blendDelta = - 1000.0f ;
CAnimManager : : AddAnimation ( ped - > GetClump ( ) , ASSOCGRP_STD , ANIM_JUMP_GLIDE ) ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
if ( ped - > bDoBloodyFootprints ) {
CVector bloodPos ( 0.0f , 0.0f , 0.0f ) ;
ped - > TransformToNode ( bloodPos , PED_FOOTL ) ;
2019-11-09 10:17:54 -05:00
2020-11-19 14:12:20 -05:00
bloodPos . z - = 0.1f ;
bloodPos + = 0.2f * ped - > GetForward ( ) ;
2020-02-29 20:43:30 -05:00
2020-11-19 14:12:20 -05:00
CShadows : : AddPermanentShadow ( SHADOWTYPE_DARK , gpBloodPoolTex , & bloodPos ,
0.26f * ped - > GetForward ( ) . x ,
0.26f * ped - > GetForward ( ) . y ,
0.14f * ped - > GetRight ( ) . x ,
0.14f * ped - > GetRight ( ) . y ,
255 , 255 , 0 , 0 , 4.0f , 3000 , 1.0f ) ;
2020-03-01 19:03:39 -05:00
2020-11-19 14:12:20 -05:00
bloodPos = CVector ( 0.0f , 0.0f , 0.0f ) ;
ped - > TransformToNode ( bloodPos , PED_FOOTR ) ;
2020-03-01 19:03:39 -05:00
2020-11-19 14:12:20 -05:00
bloodPos . z - = 0.1f ;
bloodPos + = 0.2f * ped - > GetForward ( ) ;
CShadows : : AddPermanentShadow ( SHADOWTYPE_DARK , gpBloodPoolTex , & bloodPos ,
0.26f * ped - > GetForward ( ) . x ,
0.26f * ped - > GetForward ( ) . y ,
0.14f * ped - > GetRight ( ) . x ,
0.14f * ped - > GetRight ( ) . y ,
255 , 255 , 0 , 0 , 4.0f , 3000 , 1.0f ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
if ( ped - > m_bloodyFootprintCountOrDeathTime < = 40 ) {
ped - > m_bloodyFootprintCountOrDeathTime = 0 ;
ped - > bDoBloodyFootprints = false ;
2019-11-09 10:17:54 -05:00
} else {
2020-11-19 14:12:20 -05:00
ped - > m_bloodyFootprintCountOrDeathTime - = 40 ;
2019-11-09 10:17:54 -05:00
}
}
}
2019-11-19 17:15:45 -05:00
void
2020-11-19 14:12:20 -05:00
CPed : : FinishJumpCB ( CAnimBlendAssociation * animAssoc , void * arg )
2019-11-19 17:15:45 -05:00
{
2020-11-19 14:12:20 -05:00
CPed * ped = ( CPed * ) arg ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
ped - > bResetWalkAnims = true ;
ped - > bIsLanding = false ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
animAssoc - > blendDelta = - 1000.0f ;
}
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
void
CPed : : FinishHitHeadCB ( CAnimBlendAssociation * animAssoc , void * arg )
{
CPed * ped = ( CPed * ) arg ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
if ( animAssoc ) {
animAssoc - > blendDelta = - 4.0f ;
animAssoc - > flags | = ASSOC_DELETEFADEDOUT ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
if ( ped - > m_nPedState = = PED_JUMP )
ped - > RestorePreviousState ( ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
ped - > bIsLanding = false ;
}
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
bool
CPed : : CanPedDriveOff ( void )
{
if ( m_nPedState ! = PED_DRIVING | | m_lookTimer > CTimer : : GetTimeInMilliseconds ( ) )
return false ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
for ( int i = 0 ; i < m_numNearPeds ; i + + ) {
CPed * nearPed = m_nearPeds [ i ] ;
if ( nearPed - > m_nPedType = = m_nPedType & & nearPed - > m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER & & nearPed - > m_carInObjective = = m_carInObjective ) {
m_lookTimer = CTimer : : GetTimeInMilliseconds ( ) + 1000 ;
return false ;
2019-11-19 17:15:45 -05:00
}
}
2020-11-19 14:12:20 -05:00
return true ;
}
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
// These categories are purely random, most of ped models have no correlation. So I don't think making an enum.
uint8
CPed : : GetPedRadioCategory ( uint32 modelIndex )
{
switch ( modelIndex ) {
case MI_MALE01 :
case MI_FEMALE03 :
case MI_PROSTITUTE2 :
case MI_WORKER1 :
case MI_MOD_MAN :
case MI_MOD_WOM :
case MI_ST_WOM :
case MI_FAN_WOM :
return 3 ;
case MI_TAXI_D :
case MI_PIMP :
case MI_MALE02 :
case MI_FEMALE02 :
case MI_FATFEMALE01 :
case MI_FATFEMALE02 :
case MI_DOCKER1 :
case MI_WORKER2 :
case MI_FAN_MAN2 :
return 9 ;
case MI_GANG01 :
case MI_GANG02 :
case MI_SCUM_MAN :
case MI_SCUM_WOM :
case MI_HOS_WOM :
case MI_CONST1 :
return 1 ;
case MI_GANG03 :
case MI_GANG04 :
case MI_GANG07 :
case MI_GANG08 :
case MI_CT_MAN2 :
case MI_CT_WOM2 :
case MI_B_MAN3 :
case MI_SHOPPER3 :
return 4 ;
case MI_GANG05 :
case MI_GANG06 :
case MI_GANG11 :
case MI_GANG12 :
case MI_CRIMINAL02 :
case MI_B_WOM2 :
case MI_ST_MAN :
case MI_HOS_MAN :
return 5 ;
case MI_FATMALE01 :
case MI_LI_MAN2 :
case MI_SHOPPER1 :
case MI_CAS_MAN :
return 6 ;
case MI_PROSTITUTE :
case MI_P_WOM2 :
case MI_LI_WOM2 :
case MI_B_WOM3 :
case MI_CAS_WOM :
return 2 ;
case MI_P_WOM1 :
case MI_DOCKER2 :
case MI_STUD_MAN :
return 7 ;
case MI_CT_MAN1 :
case MI_CT_WOM1 :
case MI_LI_MAN1 :
case MI_LI_WOM1 :
case MI_B_MAN1 :
case MI_B_MAN2 :
case MI_B_WOM1 :
case MI_SHOPPER2 :
case MI_STUD_WOM :
return 8 ;
default :
return 0 ;
2019-11-19 17:15:45 -05:00
}
}
2020-11-19 14:12:20 -05:00
void
CPed : : SetRadioStation ( void )
2019-11-19 17:15:45 -05:00
{
2020-11-19 14:12:20 -05:00
static const uint8 radiosPerRadioCategories [ 10 ] [ 4 ] = {
{ JAH_RADIO , RISE_FM , GAME_FM , MSX_FM } ,
{ HEAD_RADIO , DOUBLE_CLEF , LIPS_106 , FLASHBACK } ,
{ RISE_FM , GAME_FM , MSX_FM , FLASHBACK } ,
{ HEAD_RADIO , RISE_FM , LIPS_106 , MSX_FM } ,
{ HEAD_RADIO , RISE_FM , MSX_FM , FLASHBACK } ,
{ JAH_RADIO , RISE_FM , LIPS_106 , FLASHBACK } ,
{ HEAD_RADIO , RISE_FM , LIPS_106 , FLASHBACK } ,
{ HEAD_RADIO , JAH_RADIO , LIPS_106 , FLASHBACK } ,
{ HEAD_RADIO , DOUBLE_CLEF , LIPS_106 , FLASHBACK } ,
{ CHATTERBOX , HEAD_RADIO , LIPS_106 , GAME_FM }
} ;
uint8 orderInCat = 0 ; // BUG: this wasn't initialized
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) | | ! m_pMyVehicle | | m_pMyVehicle - > pDriver ! = this )
return ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
uint8 category = GetPedRadioCategory ( GetModelIndex ( ) ) ;
if ( DMAudio . IsMP3RadioChannelAvailable ( ) ) {
if ( CGeneral : : GetRandomNumber ( ) & 15 ) {
for ( orderInCat = 0 ; orderInCat < 4 ; orderInCat + + ) {
if ( m_pMyVehicle - > m_nRadioStation = = radiosPerRadioCategories [ category ] [ orderInCat ] )
break ;
}
} else {
m_pMyVehicle - > m_nRadioStation = USERTRACK ;
}
} else {
for ( orderInCat = 0 ; orderInCat < 4 ; orderInCat + + ) {
if ( m_pMyVehicle - > m_nRadioStation = = radiosPerRadioCategories [ category ] [ orderInCat ] )
break ;
2019-11-19 17:15:45 -05:00
}
}
2020-11-19 14:12:20 -05:00
if ( orderInCat = = 4 ) {
if ( DMAudio . IsMP3RadioChannelAvailable ( ) ) {
if ( CGeneral : : GetRandomNumber ( ) & 15 )
m_pMyVehicle - > m_nRadioStation = radiosPerRadioCategories [ category ] [ CGeneral : : GetRandomNumber ( ) & 3 ] ;
else
m_pMyVehicle - > m_nRadioStation = USERTRACK ;
} else {
m_pMyVehicle - > m_nRadioStation = radiosPerRadioCategories [ category ] [ CGeneral : : GetRandomNumber ( ) & 3 ] ;
2019-11-19 17:15:45 -05:00
}
}
}
void
2020-11-19 14:12:20 -05:00
CPed : : WarpPedIntoCar ( CVehicle * car )
2019-11-19 17:15:45 -05:00
{
2020-11-19 14:12:20 -05:00
bInVehicle = true ;
m_pMyVehicle = car ;
m_pMyVehicle - > RegisterReference ( ( CEntity * * ) & m_pMyVehicle ) ;
m_carInObjective = car ;
m_carInObjective - > RegisterReference ( ( CEntity * * ) & m_carInObjective ) ;
2020-12-14 22:11:02 -05:00
SetPedState ( PED_DRIVING ) ;
2019-11-19 17:15:45 -05:00
bUsesCollision = false ;
2020-11-19 14:12:20 -05:00
bIsInTheAir = false ;
bVehExitWillBeInstant = true ;
if ( m_objective = = OBJECTIVE_ENTER_CAR_AS_DRIVER ) {
car - > SetDriver ( this ) ;
car - > pDriver - > RegisterReference ( ( CEntity * * ) & car - > pDriver ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
} else if ( m_objective = = OBJECTIVE_ENTER_CAR_AS_PASSENGER ) {
for ( int i = 0 ; i < 4 ; i + + ) {
if ( ! car - > pPassengers [ i ] ) {
car - > pPassengers [ i ] = this ;
car - > pPassengers [ i ] - > RegisterReference ( ( CEntity * * ) & car - > pPassengers [ i ] ) ;
break ;
}
}
} else
2019-11-19 17:15:45 -05:00
return ;
2020-11-19 14:12:20 -05:00
if ( IsPlayer ( ) ) {
car - > SetStatus ( STATUS_PLAYER ) ;
AudioManager . PlayerJustGotInCar ( ) ;
CCarCtrl : : RegisterVehicleOfInterest ( car ) ;
} else {
car - > SetStatus ( STATUS_PHYSICS ) ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
CWorld : : Remove ( this ) ;
SetPosition ( car - > GetPosition ( ) ) ;
CWorld : : Add ( this ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
if ( car - > bIsAmbulanceOnDuty ) {
car - > bIsAmbulanceOnDuty = false ;
- - CCarCtrl : : NumAmbulancesOnDuty ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
if ( car - > bIsFireTruckOnDuty ) {
car - > bIsFireTruckOnDuty = false ;
- - CCarCtrl : : NumFiretrucksOnDuty ;
}
if ( ! car - > bEngineOn ) {
car - > bEngineOn = true ;
DMAudio . PlayOneShot ( car - > m_audioEntityId , SOUND_CAR_ENGINE_START , 1.0f ) ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
# ifdef VC_PED_PORTS
RpAnimBlendClumpSetBlendDeltas ( GetClump ( ) , ASSOC_PARTIAL , - 1000.0f ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
// VC uses AddInCarAnims but we don't have that
m_pVehicleAnim = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , car - > GetDriverAnim ( ) , 100.0f ) ;
RemoveWeaponWhenEnteringVehicle ( ) ;
# else
if ( car - > IsBoat ( ) ) {
# ifndef FIX_BUGS
m_pVehicleAnim = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_DRIVE_BOAT , 100.0f ) ;
# else
m_pVehicleAnim = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , car - > GetDriverAnim ( ) , 100.0f ) ;
# endif
CWeaponInfo * ourWeapon = CWeaponInfo : : GetWeaponInfo ( GetWeapon ( ) - > m_eWeaponType ) ;
RemoveWeaponModel ( ourWeapon - > m_nModelId ) ;
} else {
// Because we can use Uzi for drive by
RemoveWeaponWhenEnteringVehicle ( ) ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
if ( car - > bLowVehicle )
m_pVehicleAnim = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_LSIT , 100.0f ) ;
else
m_pVehicleAnim = CAnimManager : : BlendAnimation ( GetClump ( ) , ASSOCGRP_STD , ANIM_CAR_SIT , 100.0f ) ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
# endif
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
StopNonPartialAnims ( ) ;
if ( car - > bIsBus )
bRenderPedInCar = false ;
2019-11-19 17:15:45 -05:00
2020-11-19 14:12:20 -05:00
bChangedSeat = true ;
2019-11-19 17:15:45 -05:00
}
2020-11-19 14:12:20 -05:00
# ifdef PEDS_REPORT_CRIMES_ON_PHONE
// returns event id, parameter is optional
int32
CPed : : CheckForPlayerCrimes ( CPed * victim )
2019-11-24 21:25:10 -05:00
{
2020-11-19 14:12:20 -05:00
int i ;
float dist ;
float mindist = 60.0f ;
CPlayerPed * player = FindPlayerPed ( ) ;
int32 victimRef = ( victim ? CPools : : GetPedRef ( victim ) : 0 ) ;
int event = - 1 ;
2019-11-24 21:25:10 -05:00
2020-11-19 14:12:20 -05:00
for ( i = 0 ; i < NUMEVENTS ; i + + ) {
if ( gaEvent [ i ] . type = = EVENT_NULL | | gaEvent [ i ] . type > EVENT_CAR_SET_ON_FIRE )
continue ;
2019-11-24 21:25:10 -05:00
2020-11-19 14:12:20 -05:00
// those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc.
if ( gaEvent [ i ] . type = = EVENT_DEAD_PED | | gaEvent [ i ] . type = = EVENT_GUNSHOT | | gaEvent [ i ] . type = = EVENT_EXPLOSION )
continue ;
if ( victim & & gaEvent [ i ] . entityRef ! = victimRef )
continue ;
if ( gaEvent [ i ] . criminal ! = player )
continue ;
dist = ( GetPosition ( ) - gaEvent [ i ] . posn ) . Magnitude ( ) ;
if ( dist < mindist ) {
mindist = dist ;
event = i ;
2019-11-24 21:25:10 -05:00
}
2020-11-19 14:12:20 -05:00
}
2019-11-24 21:25:10 -05:00
2020-11-19 14:12:20 -05:00
if ( event ! = - 1 ) {
if ( victim ) {
m_victimOfPlayerCrime = victim ;
} else {
switch ( gaEvent [ event ] . entityType ) {
case EVENT_ENTITY_PED :
m_victimOfPlayerCrime = CPools : : GetPed ( gaEvent [ event ] . entityRef ) ;
break ;
case EVENT_ENTITY_VEHICLE :
m_victimOfPlayerCrime = CPools : : GetVehicle ( gaEvent [ event ] . entityRef ) ;
break ;
case EVENT_ENTITY_OBJECT :
m_victimOfPlayerCrime = CPools : : GetObject ( gaEvent [ event ] . entityRef ) ;
break ;
default :
break ;
}
2019-11-24 21:25:10 -05:00
}
}
2020-11-19 14:12:20 -05:00
return event ;
}
# endif
# ifdef PED_SKIN
static RpMaterial *
SetLimbAlphaCB ( RpMaterial * material , void * data )
{
( ( RwRGBA * ) RpMaterialGetColor ( material ) ) - > alpha = * ( uint8 * ) data ;
return material ;
2019-11-24 21:25:10 -05:00
}
2019-12-09 18:02:02 -05:00
void
2020-11-19 14:12:20 -05:00
CPed : : renderLimb ( int node )
2019-12-09 18:02:02 -05:00
{
2020-11-19 14:12:20 -05:00
RpHAnimHierarchy * hier = GetAnimHierarchyFromSkinClump ( GetClump ( ) ) ;
int idx = RpHAnimIDGetIndex ( hier , m_pFrames [ node ] - > nodeID ) ;
RwMatrix * mat = & RpHAnimHierarchyGetMatrixArray ( hier ) [ idx ] ;
CPedModelInfo * mi = ( CPedModelInfo * ) CModelInfo : : GetModelInfo ( GetModelIndex ( ) ) ;
RpAtomic * atomic ;
switch ( node ) {
case PED_HEAD :
atomic = mi - > getHead ( ) ;
break ;
case PED_HANDL :
atomic = mi - > getLeftHand ( ) ;
break ;
case PED_HANDR :
atomic = mi - > getRightHand ( ) ;
break ;
default :
return ;
2019-12-09 18:02:02 -05:00
}
2020-11-19 14:12:20 -05:00
if ( atomic = = nil )
return ;
RwFrame * frame = RpAtomicGetFrame ( atomic ) ;
* RwFrameGetMatrix ( frame ) = * mat ;
RwFrameUpdateObjects ( frame ) ;
int alpha = CVisibilityPlugins : : GetClumpAlpha ( GetClump ( ) ) ;
RpGeometryForAllMaterials ( RpAtomicGetGeometry ( atomic ) , SetLimbAlphaCB , & alpha ) ;
RpAtomicRender ( atomic ) ;
2019-12-09 18:02:02 -05:00
}
2020-11-19 14:12:20 -05:00
# endif
2020-05-02 11:02:17 -04:00
# ifdef COMPATIBLE_SAVES
2020-05-13 09:24:00 -04:00
# define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
# define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
2020-05-02 11:02:17 -04:00
void
CPed : : Save ( uint8 * & buf )
{
SkipSaveBuf ( buf , 52 ) ;
2020-05-13 09:24:00 -04:00
CopyToBuf ( buf , GetPosition ( ) . x ) ;
CopyToBuf ( buf , GetPosition ( ) . y ) ;
CopyToBuf ( buf , GetPosition ( ) . z ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 288 ) ;
2020-05-13 09:24:00 -04:00
CopyToBuf ( buf , CharCreatedBy ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 351 ) ;
2020-05-13 09:24:00 -04:00
CopyToBuf ( buf , m_fHealth ) ;
CopyToBuf ( buf , m_fArmour ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 148 ) ;
for ( int i = 0 ; i < 13 ; i + + ) // has to be hardcoded
m_weapons [ i ] . Save ( buf ) ;
SkipSaveBuf ( buf , 5 ) ;
2020-05-13 09:24:00 -04:00
CopyToBuf ( buf , m_maxWeaponTypeAllowed ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 162 ) ;
}
void
CPed : : Load ( uint8 * & buf )
{
SkipSaveBuf ( buf , 52 ) ;
2020-05-13 09:24:00 -04:00
CopyFromBuf ( buf , GetMatrix ( ) . GetPosition ( ) . x ) ;
CopyFromBuf ( buf , GetMatrix ( ) . GetPosition ( ) . y ) ;
CopyFromBuf ( buf , GetMatrix ( ) . GetPosition ( ) . z ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 288 ) ;
2020-05-13 09:24:00 -04:00
CopyFromBuf ( buf , CharCreatedBy ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 351 ) ;
2020-05-13 09:24:00 -04:00
CopyFromBuf ( buf , m_fHealth ) ;
CopyFromBuf ( buf , m_fArmour ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 148 ) ;
for ( int i = 0 ; i < 13 ; i + + ) // has to be hardcoded
m_weapons [ i ] . Load ( buf ) ;
SkipSaveBuf ( buf , 5 ) ;
2020-05-13 09:24:00 -04:00
CopyFromBuf ( buf , m_maxWeaponTypeAllowed ) ;
2020-05-02 11:02:17 -04:00
SkipSaveBuf ( buf , 162 ) ;
}
2020-05-13 09:24:00 -04:00
# undef CopyFromBuf
# undef CopyToBuf
2020-05-02 11:02:17 -04:00
# endif