summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/AnimViewer.cpp47
-rw-r--r--src/core/Stats.cpp2
-rw-r--r--src/core/Stats.h2
-rw-r--r--src/core/World.cpp6
-rw-r--r--src/core/config.h1
-rw-r--r--src/core/main.cpp3
-rw-r--r--src/modelinfo/PedModelInfo.cpp39
-rw-r--r--src/modelinfo/PedModelInfo.h1
-rw-r--r--src/objects/ParticleObject.cpp8
-rw-r--r--src/peds/Ped.cpp496
-rw-r--r--src/peds/Ped.h5
11 files changed, 595 insertions, 15 deletions
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp
index 30773889..86b22ec5 100644
--- a/src/core/AnimViewer.cpp
+++ b/src/core/AnimViewer.cpp
@@ -34,6 +34,8 @@
#include "Timecycle.h"
#include "RpAnimBlend.h"
#include "Shadows.h"
+#include "Radar.h"
+#include "Hud.h"
int CAnimViewer::animTxdSlot = 0;
CEntity *CAnimViewer::pTarget = nil;
@@ -70,7 +72,8 @@ CAnimViewer::Initialise(void) {
}
gbModelViewer = true;
-
+ CHud::m_Wants_To_Draw_Hud = false;
+
ThePaths.Init();
ThePaths.AllocatePathFindInfoMem(4500);
CCollision::Init();
@@ -90,6 +93,8 @@ CAnimViewer::Initialise(void) {
CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE);
CStreaming::LoadAllRequestedModels(false);
CRenderer::Init();
+ CRadar::Initialise();
+ CRadar::LoadTextures();
CVehicleModelInfo::LoadVehicleColours();
CAnimManager::LoadAnimFiles();
CWorld::PlayerInFocus = 0;
@@ -297,10 +302,15 @@ CAnimViewer::Update(void)
if (pad->NewState.LeftShoulder1 && !pad->OldState.LeftShoulder1) {
nextModelId = LastPedModelId(modelId);
+ AsciiToUnicode("Switched to peds", gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
} else {
// Start in mobile
- if (pad->NewState.Square && !pad->OldState.Square)
+ if (pad->NewState.Square && !pad->OldState.Square) {
CVehicleModelInfo::LoadVehicleColours();
+ AsciiToUnicode("Carcols.dat reloaded", gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
+ }
}
}
} else {
@@ -309,12 +319,18 @@ CAnimViewer::Update(void)
// Triangle in mobile
if (pad->NewState.Square && !pad->OldState.Square) {
reloadIFP = 1;
+ AsciiToUnicode("IFP reloaded", gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
} else if (pad->NewState.Cross && !pad->OldState.Cross) {
PlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId);
+ AsciiToUnicode("Animation restarted", gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
} else if (pad->NewState.Circle && !pad->OldState.Circle) {
PlayAnimation(pTarget->GetClump(), animGroup, ANIM_IDLE_STANCE);
+ AsciiToUnicode("Idle animation playing", gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
} else if (pad->NewState.DPadUp && pad->OldState.DPadUp == 0) {
animId--;
@@ -323,19 +339,33 @@ CAnimViewer::Update(void)
}
PlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId);
+ sprintf(gString, "Current anim: %d", animId);
+ AsciiToUnicode(gString, gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
+
} else if (pad->NewState.DPadDown && !pad->OldState.DPadDown) {
animId = (animId == (NUM_ANIMS - 1) ? 0 : animId + 1);
PlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId);
+ sprintf(gString, "Current anim: %d", animId);
+ AsciiToUnicode(gString, gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
+
} else {
if (pad->NewState.Start && !pad->OldState.Start) {
} else {
if (pad->NewState.LeftShoulder1 && !pad->OldState.LeftShoulder1) {
nextModelId = LastVehicleModelId(modelId);
+ AsciiToUnicode("Switched to vehicles", gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
} else {
-// if (CPad::GetPad(1)->NewState.LeftShoulder2)
-// CPedModelInfo::AnimatePedColModelSkinned(CModelInfo::ms_modelInfoPtrs[(pTarget + 96)], pTarget->GetClump()));
+ // Originally it was GetPad(1)->LeftShoulder2
+ if (pad->NewState.Triangle) {
+ CPedModelInfo::AnimatePedColModel(((CPedModelInfo*)CModelInfo::GetModelInfo(pTarget->m_modelIndex))->GetHitColModel(), RpClumpGetFrame(pTarget->GetClump()));
+ AsciiToUnicode("Ped Col model will be animated as long as you hold the button", gUString);
+ CMessages::AddMessage(gUString, 100, 0);
+ }
}
}
}
@@ -344,8 +374,17 @@ CAnimViewer::Update(void)
if (pad->NewState.DPadLeft && pad->OldState.DPadLeft == 0) {
nextModelId = FindMeAModelID(modelId, -1);
+
+ sprintf(gString, "Current model ID: %d", nextModelId);
+ AsciiToUnicode(gString, gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
+
} else if (pad->NewState.DPadRight && pad->OldState.DPadRight == 0) {
nextModelId = FindMeAModelID(modelId, 1);
+
+ sprintf(gString, "Current model ID: %d", nextModelId);
+ AsciiToUnicode(gString, gUString);
+ CMessages::AddMessage(gUString, 1000, 0);
}
// There were extra codes here to let us change model id by 50, but xbox CPad struct is different, so I couldn't port.
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 9d0e7df1..d4d91dac 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -2,7 +2,7 @@
#include "Stats.h"
int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
-int32 &CStats::HeadShots = *(int32*)0x8F647C;
+int32 &CStats::HeadsPopped = *(int32*)0x8F647C;
bool& CStats::CommercialPassed = *(bool*)0x8F4334;
bool& CStats::IndustrialPassed = *(bool*)0x8E2A68;
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 90db25e8..53c40ca3 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -4,7 +4,7 @@ class CStats
{
public:
static int32 &DaysPassed;
- static int32 &HeadShots;
+ static int32 &HeadsPopped;
static bool& CommercialPassed;
static bool& IndustrialPassed;
static int32 &NumberKillFrenziesPassed;
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 9c3aafcf..150e87d5 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -294,10 +294,14 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
if(e->IsPed()){
if(e->bUsesCollision ||
deadPeds && ((CPed*)e)->m_nPedState == PED_DEAD){
- if(((CPed*)e)->UseGroundColModel())
+ if (((CPed*)e)->UseGroundColModel())
colmodel = &CTempColModels::ms_colModelPedGroundHit;
else
+#ifdef ANIMATE_PED_COL_MODEL
+ colmodel = CPedModelInfo::AnimatePedColModel(((CPedModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->GetHitColModel(), RpClumpGetFrame(e->GetClump()));
+#else
colmodel = ((CPedModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->GetHitColModel();
+#endif
}else
colmodel = nil;
}else if(e->bUsesCollision)
diff --git a/src/core/config.h b/src/core/config.h
index 8eda6187..de89f7c3 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -130,3 +130,4 @@ enum Config {
#define ASPECT_RATIO_SCALE
#define USE_DEBUG_SCRIPT_LOADER
#define EXPLODING_AIRTRAIN // can blow up jumbo jet with rocket launcher
+#define ANIMATE_PED_COL_MODEL
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 7d60291c..50494ef3 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -121,9 +121,12 @@ TheModelViewer(void)
CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
255);
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
DefinedState();
CVisibilityPlugins::InitAlphaEntityList();
CAnimViewer::Render();
+ Render2dStuff();
DoRWStuffEndOfFrame();
}
#endif
diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp
index c5242ef6..afe177c2 100644
--- a/src/modelinfo/PedModelInfo.cpp
+++ b/src/modelinfo/PedModelInfo.cpp
@@ -189,6 +189,45 @@ CPedModelInfo::CreateHitColModel(void)
m_hitColModel = colmodel;
}
+CColModel*
+CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame)
+{
+ RwObjectNameAssociation nameAssoc;
+ RwObjectIdAssociation idAssoc;
+ RwMatrix* mat = RwMatrixCreate();
+ CColSphere* spheres = colmodel->spheres;
+
+ for (int i = 0; i < NUMPEDINFONODES; i++) {
+ RwFrame* f = nil;
+ if (m_pColNodeInfos[i].name) {
+ nameAssoc.name = m_pColNodeInfos[i].name;
+ nameAssoc.frame = nil;
+ RwFrameForAllChildren(frame, FindFrameFromNameCB, &nameAssoc);
+ f = nameAssoc.frame;
+ }
+ else {
+ idAssoc.id = m_pColNodeInfos[i].pedNode;
+ idAssoc.frame = nil;
+ RwFrameForAllChildren(frame, FindFrameFromIdCB, &idAssoc);
+ f = idAssoc.frame;
+ }
+ if (f) {
+ RwMatrixCopy(mat, RwFrameGetMatrix(f));
+
+ for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) {
+ RwMatrixTransform(mat, &f->modelling, rwCOMBINEPOSTCONCAT);
+ if (RwFrameGetParent(f) == frame)
+ break;
+ }
+
+ spheres[i].center.x = mat->pos.x + m_pColNodeInfos[i].x;
+ spheres[i].center.y = mat->pos.y + 0.0f;
+ spheres[i].center.z = mat->pos.z + m_pColNodeInfos[i].z;
+ }
+ }
+
+ return colmodel;
+}
class CPedModelInfo_ : public CPedModelInfo
{
diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h
index 483d13f8..a2d58d6e 100644
--- a/src/modelinfo/PedModelInfo.h
+++ b/src/modelinfo/PedModelInfo.h
@@ -39,5 +39,6 @@ public:
void SetLowDetailClump(RpClump*);
void CreateHitColModel(void);
CColModel *GetHitColModel(void) { return m_hitColModel; }
+ static CColModel *AnimatePedColModel(CColModel* colmodel, RwFrame* frame);
};
static_assert(sizeof(CPedModelInfo) == 0x54, "CPedModelInfo: error");
diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp
index 32d305c6..2171cd76 100644
--- a/src/objects/ParticleObject.cpp
+++ b/src/objects/ParticleObject.cpp
@@ -442,13 +442,13 @@ void CParticleObject::UpdateClose(void)
{
this->m_nFrameCounter = 0;
- int32 randVal; // BUG: unitialised can be used ??!!
+ int32 randVal;
if ( this->m_nCreationChance != 0 )
randVal = CGeneral::GetRandomNumber() % this->m_nCreationChance;
- if ( randVal != 0 && this->m_nCreationChance > 0
- || randVal == 0 && (this->m_nCreationChance & 128) != 0
- || this->m_nCreationChance == 0 )
+ if ( this->m_nCreationChance == 0
+ || randVal == 0 && this->m_nCreationChance < 0
+ || randVal != 0 && this->m_nCreationChance > 0)
{
switch ( this->m_Type )
{
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 7fcd6525..51781569 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -39,7 +39,6 @@
#include "Font.h"
#include "Text.h"
-WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); }
WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); }
@@ -782,7 +781,7 @@ CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
);
if (!CPed::IsPlayer() || evenOnPlayer) {
- ++CStats::HeadShots;
+ ++CStats::HeadsPopped;
// BUG: This condition will always return true.
if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {
@@ -4367,7 +4366,7 @@ CPed::SetAttack(CEntity* victim)
bIsAttacking = false;
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
animAssoc->SetRun();
- if (animAssoc->currentTime != animAssoc->hierarchy->totalLength)
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
animAssoc->SetCurrentTime(0.0f);
animAssoc->SetFinishCallback(FinishedAttackCB, this);
@@ -4668,12 +4667,19 @@ CPed::FightStrike(CVector &touchedNodePos)
// He can beat us
if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
- ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
+
if (nearPed->m_nPedState == PED_FALL
|| nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE
|| !nearPed->IsPedHeadAbovePos(-0.3f)) {
ourCol = &CTempColModels::ms_colModelPedGroundHit;
+ } else {
+#ifdef ANIMATE_PED_COL_MODEL
+ ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel(), RpClumpGetFrame(GetClump()));
+#else
+ ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
+#endif
}
+
for (int j = 0; j < ourCol->numSpheres; j++) {
attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
attackDistance -= touchedNodePos;
@@ -7723,6 +7729,484 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
}
}
+void
+CPed::InvestigateEvent(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId animToPlay;
+ AssocGroupId animGroup;
+
+ if (m_nWaitState == WAITSTATE_TURN180)
+ return;
+
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+
+ if (m_standardTimer) {
+ if (m_eventType < EVENT_ASSAULT_NASTYWEAPON)
+ SetWaitState(WAITSTATE_TURN180, nil);
+
+ m_standardTimer = 0;
+ } else {
+ ClearInvestigateEvent();
+ }
+ return;
+ }
+
+ CVector2D vecDist = m_eventOrThreat - GetPosition();
+ float distSqr = vecDist.MagnitudeSqr();
+ if (sq(m_distanceToCountSeekDone) >= distSqr) {
+
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f);
+ SetMoveState(PEDMOVE_STILL);
+
+ switch (m_eventType) {
+ case EVENT_DEAD_PED:
+ case EVENT_HIT_AND_RUN:
+ case EVENT_HIT_AND_RUN_COP:
+
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (m_pEventEntity)
+ SetLookFlag(m_pEventEntity, 1);
+
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
+
+ } else if (CGeneral::GetRandomNumber() & 3) {
+ ClearLookFlag();
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
+
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ Say(SOUND_PED_CHAT_EVENT);
+
+ } else {
+ ClearInvestigateEvent();
+ }
+ }
+ break;
+ case EVENT_FIRE:
+ case EVENT_EXPLOSION:
+
+ if (m_ped_flagD1 && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+
+ if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 14.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else if (CGeneral::GetRandomNumber() & 3) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));
+ Say(SOUND_PED_CHAT_EVENT);
+
+ } else {
+ m_standardTimer = 0;
+ }
+
+ } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+
+ if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) {
+ if (CGeneral::GetRandomNumber() & 1)
+ animToPlay = ANIM_IDLE_HBHB;
+ else
+ animToPlay = ANIM_XPRESS_SCRATCH;
+
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (CGeneral::GetRandomNumber() & 1) {
+ animToPlay = ANIM_IDLE_STANCE;
+ animGroup = m_animGroup;
+ } else {
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ animGroup = ASSOCGRP_STD;
+ }
+
+ CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else {
+ if (CGeneral::GetRandomNumber() & 1) {
+ animToPlay = ANIM_IDLE_STANCE;
+ animGroup = m_animGroup;
+ } else {
+ animToPlay = ANIM_IDLE_HBHB;
+ animGroup = ASSOCGRP_STD;
+ }
+
+ CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ }
+ Say(SOUND_PED_CHAT_EVENT);
+ }
+ break;
+ case EVENT_ASSAULT_NASTYWEAPON_POLICE:
+ case EVENT_ATM:
+
+ m_fRotationDest = m_fAngleToEvent;
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+
+ if (m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (m_eventType == EVENT_ASSAULT_NASTYWEAPON_POLICE)
+ animToPlay = ANIM_IDLE_CHAT;
+ else
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ClearInvestigateEvent();
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ ClearInvestigateEvent();
+ }
+ }
+ } else {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ } else {
+ m_vecSeekPos.x = m_eventOrThreat.x;
+ m_vecSeekPos.y = m_eventOrThreat.y;
+ m_vecSeekPos.z = GetPosition().z;
+ Seek();
+
+ if (m_eventType < EVENT_ASSAULT_NASTYWEAPON_POLICE) {
+ if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {
+ SetMoveState(PEDMOVE_RUN);
+ return;
+ }
+ }
+ if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_ATM) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+ if (distSqr > 1.44f) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < 0.16f) {
+ SetMoveState(PEDMOVE_STILL);
+ return;
+ }
+ }
+
+ SetMoveState(PEDMOVE_WALK);
+ }
+}
+
+bool
+CPed::IsPedDoingDriveByShooting(void)
+{
+ if (this == FindPlayerPed() && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
+ return true;
+ }
+ return false;
+}
+
+bool
+CPed::IsPedShootable(void)
+{
+ return m_nPedState <= PED_STATES_NO_ST;
+}
+
+bool
+CPed::IsRoomToBeCarJacked(void)
+{
+ if (!m_pMyVehicle)
+ return false;
+
+ CVector2D offset;
+ if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) {
+ offset = vecPedDraggedOutCarAnimOffset;
+ } else {
+ offset = vecPedQuickDraggedOutCarAnimOffset;
+ }
+
+ CVector doorPos(offset.x, offset.y, 0.0f);
+ if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &doorPos)) {
+ return true;
+ }
+
+ return false;
+}
+
+void
+CPed::KillPedWithCar(CVehicle* car, float impulse)
+{
+ CVehicleModelInfo* vehModel;
+ CColModel* vehColModel;
+ uint8 damageDir;
+ PedNode nodeToDamage;
+ eWeaponType killMethod;
+
+ if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {
+ if (!this->m_pCollidingEntity || car->m_status == STATUS_PLAYER)
+ this->m_pCollidingEntity = car;
+ return;
+ }
+
+ if (m_nPedState == PED_DEAD)
+ return;
+
+ if (m_pCurSurface) {
+ if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer()))
+ return;
+ }
+ CVector distVec = GetPosition() - car->GetPosition();
+
+ if ((impulse > 12.0f || car->m_modelIndex == MI_TRAIN) && !IsPlayer()) {
+ nodeToDamage = PED_TORSO;
+ killMethod = WEAPONTYPE_RAMMEDBYCAR;
+ uint8 randVal = CGeneral::GetRandomNumber() & 3;
+
+ if (car == FindPlayerVehicle()) {
+ float carSpeed = car->m_vecMoveSpeed.Magnitude();
+ uint8 shakeFreq;
+ if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) {
+ shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f;
+ } else {
+ shakeFreq = 250.0f;
+ }
+ CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);
+ }
+ bIsStanding = false;
+ damageDir = CPed::GetLocalDirection(-m_vecMoveSpeed);
+ vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(car->m_modelIndex);
+ vehColModel = vehModel->GetColModel();
+ float carRightAndDistDotProd = DotProduct(distVec, car->GetRight());
+
+ if (car->m_modelIndex == MI_TRAIN) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ nodeToDamage = PED_HEAD;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ // Car doesn't look to us
+ } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){
+
+ if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) {
+
+ // We're at the right of the car
+ if (carRightAndDistDotProd <= 0.0f)
+ nodeToDamage = PED_UPPERARML;
+ else
+ nodeToDamage = PED_UPPERARMR;
+
+ if (fabs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ }
+ } else {
+ float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());
+
+ // carFrontAndDistDotProd <= 0.0 car looks to us
+ if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ nodeToDamage = PED_HEAD;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ } else {
+ nodeToDamage = PED_MID;
+ float vehColMaxY = vehColModel->boundingBox.max.y;
+ float vehColMinY = vehColModel->boundingBox.min.y;
+ float vehColMaxZ = vehColModel->boundingBox.max.z;
+ float carFrontZ = car->GetForward().z;
+
+ // Col. Z of where?
+ float carColZ;
+
+ // TODO: Figure out what these codes do
+ float unk1, unk2;
+
+ if (carFrontZ < -0.2f) {
+ carColZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
+ unk1 = vehColMaxY - vehColMinY;
+
+ } else if (carFrontZ > 0.1f) {
+ carColZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ float colZDist = carColZ - GetPosition().z;
+ if (colZDist > 0.0f) {
+ GetPosition().z += 0.5f * colZDist;
+ carColZ += colZDist * 0.25f;
+ }
+ unk1 = vehColMaxY;
+
+ } else {
+ carColZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ unk1 = vehColMaxY;
+ }
+
+ unk2 = (carColZ - GetPosition().z) / (unk1 / car->m_vecMoveSpeed.Magnitude());
+ float moveForce = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * unk2;
+
+ // After this point, distVec isn't distVec anymore.
+ distVec = car->m_vecMoveSpeed;
+ distVec.Normalise();
+ distVec *= 0.2 * moveForce;
+
+ if (damageDir != 1 && damageDir != 3)
+ distVec.z += moveForce;
+ else
+ distVec.z += 1.5f * moveForce;
+
+ m_vecMoveSpeed = distVec;
+ damageDir += 2;
+ if (damageDir > 3)
+ damageDir = damageDir - 4;
+
+ if (car->m_vehType == VEHICLE_TYPE_CAR) {
+ CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
+
+ if (bonnet) {
+ if (rand() & 1) {
+ bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));
+ } else {
+ bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));
+ }
+ CVector forceDir = car->GetUp() * 10.0f;
+ bonnet->ApplyTurnForce(forceDir, car->GetForward());
+ }
+ }
+ }
+ }
+ }
+
+ if (car->pDriver) {
+ CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000);
+ }
+
+ ePedPieceTypes pieceToDamage;
+ switch (nodeToDamage) {
+ case PED_HEAD:
+ pieceToDamage = PEDPIECE_HEAD;
+ break;
+ case PED_UPPERARML:
+ pieceToDamage = PEDPIECE_LEFTARM;
+ break;
+ case PED_UPPERARMR:
+ pieceToDamage = PEDPIECE_RIGHTARM;
+ break;
+ default:
+ pieceToDamage = PEDPIECE_MID;
+ break;
+ }
+ CPed::InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);
+
+ if ((m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
+ && bIsPedDieAnimPlaying
+ && !m_pCollidingEntity) {
+ m_pCollidingEntity = car;
+ }
+ if (nodeToDamage == PED_MID)
+ m_ped_flagH1 = true;
+ else
+ m_ped_flagH1 = false;
+
+ distVec.Normalise();
+ car->ApplyMoveForce(distVec * -100.0f);
+
+ } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f
+ || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {
+
+ bIsStanding = false;
+ uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed);
+ float damage;
+ if (IsPlayer() && car->m_modelIndex == MI_TRAIN)
+ damage = 150.0f;
+ else
+ damage = 30.0f;
+
+ CPed::InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);
+ CPed::SetFall(1000, (AnimationId)(fallDirection + 25), true);
+
+ // float ok
+ if ((m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
+ && !m_pCollidingEntity
+ && (!IsPlayer() || m_ped_flagD2 || car->m_modelIndex == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
+
+ m_pCollidingEntity = car;
+ }
+
+ m_ped_flagH1 = false;
+ if (car->m_modelIndex != MI_TRAIN && !m_ped_flagD2) {
+ m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f;
+ }
+ m_vecMoveSpeed.z = 0.0f;
+ distVec.Normalise();
+ car->ApplyMoveForce(distVec * -60.0f);
+ }
+
+ Say(SOUND_PED_DEFEND);
+#ifdef FIX_BUGS
+ // Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
+ if (IsGangMember()) {
+ CPed *driver = car->pDriver;
+ if (driver && driver->IsPlayer()) {
+ RegisterThreatWithGangPeds(driver);
+ }
+ }
+#endif
+}
+
+void
+CPed::Look(void)
+{
+ // UNUSED: This is a perfectly empty function.
+}
+
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); }
@@ -7901,4 +8385,8 @@ STARTPATCHES
InjectHook(0x4D0D10, &CPed::InTheAir, PATCH_JUMP);
InjectHook(0x4C5270, &CPed::Initialise, PATCH_JUMP);
InjectHook(0x4D0E40, &CPed::SetLanding, PATCH_JUMP);
+ InjectHook(0x4E9B50, &CPed::InvestigateEvent, PATCH_JUMP);
+ InjectHook(0x564BB0, &CPed::IsPedDoingDriveByShooting, PATCH_JUMP);
+ InjectHook(0x4E4D90, &CPed::IsRoomToBeCarJacked, PATCH_JUMP);
+ InjectHook(0x4EC430, &CPed::KillPedWithCar, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 3085f74d..96767ce1 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -618,6 +618,9 @@ public:
void Idle(void);
void InTheAir(void);
void SetLanding(void);
+ void InvestigateEvent(void);
+ bool IsPedDoingDriveByShooting(void);
+ bool IsRoomToBeCarJacked(void);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
@@ -681,6 +684,8 @@ public:
void EnterTrain(void);
void ExitTrain(void);
void Fall(void);
+ bool IsPedShootable(void);
+ void Look(void);
bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }