diff options
-rw-r--r-- | src/control/AutoPilot.h | 92 | ||||
-rw-r--r-- | src/entities/Ped.cpp | 416 | ||||
-rw-r--r-- | src/entities/Ped.h | 78 | ||||
-rw-r--r-- | src/entities/Vehicle.h | 10 | ||||
-rw-r--r-- | src/weapons/Weapon.cpp | 6 | ||||
-rw-r--r-- | src/weapons/Weapon.h | 1 |
6 files changed, 540 insertions, 63 deletions
diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h new file mode 100644 index 00000000..a2458327 --- /dev/null +++ b/src/control/AutoPilot.h @@ -0,0 +1,92 @@ +#pragma once + +class CVehicle; + +enum eCarMission : uint8 +{ + MISSION_NONE, + MISSION_CRUISE, + MISSION_RAMPLAYER_FARAWAY, + MISSION_RAMPLAYER_CLOSE, + MISSION_BLOCKPLAYER_FARAWAY, + MISSION_BLOCKPLAYER_CLOSE, + MISSION_BLOCKPLAYER_HANDBRAKESTOP, + MISSION_WAITFORDELETION, + MISSION_GOTOCOORDS, + MISSION_GOTOCOORDS_STRAIGHT, + MISSION_EMERGENCYVEHICLE_STOP, + MISSION_STOP_FOREVER, + MISSION_GOTOCOORDS_ACCURATE, + MISSION_GOTO_COORDS_STRAIGHT_ACCURATE, + MISSION_GOTOCOORDS_ASTHECROWSWIMS, + MISSION_RAMCAR_FARAWAY, + MISSION_RAMCAR_CLOSE, + MISSION_BLOCKCAR_FARAWAY, + MISSION_BLOCKCAR_CLOSE, + MISSION_BLOCKCAR_HANDBRAKESTOP, + MISSION_HELI_FLYTOCOORS, + MISSION_ATTACKPLAYER, + MISSION_PLANE_FLYTOCOORS, + MISSION_HELI_LAND, + MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1, + MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2, + MISSION_BLOCKPLAYER_FORWARDANDBACK +}; + +enum eCarTempAction : uint8 +{ + TEMPACT_NONE, + TEMPACT_WAIT, + TEMPACT_REVERSE, + TEMPACT_HANDBRAKETURNLEFT, + TEMPACT_HANDBRAKETURNRIGHT, + TEMPACT_HANDBRAKESTRAIGHT, + TEMPACT_TURNLEFT, + TEMPACT_TURNRIGHT, + TEMPACT_GOFORWARD, + TEMPACT_SWERVELEFT, + TEMPACT_SWERVERIGHT +}; + +enum eCarDrivingStyle : uint8 +{ + DRIVINGSTYLE_STOP_FOR_CARS, + DRIVINGSTYLE_SLOW_DOWN_FOR_CARS, + DRIVINGSTYLE_AVOID_CARS, + DRIVINGSTYLE_PLOUGH_THROUGH, + DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS +}; + +class CAutoPilot { +public: + void *m_currentAddress; + void *m_startingRouteNode; + void *m_PreviousRouteNode; + uint32 m_nTotalSpeedScaleFactor; + uint32 m_nSpeedScaleFactor; + uint32 m_nCurrentPathNodeInfo; + uint32 m_nNextPathNodeInfo; + uint32 m_nPreviousPathNodeInfo; + uint32 m_nTimeToStartMission; + uint32 m_nTimeSwitchedToRealPhysics; + int8 m_nPreviousDirection; + int8 m_nCurrentDirecton; + int8 m_nNextDirection; + int8 m_nPreviousPathDirection; + int8 m_nCurrentPathDirection; + eCarDrivingStyle m_nDrivingStyle; + eCarMission m_nCarMission; + eCarTempAction m_nAnimationId; + uint8 m_nAnimationTime; + float m_fMaxTrafficSpeed; + uint8 m_nCruiseSpeed; + uint8 m_nCarCtrlFlags; + int8 pad1[2]; + CVector m_vecDestinationCoors; + void *m_aPathFindNodesInfo[8]; + uint16 m_nPathFindNodesCount; + int8 pad2[2]; + CVehicle *m_pTargetCar; +}; + +static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error");
\ No newline at end of file diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 9e1836c2..e53066f7 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -24,21 +24,23 @@ #include "PointLights.h" #include "Pad.h" -WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); } -WRAPPER void CPed::KillPedWithCar(CVehicle* veh, float impulse) { EAXJMP(0x4EC430); } +WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); } WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); } WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); } WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); } WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); } WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); } -WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2480); } -WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2920); } +WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); } +WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); } WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); } WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); } WRAPPER void CPed::PreRender(void) { EAXJMP(0x4CFDD0); } WRAPPER void CPed::Render(void) { EAXJMP(0x4D03F0); } WRAPPER int32 CPed::ProcessEntityCollision(CEntity*, CColPoint*) { EAXJMP(0x4CBB30); } WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); } +WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); } +WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); } +WRAPPER void CPed::RegisterThreatWithGangPeds(CEntity*) { EAXJMP(0x4E3870); } bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; @@ -60,14 +62,7 @@ CPed::~CPed(void) CWorld::Remove(this); CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); if (bInVehicle && m_pMyVehicle){ - uint8 door_flag = 0; - switch (m_vehEnterType) { - case VEHICLE_ENTER_FRONT_LEFT: door_flag = 1; break; - case VEHICLE_ENTER_REAR_LEFT: door_flag = 2; break; - case VEHICLE_ENTER_FRONT_RIGHT: door_flag = 4; break; - case VEHICLE_ENTER_REAR_RIGHT: door_flag = 8; break; - default: break; - } + uint8 door_flag = GetVehEnterExitFlag(m_vehEnterType); if (m_pMyVehicle->pDriver == this) m_pMyVehicle->pDriver = nil; else { @@ -330,7 +325,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_fleeTimer = 0; m_vecSeekPosEx = CVector(0.0f, 0.0f, 0.0f); m_seekExAngle = 0.0f; - m_nWaitState = 0; + m_nWaitState = WAITSTATE_FALSE; m_nWaitTimer = 0; m_pCollidingEntity = nil; m_nPedState = PED_IDLE; @@ -370,15 +365,15 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bIsRestoringGun = false; bCanPointGunAtTarget = false; - m_ped_flagB4 = false; - m_ped_flagB8 = false; - m_ped_flagB10 = false; + bIsTalking = false; + bIsInTheAir = false; + bIsLanding = false; m_ped_flagB20 = false; m_ped_flagB40 = false; m_ped_flagB80 = false; m_ped_flagC1 = false; - m_ped_flagC2 = true; + bRespondsToThreats = true; m_ped_flagC4 = true; m_ped_flagC8 = false; m_ped_flagC10 = false; @@ -397,9 +392,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagE1 = false; m_ped_flagE2 = false; - m_ped_flagE4 = false; - m_ped_flagE8 = false; - bCantFireBecauseCrouched = false; + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + bIsDucking = false; m_ped_flagE20 = false; bDoBloodyFootprints = false; m_ped_flagE80 = false; @@ -635,7 +630,7 @@ bool CPed::IsPedInControl(void) { return m_nPedState <= PED_STATES_NO_AI - && !m_ped_flagB8 && !m_ped_flagB10 + && !bIsInTheAir && !bIsLanding && m_fHealth > 0.0f; } @@ -1019,7 +1014,7 @@ CPed::Attack(void) if (reloadAnim != NUM_ANIMS) reloadAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, reloadAnim); - if (bCantFireBecauseCrouched) + if (bIsDucking) return; if (reloadAnimAssoc) { @@ -1280,7 +1275,7 @@ CPed::ClearDuck(void) if (animAssoc) { - if (m_ped_flagE8) { + if (bCrouchWhenShooting) { if (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN) { animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RBLOCK_CSHOOT); @@ -1290,7 +1285,7 @@ CPed::ClearDuck(void) } } } else - bCantFireBecauseCrouched = false; + bIsDucking = false; } void @@ -1400,20 +1395,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) ped->m_pSeekTarget = nil; vehicle = ped->m_pMyVehicle; - switch (ped->m_vehEnterType) { - case VEHICLE_ENTER_FRONT_RIGHT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FR; - break; - case VEHICLE_ENTER_REAR_RIGHT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RR; - break; - case VEHICLE_ENTER_FRONT_LEFT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FL; - break; - case VEHICLE_ENTER_REAR_LEFT: - vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RL; - break; - } + vehicle->m_nGettingOutFlags &= ~GetVehEnterExitFlag(ped->m_vehEnterType); if (vehicle->pDriver == ped) { vehicle->RemoveDriver(); @@ -1742,7 +1724,6 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } } - // I hope bool stillGettingInOut = false; if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || m_ped_flagG10; @@ -1937,7 +1918,7 @@ CPed::IsPointerValid(void) // Some kind of binary sort void -CPed::SortPeds(CPed** list, int min, int max) +CPed::SortPeds(CPed **list, int min, int max) { if (min >= max) return; @@ -1977,7 +1958,7 @@ CPed::SortPeds(CPed** list, int min, int max) void CPed::BuildPedLists(void) { - static CPed* unsortedNearPeds[10]; + static CPed *unsortedNearPeds[10]; uint16 nextNearPedSlot = 0; if ((CTimer::GetFrameCounter() + m_randomSeed) & 15) { @@ -2543,6 +2524,350 @@ CPed::SetObjective(eObjective newObj, void *entity) } } +void +CPed::SetIdle(void) +{ + if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) { + m_nPedState = PED_IDLE; + SetMoveState(PEDMOVE_STILL); + } + if (m_nWaitState == WAITSTATE_FALSE) { + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000); + } +} + +void +CPed::SetObjective(eObjective newObj) +{ + if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD) + return; + + if (newObj == OBJECTIVE_NONE) { + if ((m_objective == OBJECTIVE_LEAVE_VEHICLE || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) + && IsPedInControl()) { + + m_ped_flagG8 = true; + return; + } + // Unused code from assembly... + /* + else if(m_objective == OBJECTIVE_FLEE_CAR) { + + } else { + + } + */ + m_objective = newObj; + m_prevObjective = OBJECTIVE_NONE; + } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) { + SetObjectiveTimer(0); + + if (m_objective == newObj) + return; + + if (IsTemporaryObjective(m_objective)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) + SetStoredObjective(); + + m_objective = newObj; + } + m_ped_flagD40 = false; + + switch (newObj) { + case OBJECTIVE_NONE: + m_prevObjective = OBJECTIVE_NONE; + break; + case OBJECTIVE_HAIL_TAXI: + m_nWaitTimer = 0; + SetIdle(); + SetMoveState(PEDMOVE_STILL); + break; + default: + break; + } + } +} + +// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode +// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call... +void +CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType) +{ + if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD) + return; + + if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE) + return; + + SetObjectiveTimer(0); + + if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType) + return; + + m_ped_flagD40 = false; + if (IsTemporaryObjective(m_objective)) { + m_prevObjective = newObj; + } else { + if (m_objective != newObj) + SetStoredObjective(); + + m_objective = newObj; + } + + if (newObj == OBJECTIVE_FOLLOW_ROUTE) { + SetFollowRoute(routePoint, routeType); + } +} + +void +CPed::ClearChat(void) +{ + CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT); + if (animAssoc) { + animAssoc->blendDelta = -8.0f; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + } + bIsTalking = false; + ClearLookFlag(); + RestorePreviousState(); +} + +bool +CPed::IsGangMember(void) +{ + return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9; +} + +void +CPed::InformMyGangOfAttack(CEntity *attacker) +{ + CPed *attackerPed; + + if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) + return; + + if (attacker->IsPed()) { + attackerPed = (CPed*)attacker; + } else { + if (!attacker->IsVehicle()) + return; + + attackerPed = ((CVehicle*)attacker)->pDriver; + if (!attackerPed) + return; + } + + if (attackerPed->m_nPedType == PEDTYPE_COP) + return; + + for (int i = 0; i < m_numNearPeds; i++) { + CPed *nearPed = m_nearPeds[i]; + if (nearPed && nearPed != this) { + CPed *leader = nearPed->m_leader; + if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) + { + nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed); + nearPed->SetObjectiveTimer(30000); + } + } + } +} + +void +CPed::QuitEnteringCar(void) +{ + CAnimBlendAssociation *animAssoc = m_pVehicleAnim; + CVehicle *veh = m_pMyVehicle; + if (animAssoc) + animAssoc->blendDelta = -1000.0f; + + RestartNonPartialAnims(); + + if (!RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_STANCE)) + CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f); + + if (veh) { + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK) + veh->m_veh_flagC10 = false; + + if (veh->m_nNumGettingIn != 0) + veh->m_nNumGettingIn--; + + veh->m_nGettingInFlags = GetVehEnterExitFlag(m_vehEnterType); + } + + bUsesCollision = true; + + if (IsPlayer() && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) { + if (IsPlayer() && m_storedWeapon != NO_STORED_WEAPON) { + SetCurrentWeapon(m_storedWeapon); + m_storedWeapon = NO_STORED_WEAPON; + } + } else { + CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + AddWeaponModel(curWeapon->m_nModelId); + } + if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD) { + animAssoc = m_pVehicleAnim; + if (animAssoc) { + animAssoc->blendDelta = -4.0; + animAssoc->flags |= ASSOC_FADEOUTWHENDONE; + animAssoc = m_pVehicleAnim; + animAssoc->flags &= ~ASSOC_RUNNING; + } + } else + SetIdle(); + + m_pVehicleAnim = nil; + + if (veh) { + if (veh->m_autoPilot.m_nCruiseSpeed == 0) + veh->m_autoPilot.m_nCruiseSpeed = 17; + } +} + +void +CPed::ReactToAttack(CEntity *attacker) +{ + if (IsPlayer() && attacker->IsPed()) { + InformMyGangOfAttack(attacker); + SetLookFlag(attacker, 1); + SetLookTimer(700); + return; + } + + if (IsPedInControl() && (m_nCreatedBy != CREATED_BY_SCRIPT || bRespondsToThreats)) { + CPed *ourLeader = m_leader; + if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader) + && attacker->IsPed()) { + + CPed *attackerPed = (CPed*)attacker; + if (bNotAllowedToDuck) { + if (!attackerPed->GetWeapon()->IsTypeMelee()) { + field_4E8 = CTimer::GetTimeInMilliseconds(); + return; + } + } else if (bCrouchWhenShooting || m_ped_flagE1) { + SetDuck(CGeneral::GetRandomNumberInRange(1000,3000)); + return; + } + + if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) { + if (m_pedStats != attackerPed->m_pedStats) { + if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) { + RegisterThreatWithGangPeds(attackerPed); + } + if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker); + SetMoveState(PEDMOVE_RUN); + } else { + SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker); + SetObjectiveTimer(20000); + } + } + } else { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed); + SetMoveState(PEDMOVE_RUN); + if (attackerPed->GetWeapon()->IsTypeMelee()) + Say(SOUND_PED_FLEE_RUN); + } + } + } +} + +bool +CPed::TurnBody(void) +{ + float lookDir; + bool doneSmoothly = true; + + if (m_pLookTarget) { + CVector &lookPos = m_pLookTarget->GetPosition(); + + lookDir = CGeneral::GetRadianAngleBetweenPoints( + lookPos.x, + lookPos.y, + GetPosition().x, + GetPosition().y); + } else + lookDir = m_fLookDirection; + + float limitedLookDir = CGeneral::LimitRadianAngle(lookDir); + 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 (fabs(neededTurn) > 0.05f) { + doneSmoothly = false; + currentRot -= neededTurn * 0.2f; + } + + m_fRotationCur = currentRot; + m_fLookDirection = limitedLookDir; + return doneSmoothly; +} + +void +CPed::Chat(void) +{ + if (bIsLooking && TurnBody()) + ClearLookFlag(); + + if (!m_pLookTarget || !m_pLookTarget->IsPed()) { + ClearChat(); + return; + } + + 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); + } + return; + } + if (bIsTalking) { + if (CGeneral::GetRandomNumber() < 512) { + CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT); + if (chatAssoc) { + chatAssoc->blendDelta = -4.0f; + chatAssoc->flags |= ASSOC_FADEOUTWHENDONE; + } + bIsTalking = false; + } else + Say(SOUND_PED_CHAT); + + } else if (!RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject, ASSOC_FLAG100)) { + + if (CGeneral::GetRandomNumber() < 20) { + CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); + } + if (!bIsTalking) { + CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f); + float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f); + chatAssoc->SetCurrentTime(chatTime); + + bIsTalking = true; + Say(SOUND_PED_CHAT); + } + } + if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) { + ClearChat(); + m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; + } +} + WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); } WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); } WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); } @@ -2611,5 +2936,14 @@ STARTPATCHES InjectHook(0x4D72F0, &CPed::CanPedJumpThis, PATCH_JUMP); InjectHook(0x4DD820, &CPed::CanSeeEntity, PATCH_JUMP); InjectHook(0x4D9460, &CPed::RestorePreviousObjective, PATCH_JUMP); + InjectHook(0x4D82C0, (void (CPed::*)(eObjective)) &CPed::SetObjective, PATCH_JUMP); InjectHook(0x4D83E0, (void (CPed::*)(eObjective, void*)) &CPed::SetObjective, PATCH_JUMP); + InjectHook(0x4D89A0, (void (CPed::*)(eObjective, int16, int16)) &CPed::SetObjective, PATCH_JUMP); + InjectHook(0x4DDEC0, &CPed::ReactToAttack, PATCH_JUMP); + InjectHook(0x4D0600, &CPed::SetIdle, PATCH_JUMP); + InjectHook(0x4E0E00, &CPed::QuitEnteringCar, PATCH_JUMP); + InjectHook(0x4E4AD0, &CPed::InformMyGangOfAttack, PATCH_JUMP); + InjectHook(0x4D3C80, &CPed::ClearChat, PATCH_JUMP); + InjectHook(0x4D1390, &CPed::TurnBody, PATCH_JUMP); + InjectHook(0x4D3AC0, &CPed::Chat, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Ped.h b/src/entities/Ped.h index 558ec9c1..a774dbbe 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -13,7 +13,31 @@ struct CPathNode; -enum eObjective { +enum eWaitState : uint32 { + WAITSTATE_FALSE, + WAITSTATE_TRAFFIC_LIGHTS, + WAITSTATE_CROSS_ROAD, + WAITSTATE_CROSS_ROAD_LOOK, + WAITSTATE_LOOK_PED, + WAITSTATE_LOOK_SHOP, + WAITSTATE_LOOK_ACCIDENT, + WAITSTATE_FACEOFF_GANG, + WAITSTATE_DOUBLEBACK, + WAITSTATE_HITWALL, + WAITSTATE_TURN180, + WAITSTATE_SURPRISE, + WAITSTATE_STUCK, + WAITSTATE_LOOK_ABOUT, + WAITSTATE_PLAYANIM_DUCK, + WAITSTATE_PLAYANIM_COWER, + WAITSTATE_PLAYANIM_TAXI, + WAITSTATE_PLAYANIM_HANDSUP, + WAITSTATE_PLAYANIM_HANDSCOWER, + WAITSTATE_PLAYANIM_CHAT, + WAITSTATE_FINISH_FLEE +}; + +enum eObjective : uint32 { OBJECTIVE_NONE, OBJECTIVE_IDLE, OBJECTIVE_FLEE_TILL_SAFE, @@ -52,7 +76,7 @@ enum eObjective { OBJECTIVE_35 }; -enum { +enum eVehEnter : uint16 { VEHICLE_ENTER_FRONT_RIGHT = 11, VEHICLE_ENTER_REAR_RIGHT = 12, VEHICLE_ENTER_FRONT_LEFT = 15, @@ -168,15 +192,15 @@ public: uint8 bIsRestoringGun : 1; uint8 bCanPointGunAtTarget : 1; - uint8 m_ped_flagB4 : 1; - uint8 m_ped_flagB8 : 1; - uint8 m_ped_flagB10 : 1; + uint8 bIsTalking : 1; + uint8 bIsInTheAir : 1; + uint8 bIsLanding : 1; uint8 m_ped_flagB20 : 1; uint8 m_ped_flagB40 : 1; uint8 m_ped_flagB80 : 1; uint8 m_ped_flagC1 : 1; - uint8 m_ped_flagC2 : 1; + uint8 bRespondsToThreats : 1; uint8 m_ped_flagC4 : 1; uint8 m_ped_flagC8 : 1; uint8 m_ped_flagC10 : 1; @@ -195,9 +219,9 @@ public: uint8 m_ped_flagE1 : 1; uint8 m_ped_flagE2 : 1; - uint8 m_ped_flagE4 : 1; - uint8 m_ped_flagE8 : 1; // can duck? - uint8 bCantFireBecauseCrouched : 1; // set if you don't want ped to attack + uint8 bNotAllowedToDuck : 1; + uint8 bCrouchWhenShooting : 1; + uint8 bIsDucking : 1; // set if you don't want ped to attack uint8 m_ped_flagE20 : 1; uint8 bDoBloodyFootprints : 1; uint8 m_ped_flagE80 : 1; @@ -270,7 +294,7 @@ public: eMoveState m_nMoveState; int32 m_nStoredActionState; int32 m_nPrevActionState; - int32 m_nWaitState; + eWaitState m_nWaitState; uint32 m_nWaitTimer; void *m_pPathNodesStates[8]; CVector2D m_stPathNodeStates[10]; @@ -286,15 +310,15 @@ public: float m_fArmour; int16 m_routeLastPoint; uint16 m_routePoints; - uint16 m_routePos; - uint16 m_routeType; - uint16 m_routeCurDir; + int16 m_routePos; + int16 m_routeType; + int16 m_routeCurDir; uint16 field_2D2; CVector2D m_moved; float m_fRotationCur; float m_fRotationDest; float m_headingRate; - uint16 m_vehEnterType; + eVehEnter m_vehEnterType; uint16 m_walkAroundType; CEntity *m_pCurrentPhysSurface; CVector m_vecOffsetFromPhysSurface; @@ -426,7 +450,18 @@ public: bool CanPedJumpThis(int32); bool CanSeeEntity(CEntity*, float); void RestorePreviousObjective(void); + void SetIdle(void); void SetObjective(eObjective, void*); + void SetObjective(eObjective); + void SetObjective(eObjective, int16, int16); + void ClearChat(void); + void InformMyGangOfAttack(CEntity*); + void SetFollowRoute(int16, int16); + void ReactToAttack(CEntity*); + void SetDuck(uint32); + void RegisterThreatWithGangPeds(CEntity*); + bool TurnBody(void); + void Chat(void); // Static methods static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); @@ -482,11 +517,26 @@ public: void SetStoredObjective(void); void SetLeader(CEntity* leader); void SetPedStats(ePedStats); + bool IsGangMember(void); inline bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } inline CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } inline CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } inline RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; } + inline static uint8 GetVehEnterExitFlag(eVehEnter vehEnter) { + switch (vehEnter) { + case VEHICLE_ENTER_FRONT_RIGHT: + return 4; + case VEHICLE_ENTER_REAR_RIGHT: + return 8; + case VEHICLE_ENTER_FRONT_LEFT: + return 1; + case VEHICLE_ENTER_REAR_LEFT: + return 2; + default: + return 0; + } + } // to make patching virtual functions possible void SetModelIndex_(uint32 mi) { CPed::SetModelIndex(mi); } diff --git a/src/entities/Vehicle.h b/src/entities/Vehicle.h index ba3e568e..e9acaa0b 100644 --- a/src/entities/Vehicle.h +++ b/src/entities/Vehicle.h @@ -1,18 +1,12 @@ #pragma once #include "Physical.h" +#include "AutoPilot.h" class CPed; class CFire; struct tHandlingData; -enum { - GETTING_IN_OUT_FL = 1, - GETTING_IN_OUT_RL = 2, - GETTING_IN_OUT_FR = 4, - GETTING_IN_OUT_RR = 8 -}; - enum eCarLock : uint8 { CARLOCK_NOT_USED, CARLOCK_UNLOCKED, @@ -29,7 +23,7 @@ class CVehicle : public CPhysical public: // 0x128 tHandlingData *m_handling; - uint8 stuff1[112]; + CAutoPilot m_autoPilot; uint8 m_currentColour1; uint8 m_currentColour2; uint8 m_anExtras[2]; diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 0c48db6b..90a6408b 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -35,6 +35,12 @@ CWeapon::Reload(void) m_nAmmoInClip = m_nAmmoTotal; } +bool +CWeapon::IsTypeMelee(void) +{ + return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT; +} + STARTPATCHES InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP); InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP); diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 8cb435ce..ba552035 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -58,5 +58,6 @@ public: void Reload(void); bool Fire(CEntity*, CVector*); void AddGunshell(CEntity*, CVector const&, CVector2D const&, float); + bool IsTypeMelee(void); }; static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); |