diff options
-rw-r--r-- | src/FileLoader.cpp | 1 | ||||
-rw-r--r-- | src/control/PedType.cpp | 18 | ||||
-rw-r--r-- | src/control/PedType.h | 122 | ||||
-rw-r--r-- | src/entities/Ped.cpp | 112 | ||||
-rw-r--r-- | src/entities/Ped.h | 13 | ||||
-rw-r--r-- | src/math/Vector2D.h | 6 |
6 files changed, 151 insertions, 121 deletions
diff --git a/src/FileLoader.cpp b/src/FileLoader.cpp index 7dfb1cd2..53449d9b 100644 --- a/src/FileLoader.cpp +++ b/src/FileLoader.cpp @@ -1145,7 +1145,6 @@ CFileLoader::LoadMapZones(const char *filename) STARTPATCHES - // this makes my game crash in CGarage! InjectHook(0x476290, CFileLoader::LoadLevel, PATCH_JUMP); InjectHook(0x476520, CFileLoader::LoadCollisionFromDatFile, PATCH_JUMP); diff --git a/src/control/PedType.cpp b/src/control/PedType.cpp index b6d77cb0..645ab15c 100644 --- a/src/control/PedType.cpp +++ b/src/control/PedType.cpp @@ -2,25 +2,27 @@ #include "patcher.h" #include "PedType.h" -CPedType* (&CPedType::ms_apPedType)[23] = *(CPedType * (*)[23]) * (int*)0x941594; +CPedType *(&CPedType::ms_apPedType)[NUM_PEDTYPES] = *(CPedType *(*)[NUM_PEDTYPES]) *(int*)0x941594; WRAPPER void CPedType::LoadPedData(void) { EAXJMP(0x4EE8D0); } -WRAPPER int32 CPedType::FindPedType(char* type) { EAXJMP(0x4EEC10); } +WRAPPER int32 CPedType::FindPedType(char *type) { EAXJMP(0x4EEC10); } void -CPedType::Initialise() +CPedType::Initialise(void) { + int i; + debug("Initialising CPedType...\n"); - for (int i = 0; i < 23; i++) { + for(i = 0; i < NUM_PEDTYPES; i++){ ms_apPedType[i] = new CPedType; - ms_apPedType[i]->m_Type.IntValue = 1; + ms_apPedType[i]->m_flag = PED_FLAG_PLAYER1; ms_apPedType[i]->field_4 = 0; ms_apPedType[i]->field_8 = 0; // Why field_C not initialized? ms_apPedType[i]->field_10 = 0; ms_apPedType[i]->field_14 = 0; - ms_apPedType[i]->m_Threat.IntValue = 0; - ms_apPedType[i]->m_Avoid.IntValue = 0; + ms_apPedType[i]->m_threats = 0; + ms_apPedType[i]->m_avoid = 0; } debug("Loading ped data...\n"); LoadPedData(); @@ -29,4 +31,4 @@ CPedType::Initialise() STARTPATCHES InjectHook(0x4EE7E0, &CPedType::Initialise, PATCH_JUMP); -ENDPATCHES
\ No newline at end of file +ENDPATCHES diff --git a/src/control/PedType.h b/src/control/PedType.h index 1d1057d7..a681ff13 100644 --- a/src/control/PedType.h +++ b/src/control/PedType.h @@ -4,59 +4,87 @@ #include "templates.h" #include "Lists.h" -class CPedType { -public: - union tPedTypeFlags - { - uint32 IntValue; - struct - { - uint8 bPlayer1 : 1; - uint8 bPlayer2 : 1; - uint8 bPlayer3 : 1; - uint8 bPlayer4 : 1; - uint8 bCivmale : 1; - uint8 bCivfemale : 1; - uint8 bCop : 1; - uint8 bGang1 : 1; - - uint8 bGang2 : 1; - uint8 bGang3 : 1; - uint8 bGang4 : 1; - uint8 bGang5 : 1; - uint8 bGang6 : 1; - uint8 bGang7 : 1; - uint8 bGang8 : 1; - uint8 bGang9 : 1; - - uint8 bEmergency : 1; - uint8 bProstitute : 1; - uint8 bCriminal : 1; - uint8 bSpecial : 1; - uint8 bGun : 1; - uint8 bCop_car : 1; - uint8 bFast_car : 1; - uint8 bExplosion : 1; - - uint8 bFireman : 1; - uint8 bDeadpeds : 1; - }; - }; - - tPedTypeFlags m_Type; +// Index into the PedType array +enum +{ + PEDTYPE_PLAYER1, + PEDTYPE_PLAYER2, + PEDTYPE_PLAYER3, + PEDTYPE_PLAYER4, + PEDTYPE_CIVMALE, + PEDTYPE_CIVFEMALE, + PEDTYPE_COP, + PEDTYPE_GANG1, + PEDTYPE_GANG2, + PEDTYPE_GANG3, + PEDTYPE_GANG4, + PEDTYPE_GANG5, + PEDTYPE_GANG6, + PEDTYPE_GANG7, + PEDTYPE_GANG8, + PEDTYPE_GANG9, + PEDTYPE_EMERGENCY, + PEDTYPE_FIREMAN, + PEDTYPE_CRIMINAL, + PEDTYPE_SPECIAL, + PEDTYPE_PROSTITUE, + PEDTYPE_UNUSED1, + PEDTYPE_UNUSED2, + + NUM_PEDTYPES +}; + +enum +{ + PED_FLAG_PLAYER1 = 1 << 0, + PED_FLAG_PLAYER2 = 1 << 1, + PED_FLAG_PLAYER3 = 1 << 2, + PED_FLAG_PLAYER4 = 1 << 3, + PED_FLAG_CIVMALE = 1 << 4, + PED_FLAG_CIVFEMALE = 1 << 5, + PED_FLAG_COP = 1 << 6, + PED_FLAG_GANG1 = 1 << 7, + PED_FLAG_GANG2 = 1 << 8, + PED_FLAG_GANG3 = 1 << 9, + PED_FLAG_GANG4 = 1 << 10, + PED_FLAG_GANG5 = 1 << 11, + PED_FLAG_GANG6 = 1 << 12, + PED_FLAG_GANG7 = 1 << 13, + PED_FLAG_GANG8 = 1 << 14, + PED_FLAG_GANG9 = 1 << 15, + PED_FLAG_EMERGENCY = 1 << 16, + PED_FLAG_PROSTITUTE = 1 << 17, + PED_FLAG_CRIMINAL = 1 << 18, + PED_FLAG_SPECIAL = 1 << 19, + PED_FLAG_GUN = 1 << 20, + PED_FLAG_COPCAR = 1 << 21, + PED_FLAG_FASTCAR = 1 << 22, + PED_FLAG_EXPLOSION = 1 << 23, + PED_FLAG_FIREMAN = 1 << 24, + PED_FLAG_DEADPEDS = 1 << 25, +}; + +class CPedType +{ + uint32 m_flag; float field_4; float field_8; float field_C; float field_10; float field_14; - tPedTypeFlags m_Threat; - tPedTypeFlags m_Avoid; + uint32 m_threats; + uint32 m_avoid; + + static CPedType *(&ms_apPedType)[NUM_PEDTYPES]; +public: - static CPedType* (&ms_apPedType)[23]; + static void Initialise(void); + static void LoadPedData(void); + static int32 FindPedType(char *type); - static void Initialise(); - static void LoadPedData(); - static int32 FindPedType(char* type); + static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; } + static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; } + static uint32 GetThreats(int type) { return ms_apPedType[type]->m_threats; } }; -static_assert(sizeof(CPedType) == 0x20, "CPedType: error");
\ No newline at end of file +static_assert(sizeof(CPedType) == 0x20, "CPedType: error"); diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 12528b20..9e986dd0 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -177,6 +177,13 @@ static char WaitStateText[21][16] = { }; bool +CPed::IsPlayer(void) +{ + return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType== PEDTYPE_PLAYER2 || + m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4; +} + +bool CPed::UseGroundColModel(void) { return m_nPedState == PED_FALL || @@ -217,7 +224,7 @@ CPed::AimGun() CPed::Say(SOUND_PED_ATTACK); m_ped_flagB2 = m_pedIK.PointGunAtPosition(&vector); - if (m_pPedFight != m_pSeekTarget) { + if (m_pLookTarget != m_pSeekTarget) { CPed::SetLookFlag(m_pSeekTarget, 1); } @@ -327,16 +334,16 @@ CPed::RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data) } void -CPed::SetLookFlag(CPed *to, bool set) +CPed::SetLookFlag(CPed *target, bool unknown) { if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { - m_ped_flagA10 = 1; - m_ped_flagA40 = 0; - m_pPedFight = to; - m_pPedFight->RegisterReference((CEntity**)&m_pPedFight); + bIsLooking = true; + m_ped_flagA40 = false; + m_pLookTarget = target; + m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); m_fLookDirection = 999999.0f; m_lookTimer = 0; - m_ped_flagA20_look = set; + m_ped_flagA20_look = unknown; if (m_nPedState != PED_DRIVING) { m_pedIK.m_flags &= ~CPedIK::FLAG_2; } @@ -344,15 +351,15 @@ CPed::SetLookFlag(CPed *to, bool set) } void -CPed::SetLookFlag(float angle, bool set) +CPed::SetLookFlag(float direction, bool unknown) { if (m_lookTimer < CTimer::GetTimeInMilliseconds()) { - m_ped_flagA10 = 1; - m_ped_flagA40 = 0; - m_pPedFight = 0; - m_fLookDirection = angle; + bIsLooking = true; + m_ped_flagA40 = false; + m_pLookTarget = nil; + m_fLookDirection = direction; m_lookTimer = 0; - m_ped_flagA20_look = set; + m_ped_flagA20_look = unknown; if (m_nPedState != PED_DRIVING) { m_pedIK.m_flags &= ~CPedIK::FLAG_2; } @@ -368,76 +375,65 @@ CPed::SetLookTimer(int time) } bool -CPed::OurPedCanSeeThisOne(CEntity* who) +CPed::OurPedCanSeeThisOne(CEntity *target) { - float distance; CColPoint colpoint; - CEntity* ent; - CVector ourPos; - CVector itsPos; + CEntity *ent; - ourPos = this->GetPosition(); - itsPos = who->GetPosition(); + CVector2D dist = CVector2D(target->GetPosition()) - CVector2D(this->GetPosition()); - CVector2D posDiff( - itsPos.x - ourPos.x, - itsPos.y - ourPos.y - ); - - if ((posDiff.y * this->GetForward().y) + (posDiff.x * this->GetForward().x) < 0.0f) + // Check if target is behind ped + if (DotProduct2D(dist, CVector2D(this->GetForward())) < 0.0f) return 0; - distance = posDiff.Magnitude(); - - if (distance < 40.0f) + // Check if target is too far away + if (dist.Magnitude() < 40.0f) return 0; - ourPos.z += 1.0f; - return !CWorld::ProcessLineOfSight(ourPos, itsPos, colpoint, ent, 1, 0, 0, 0, 0, 0, 0); + // 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); } void -CPed::Avoid(void) { - int8 temper; - int moveState; - CPed* nearestPed; - float walkAngle; - float distance; - - temper = m_pedStats->m_temper; - if ((temper <= m_pedStats->m_fear || temper <= 50) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { - moveState = m_nMoveState; - - if (moveState != PEDMOVE_NONE && moveState != PEDMOVE_STILL) { +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) { - if (nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_field_16C - && (CPedType::ms_apPedType[nearestPed->m_nPedType]->m_Type.IntValue - & CPedType::ms_apPedType[this->m_nPedType]->m_Avoid.IntValue)) { + if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_field_16C) { + + // Check if this ped wants to avoid the nearest one + if (CPedType::GetAvoid(this->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. - walkAngle = RADTODEG(m_fRotationCur) / RADTODEG(1); - - // Original code was multiplying sin/cos with the number below, which is pointless because it's always 1. - // ratio = 1.0f / sqrt(sin*sin + cos*cos); + // 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 - CVector2D walkedUpToPed( - nearestPed->GetPosition().x - (1.25 * -sin(walkAngle) + GetPosition().x), - nearestPed->GetPosition().y - (1.25 * cos(walkAngle) + GetPosition().y) - ); + // Move forward 1.25 meters + CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f; - distance = walkedUpToPed.Magnitude(); + // Get distance to ped we want to avoid + CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition; - if (distance <= 1.0f && CPed::OurPedCanSeeThisOne((CEntity*)nearestPed)) { + if (distToPed.Magnitude() <= 1.0f && CPed::OurPedCanSeeThisOne((CEntity*)nearestPed)) { m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 / 5; m_fRotationDest += DEGTORAD(45.0f); - if (!m_ped_flagA10) { + if (!bIsLooking) { CPed::SetLookFlag(nearestPed, 0); CPed::SetLookTimer(CGeneral::GetRandomNumberInRange(0, 300) + 500); } diff --git a/src/entities/Ped.h b/src/entities/Ped.h index f9e46dae..60b88765 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -97,7 +97,7 @@ public: uint8 m_ped_flagA2 : 1; uint8 m_ped_flagA4 : 1; // stores (CTimer::GetTimeInMilliseconds() < m_lastHitTime) uint8 m_ped_flagA8 : 1; - uint8 m_ped_flagA10 : 1; // set when A20 just changed? + uint8 bIsLooking : 1; // set when A20 just changed? uint8 m_ped_flagA20_look : 1; uint8 m_ped_flagA40 : 1; uint8 m_ped_flagA80 : 1; @@ -222,7 +222,7 @@ public: int32 m_pPointGunAt; CVector m_vecHitLastPos; uint8 stuff8[12]; - CPed *m_pPedFight; + CEntity *m_pLookTarget; float m_fLookDirection; int32 m_wepModelID; uint32 m_leaveCarTimer; @@ -240,21 +240,20 @@ public: static void *operator new(size_t); static void operator delete(void*, size_t); - // TODO: enum! - bool IsPlayer(void) { return m_nPedType == 0 || m_nPedType== 1 || m_nPedType == 2 || m_nPedType == 3; } + bool IsPlayer(void); bool UseGroundColModel(void); void AddWeaponModel(int id); void AimGun(); void KillPedWithCar(CVehicle *veh, float impulse); void Say(uint16 audio); - void SetLookFlag(CPed *to, bool set); - void SetLookFlag(float angle, bool set); + void SetLookFlag(CPed *target, bool unknown); + void SetLookFlag(float direction, bool unknown); void SetLookTimer(int time); void SetDie(AnimationId anim, float arg1, float arg2); void ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer); void RemoveBodyPart(PedNode nodeId, int8 unknown); void SpawnFlyingComponent(int, int8 unknown); - bool OurPedCanSeeThisOne(CEntity* who); + bool OurPedCanSeeThisOne(CEntity *target); void Avoid(void); static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data); static RwFrame *RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data); diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h index 3c0013d4..fa32bd9b 100644 --- a/src/math/Vector2D.h +++ b/src/math/Vector2D.h @@ -31,6 +31,12 @@ public: }; inline float +DotProduct2D(const CVector2D &v1, const CVector2D &v2) +{ + return v1.x*v2.x + v1.y*v2.y; +} + +inline float CrossProduct2D(const CVector2D &v1, const CVector2D &v2) { return v1.x*v2.y - v1.y*v2.x; |