From e45689373db75d47ee6a87aa5440de8d99d87c4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?eray=20or=C3=A7unus?= <erayorcunus@gmail.com>
Date: Mon, 17 Jun 2019 12:48:42 +0300
Subject: [PATCH 1/3] CPed::Avoid and needed changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: eray orçunus <erayorcunus@gmail.com>
---
 src/PedType.cpp      | 31 +++++++++++++++++++++
 src/PedType.h        | 61 +++++++++++++++++++++++++++++++++++++++++
 src/entities/Ped.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++--
 src/entities/Ped.h   | 12 ++++++---
 4 files changed, 162 insertions(+), 6 deletions(-)
 create mode 100644 src/PedType.cpp
 create mode 100644 src/PedType.h

diff --git a/src/PedType.cpp b/src/PedType.cpp
new file mode 100644
index 00000000..904b4f97
--- /dev/null
+++ b/src/PedType.cpp
@@ -0,0 +1,31 @@
+#include "common.h"
+#include "patcher.h"
+#include "PedType.h"
+
+CPedType* (&CPedType::ms_apPedType)[23] = *(CPedType * (*)[23]) * (int*)0x941594;
+
+WRAPPER void CPedType::LoadPedData(void) { EAXJMP(0x4EE8D0); }
+
+void
+CPedType::Initialise()
+{
+	debug("Initialising CPedType...\n");
+	for(int i = 0; i < 23; i++) {
+		ms_apPedType[i] = new CPedType;
+		ms_apPedType[i]->m_Type.IntValue = 1;
+		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;
+	}
+	debug("Loading ped data...\n");
+	LoadPedData();
+	debug("CPedType ready\n");
+}
+
+STARTPATCHES
+	InjectHook(0x4EE7E0, &CPedType::Initialise, PATCH_JUMP);
+ENDPATCHES
\ No newline at end of file
diff --git a/src/PedType.h b/src/PedType.h
new file mode 100644
index 00000000..7b9e3096
--- /dev/null
+++ b/src/PedType.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "common.h"
+#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;
+	float field_4;
+	float field_8;
+	float field_C;
+	float field_10;
+	float field_14;
+	tPedTypeFlags m_Threat;
+	tPedTypeFlags m_Avoid;
+
+	static CPedType* (&ms_apPedType)[23];
+
+	static void Initialise();
+	static void LoadPedData();
+};
+
+static_assert(sizeof(CPedType) == 0x20, "CPedType: error");
\ No newline at end of file
diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index ccb07d46..b8236ecc 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -7,6 +7,8 @@
 #include "PedStat.h"
 #include "DMaudio.h"
 #include "Ped.h"
+#include "PedType.h"
+#include "General.h"
 
 bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
 bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
@@ -229,8 +231,6 @@ CPed::AimGun()
 	}
 }
 
-
-// After I finished this I realized it's only for SCM opcode...
 void
 CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
 {
@@ -397,6 +397,65 @@ CPed::OurPedCanSeeThisOne(CEntity* who)
 	return !CWorld::ProcessLineOfSight(ourPos, itsPos, colpoint, ent, 1, 0, 0, 0, 0, 0, 0);
 }
 
+void
+CPed::Avoid(void) {
+	int8 temper;
+	int moveState;
+	CPed* nearestPed;
+	float sinValue;
+	float cosValue;
+	float someRate;
+	float someY;
+	float someX;
+	float someDistance;
+	float simplifiedAngle;
+
+	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) {
+			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)) {
+
+					simplifiedAngle = RADTODEG(m_fRotationCur) / RADTODEG(1);
+					sinValue = -sin(simplifiedAngle);
+					cosValue = cos(simplifiedAngle);
+
+					// sin^2 + cos^2 must always return 1, and it does return... so what's the point?
+					someRate = 1.0f / sqrt(cosValue * cosValue + sinValue * sinValue);
+
+					// 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.
+					someY = nearestPed->GetPosition().y
+						- (1.25 * (cosValue * someRate)
+							+ GetPosition().y);
+					someX = nearestPed->GetPosition().x
+						- (1.25 * (sinValue * someRate)
+							+ GetPosition().x);
+					someDistance = sqrt(someY * someY + someX * someX);
+
+					if (someDistance <= 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) {
+							CPed::SetLookFlag(nearestPed, 0);
+							CPed::SetLookTimer(CGeneral::GetRandomNumberInRange(0, 300) + 500);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
 STARTPATCHES
 	InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP);
 	InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP);
@@ -406,4 +465,5 @@ STARTPATCHES
 	InjectHook(0x4C63E0, (void (CPed::*)(float, bool)) &CPed::SetLookFlag, PATCH_JUMP);
 	InjectHook(0x4D12E0, &CPed::SetLookTimer, PATCH_JUMP);
 	InjectHook(0x4C5700, &CPed::OurPedCanSeeThisOne, PATCH_JUMP);
+	InjectHook(0x4D2BB0, &CPed::Avoid, PATCH_JUMP);
 ENDPATCHES
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index 0b0a5562..0249c707 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;
 	uint8 m_ped_flagA8 : 1;
-	uint8 m_ped_flagA10 : 1;
+	uint8 m_ped_flagA10 : 1;	// set when A20 just changed?
 	uint8 m_ped_flagA20_look : 1;
 	uint8 m_ped_flagA40 : 1;
 	uint8 m_ped_flagA80 : 1;
@@ -114,7 +114,7 @@ public:
 	uint8 m_ped_flagC4 : 1;
 	uint8 m_ped_flagC8 : 1;
 	uint8 m_ped_flagC10 : 1;
-	uint8 m_ped_flagC20 : 1;
+	uint8 m_ped_flagC20 : 1;	// just left some body part?
 	uint8 m_ped_flagC40 : 1;
 	uint8 m_ped_flagC80 : 1;
 	uint8 m_ped_flagD1 : 1;
@@ -166,7 +166,7 @@ public:
 	uint8 m_ped_flagI40 : 1;
 	uint8 m_ped_flagI80 : 1;
 	uint8 stuff10[15];
-	int32 m_field_16C;
+	CPed *m_field_16C;
 	uint8 stuff12[44];
 	int32 m_pEventEntity;
 	float m_fAngleToEvent;
@@ -198,7 +198,10 @@ public:
 	CPathNode *m_pLastPathNode;
 	float m_fHealth;
 	float m_fArmour;
-	uint8 stuff2[34];
+	uint8 stuff2[20];
+	float m_fRotationCur;
+	float m_fRotationDest;
+	uint8 stuff13[6];
 	CEntity *m_pCurrentPhysSurface;
 	CVector m_vecOffsetFromPhysSurface;
 	CEntity *m_pCurSurface;
@@ -249,6 +252,7 @@ public:
 	void RemoveBodyPart(PedNode nodeId, int8 unknown);
 	void SpawnFlyingComponent(int, int8 unknown);
 	bool OurPedCanSeeThisOne(CEntity* who);
+	void Avoid(void);
 	static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data);
 	static RwFrame *RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data);
 

From 4ed6e86db155dfc147a4c6ec2d82686a38cb0e39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?eray=20or=C3=A7unus?= <erayorcunus@gmail.com>
Date: Tue, 18 Jun 2019 15:34:27 +0300
Subject: [PATCH 2/3] CPed fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: eray orçunus <erayorcunus@gmail.com>
---
 src/entities/Ped.cpp     | 49 ++++++++++++++++++----------------------
 src/entities/Ped.h       |  9 +++++---
 src/entities/PedIK.h     |  2 +-
 src/entities/PlayerPed.h |  2 +-
 4 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index b8236ecc..181ba5b7 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -339,7 +339,7 @@ CPed::SetLookFlag(CPed *to, bool set)
 		m_lookTimer = 0;
 		m_ped_flagA20_look = set;
 		if (m_nPedState != PED_DRIVING) {
-			m_pedIK.m_flags &= ~CPedIK::FLAG_4;
+			m_pedIK.m_flags &= ~CPedIK::FLAG_2;
 		}
 	}
 }
@@ -355,7 +355,7 @@ CPed::SetLookFlag(float angle, bool set)
 		m_lookTimer = 0;
 		m_ped_flagA20_look = set;
 		if (m_nPedState != PED_DRIVING) {
-			m_pedIK.m_flags &= ~CPedIK::FLAG_4;
+			m_pedIK.m_flags &= ~CPedIK::FLAG_2;
 		}
 	}
 }
@@ -371,8 +371,6 @@ CPed::SetLookTimer(int time)
 bool
 CPed::OurPedCanSeeThisOne(CEntity* who)
 {
-	float xDiff;
-	float yDiff;
 	float distance;
 	CColPoint colpoint;
 	CEntity* ent;
@@ -382,13 +380,15 @@ CPed::OurPedCanSeeThisOne(CEntity* who)
 	ourPos = this->GetPosition();
 	itsPos = who->GetPosition();
 
-	xDiff = itsPos.x - ourPos.x;
-	yDiff = itsPos.y - ourPos.y;
+	CVector2D posDiff(
+		itsPos.x - ourPos.x,
+		itsPos.y - ourPos.y
+	);
 
-	if ((yDiff * this->GetUp().y) + (xDiff * this->GetUp().x) < 0.0f)
+	if ((posDiff.y * this->GetForward().y) + (posDiff.x * this->GetForward().x) < 0.0f)
 		return 0;
 
-	distance = sqrt(yDiff * yDiff + xDiff * xDiff);
+	distance = posDiff.Magnitude();
 
 	if (distance < 40.0f)
 		return 0;
@@ -402,13 +402,8 @@ CPed::Avoid(void) {
 	int8 temper;
 	int moveState;
 	CPed* nearestPed;
-	float sinValue;
-	float cosValue;
-	float someRate;
-	float someY;
-	float someX;
-	float someDistance;
-	float simplifiedAngle;
+	float rate;
+	float distance;
 
 	temper = m_pedStats->m_temper;
 	if ((temper <= m_pedStats->m_fear || temper <= 50) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
@@ -422,24 +417,24 @@ CPed::Avoid(void) {
 					&& (CPedType::ms_apPedType[nearestPed->m_nPedType]->m_Type.IntValue
 						& CPedType::ms_apPedType[this->m_nPedType]->m_Avoid.IntValue)) {
 
-					simplifiedAngle = RADTODEG(m_fRotationCur) / RADTODEG(1);
-					sinValue = -sin(simplifiedAngle);
-					cosValue = cos(simplifiedAngle);
+					CVector2D pedAngleRatio(
+						cos(RADTODEG(m_fRotationCur) / RADTODEG(1)),
+						-sin(RADTODEG(m_fRotationCur) / RADTODEG(1))
+					);
 
 					// sin^2 + cos^2 must always return 1, and it does return... so what's the point?
-					someRate = 1.0f / sqrt(cosValue * cosValue + sinValue * sinValue);
+					rate = 1.0f / pedAngleRatio.Magnitude();
 
 					// 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.
-					someY = nearestPed->GetPosition().y
-						- (1.25 * (cosValue * someRate)
-							+ GetPosition().y);
-					someX = nearestPed->GetPosition().x
-						- (1.25 * (sinValue * someRate)
-							+ GetPosition().x);
-					someDistance = sqrt(someY * someY + someX * someX);
+					CVector2D walkedUpToPed(
+						nearestPed->GetPosition().x - (1.25 * (pedAngleRatio.y * rate) + GetPosition().x),
+						nearestPed->GetPosition().y - (1.25 * (pedAngleRatio.x * rate) + GetPosition().y)
+					);
 
-					if (someDistance <= 1.0f && CPed::OurPedCanSeeThisOne((CEntity*)nearestPed)) {
+					distance = walkedUpToPed.Magnitude();
+
+					if (distance <= 1.0f && CPed::OurPedCanSeeThisOne((CEntity*)nearestPed)) {
 						m_nPedStateTimer = CTimer::GetTimeInMilliseconds()
 							+ 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter())
 							% 1000 / 5;
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index 0249c707..7496ee67 100644
--- a/src/entities/Ped.h
+++ b/src/entities/Ped.h
@@ -95,7 +95,7 @@ public:
 	float m_fCollisionSpeed;
 	uint8 m_ped_flagA1 : 1;
 	uint8 m_ped_flagA2 : 1;
-	uint8 m_ped_flagA4 : 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 m_ped_flagA20_look : 1;
@@ -129,7 +129,7 @@ public:
 	uint8 m_ped_flagE2 : 1;
 	uint8 m_ped_flagE4 : 1;
 	uint8 m_ped_flagE8 : 1;
-	uint8 m_ped_flagE10 : 1;
+	uint8 m_ped_flagE10 : 1;	// can't attack if it's set
 	uint8 m_ped_flagE20 : 1;
 	uint8 m_ped_flagE40 : 1;
 	uint8 m_ped_flagE80 : 1;
@@ -228,7 +228,10 @@ public:
 	uint32 m_leaveCarTimer;
 	uint32 m_getUpTimer;
 	uint32 m_lookTimer;
-	uint8 stuff9[34];
+	uint32 m_standardTimer;
+	uint32 m_attackTimer;
+	uint32 m_lastHitTime;
+	uint8 stuff9[22];
 	uint8 m_bodyPartBleeding;
 	uint8 m_field_4F3;
 	CPed *m_nearPeds[10];
diff --git a/src/entities/PedIK.h b/src/entities/PedIK.h
index 67aaa469..266372c4 100644
--- a/src/entities/PedIK.h
+++ b/src/entities/PedIK.h
@@ -16,7 +16,7 @@ public:
 	enum {
 		FLAG_1,
 		FLAG_2,
-		FLAG_4,
+		FLAG_4,	// aims with arm
 	};
 
 	CPed* m_ped;
diff --git a/src/entities/PlayerPed.h b/src/entities/PlayerPed.h
index a41135e9..23e7dae5 100644
--- a/src/entities/PlayerPed.h
+++ b/src/entities/PlayerPed.h
@@ -19,7 +19,7 @@ public:
 	int32 m_nSpeedTimer;
 	int32 m_nShotDelay;
 	float field_1376;
-	int8 field_1380;
+	int8 field_1380;	// set if can't attack, why?
 	int8 field_1381;
 	int8 field_1382;
 	int8 field_1383;

From c9f6e7bf83dcef53f13de9e24fa9c6113cf1f0fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?eray=20or=C3=A7unus?= <erayorcunus@gmail.com>
Date: Tue, 18 Jun 2019 15:55:39 +0300
Subject: [PATCH 3/3] CPed merge fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: eray orçunus <erayorcunus@gmail.com>
---
 src/PedType.cpp         | 31 ---------------------
 src/PedType.h           | 61 -----------------------------------------
 src/control/PedType.cpp | 29 +++++++++++++++++++-
 src/control/PedType.h   | 61 +++++++++++++++++++++++++++++++++++++++--
 src/entities/Ped.cpp    | 20 ++++++--------
 src/entities/Ped.h      |  2 +-
 6 files changed, 96 insertions(+), 108 deletions(-)
 delete mode 100644 src/PedType.cpp
 delete mode 100644 src/PedType.h

diff --git a/src/PedType.cpp b/src/PedType.cpp
deleted file mode 100644
index 904b4f97..00000000
--- a/src/PedType.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "PedType.h"
-
-CPedType* (&CPedType::ms_apPedType)[23] = *(CPedType * (*)[23]) * (int*)0x941594;
-
-WRAPPER void CPedType::LoadPedData(void) { EAXJMP(0x4EE8D0); }
-
-void
-CPedType::Initialise()
-{
-	debug("Initialising CPedType...\n");
-	for(int i = 0; i < 23; i++) {
-		ms_apPedType[i] = new CPedType;
-		ms_apPedType[i]->m_Type.IntValue = 1;
-		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;
-	}
-	debug("Loading ped data...\n");
-	LoadPedData();
-	debug("CPedType ready\n");
-}
-
-STARTPATCHES
-	InjectHook(0x4EE7E0, &CPedType::Initialise, PATCH_JUMP);
-ENDPATCHES
\ No newline at end of file
diff --git a/src/PedType.h b/src/PedType.h
deleted file mode 100644
index 7b9e3096..00000000
--- a/src/PedType.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#pragma once
-
-#include "common.h"
-#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;
-	float field_4;
-	float field_8;
-	float field_C;
-	float field_10;
-	float field_14;
-	tPedTypeFlags m_Threat;
-	tPedTypeFlags m_Avoid;
-
-	static CPedType* (&ms_apPedType)[23];
-
-	static void Initialise();
-	static void LoadPedData();
-};
-
-static_assert(sizeof(CPedType) == 0x20, "CPedType: error");
\ No newline at end of file
diff --git a/src/control/PedType.cpp b/src/control/PedType.cpp
index 587aa815..b6d77cb0 100644
--- a/src/control/PedType.cpp
+++ b/src/control/PedType.cpp
@@ -2,4 +2,31 @@
 #include "patcher.h"
 #include "PedType.h"
 
-WRAPPER int32 CPedType::FindPedType(char *type) { EAXJMP(0x4EEC10); }
+CPedType* (&CPedType::ms_apPedType)[23] = *(CPedType * (*)[23]) * (int*)0x941594;
+
+WRAPPER void CPedType::LoadPedData(void) { EAXJMP(0x4EE8D0); }
+WRAPPER int32 CPedType::FindPedType(char* type) { EAXJMP(0x4EEC10); }
+
+void
+CPedType::Initialise()
+{
+	debug("Initialising CPedType...\n");
+	for (int i = 0; i < 23; i++) {
+		ms_apPedType[i] = new CPedType;
+		ms_apPedType[i]->m_Type.IntValue = 1;
+		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;
+	}
+	debug("Loading ped data...\n");
+	LoadPedData();
+	debug("CPedType ready\n");
+}
+
+STARTPATCHES
+	InjectHook(0x4EE7E0, &CPedType::Initialise, PATCH_JUMP);
+ENDPATCHES
\ No newline at end of file
diff --git a/src/control/PedType.h b/src/control/PedType.h
index 563dc294..1d1057d7 100644
--- a/src/control/PedType.h
+++ b/src/control/PedType.h
@@ -1,7 +1,62 @@
 #pragma once
 
-class CPedType
-{
+#include "common.h"
+#include "templates.h"
+#include "Lists.h"
+
+class CPedType {
 public:
-	static int32 FindPedType(char *type);
+	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;
+	float field_4;
+	float field_8;
+	float field_C;
+	float field_10;
+	float field_14;
+	tPedTypeFlags m_Threat;
+	tPedTypeFlags m_Avoid;
+
+	static CPedType* (&ms_apPedType)[23];
+
+	static void Initialise();
+	static void LoadPedData();
+	static int32 FindPedType(char* type);
 };
+
+static_assert(sizeof(CPedType) == 0x20, "CPedType: error");
\ No newline at end of file
diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index f6d9f4b2..12528b20 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -401,7 +401,7 @@ CPed::Avoid(void) {
 	int8 temper;
 	int moveState;
 	CPed* nearestPed;
-	float rate;
+	float walkAngle;
 	float distance;
 
 	temper = m_pedStats->m_temper;
@@ -416,19 +416,17 @@ CPed::Avoid(void) {
 					&& (CPedType::ms_apPedType[nearestPed->m_nPedType]->m_Type.IntValue
 						& CPedType::ms_apPedType[this->m_nPedType]->m_Avoid.IntValue)) {
 
-					CVector2D pedAngleRatio(
-						cos(RADTODEG(m_fRotationCur) / RADTODEG(1)),
-						-sin(RADTODEG(m_fRotationCur) / RADTODEG(1))
-					);
-
-					// sin^2 + cos^2 must always return 1, and it does return... so what's the point?
-					rate = 1.0f / pedAngleRatio.Magnitude();
-
 					// 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);
+
 					CVector2D walkedUpToPed(
-						nearestPed->GetPosition().x - (1.25 * (pedAngleRatio.y * rate) + GetPosition().x),
-						nearestPed->GetPosition().y - (1.25 * (pedAngleRatio.x * rate) + GetPosition().y)
+						nearestPed->GetPosition().x - (1.25 * -sin(walkAngle) + GetPosition().x),
+						nearestPed->GetPosition().y - (1.25 * cos(walkAngle) + GetPosition().y)
 					);
 
 					distance = walkedUpToPed.Magnitude();
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index 7496ee67..f9e46dae 100644
--- a/src/entities/Ped.h
+++ b/src/entities/Ped.h
@@ -3,10 +3,10 @@
 #include "Physical.h"
 #include "Weapon.h"
 #include "PedIK.h"
+#include "PedStats.h"
 #include "AnimManager.h"
 #include "AnimBlendClumpData.h"
 
-struct PedStat;
 struct CPathNode;
 
 enum {