summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/re3.cpp1
-rw-r--r--src/math/Vector2D.h13
-rw-r--r--src/peds/Ped.cpp381
-rw-r--r--src/peds/Ped.h14
-rw-r--r--src/vehicles/Automobile.cpp6
5 files changed, 387 insertions, 28 deletions
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 62e9a040..d6bc8148 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -354,6 +354,7 @@ DebugMenuPopulate(void)
#ifndef MASTER
DebugMenuAddVarBool8("Debug", "Toggle unused fight feature", (int8*)&CPed::bUnusedFightThingOnPlayer, nil);
DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil);
+ DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil);
#endif
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h
index a090155c..1e4d698f 100644
--- a/src/math/Vector2D.h
+++ b/src/math/Vector2D.h
@@ -49,9 +49,6 @@ public:
CVector2D operator+(const CVector2D &rhs) const {
return CVector2D(x+rhs.x, y+rhs.y);
}
- CVector2D operator*(float t) const {
- return CVector2D(x*t, y*t);
- }
CVector2D operator/(float t) const {
return CVector2D(x/t, y/t);
}
@@ -91,3 +88,13 @@ NormalizeXY(float &x, float &y)
}else
x = 1.0f;
}
+
+inline CVector2D operator*(const CVector2D &left, float right)
+{
+ return CVector2D(left.x * right, left.y * right);
+}
+
+inline CVector2D operator*(float left, const CVector2D &right)
+{
+ return CVector2D(left * right.x, left * right.y);
+}
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 494b37d1..4e64c1db 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -49,16 +49,12 @@
#include "ParticleObject.h"
#include "Floater.h"
-WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
-WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); }
-WRAPPER void CPed::UpdatePosition(void) { EAXJMP(0x4C7A00); }
WRAPPER void CPed::WanderPath(void) { EAXJMP(0x4D28D0); }
WRAPPER void CPed::SetEnterCar_AllClear(CVehicle*, uint32, uint32) { EAXJMP(0x4E0A40); }
WRAPPER bool CPed::WarpPedToNearEntityOffScreen(CEntity*) { EAXJMP(0x4E5570); }
WRAPPER void CPed::SetObjective(eObjective, CVector) { EAXJMP(0x4D8A90); }
WRAPPER void CPed::SetObjective(eObjective, CVector, float) { EAXJMP(0x4D8770); }
-WRAPPER void CPed::WarpPedIntoCar(CVehicle*) { EAXJMP(0x4D7D20); }
WRAPPER void CPed::SetCarJack(CVehicle*) { EAXJMP(0x4E0220); }
WRAPPER void CPed::WarpPedToNearLeaderOffScreen(void) { EAXJMP(0x4E52A0); }
@@ -78,6 +74,8 @@ CPedAudioData (&CPed::CommentWaitTime)[38] = *(CPedAudioData(*)[38]) * (uintptr*
uint16 nPlayerInComboMove;
+RpClump *flyingClumpTemp;
+
// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat.
FightMove tFightMoves[NUM_FIGHTMOVES] = {
{NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
@@ -286,6 +284,7 @@ static char WaitStateText[][16] = {
#ifndef MASTER
int nDisplayDebugInfo = 0;
bool CPed::bUnusedFightThingOnPlayer = false;
+bool CPed::bPopHeadsOnHeadshot = false;
void
CPed::SwitchDebugDisplay(void)
@@ -878,7 +877,11 @@ CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
frame = GetNodeFrame(nodeId);
if (frame) {
if (CGame::nastyGame) {
+#ifndef MASTER
+ if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
+#else
if (nodeId != PED_HEAD)
+#endif
SpawnFlyingComponent(nodeId, direction);
RecurseFrameChildrenVisibilityCB(frame, nil);
@@ -1852,11 +1855,11 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
// Getting out
if (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) {
- float pedZSpeedOnExit = m_vecMoveSpeed.z - 0.008f * CTimer::GetTimeStep();
+ float nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep();
// If we're not in ground at next step, apply animation
- if (neededPos.z + pedZSpeedOnExit >= autoZPos.z) {
- m_vecMoveSpeed.z = pedZSpeedOnExit;
+ if (neededPos.z + nextZSpeed >= autoZPos.z) {
+ m_vecMoveSpeed.z = nextZSpeed;
ApplyMoveSpeed();
// Removing below line breaks the animation
neededPos.z = GetPosition().z;
@@ -6893,8 +6896,8 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
}
#ifdef VC_PED_PORTS
if (ped->m_pCurrentPhysSurface) {
- ped->m_vecMoveSpeed.x += ((CPhysical*)ped->m_pCurrentPhysSurface)->m_vecMoveSpeed.x;
- ped->m_vecMoveSpeed.y += ((CPhysical*)ped->m_pCurrentPhysSurface)->m_vecMoveSpeed.y;
+ ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;
+ ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;
}
#endif
}
@@ -8330,8 +8333,7 @@ CPed::InvestigateEvent(void)
bool
CPed::IsPedDoingDriveByShooting(void)
{
- if (this == FindPlayerPed() && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
-
+ if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
return true;
}
@@ -13638,7 +13640,7 @@ LocalPosForWalkAround(CVector2D colMin, CVector2D colMax, int walkAround, uint32
bool
CanWeSeeTheCorner(CVector2D dist, CVector2D fwdOffset)
{
- // because if dist is more then 5 unit, fov isn't important, we want shortest way
+ // because fov isn't important if dist is more then 5 unit, we want shortest way
if (dist.Magnitude() > 5.0f)
return true;
@@ -13769,6 +13771,7 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
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;
@@ -13796,6 +13799,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
cornerToGo = tl;
m_walkAroundType = 1;
+
+ if (m_vehEnterType == CAR_DOOR_LR)
+ iWouldPreferGoingBack = 1;
} else if(CanWeSeeTheCorner(tl, GetForward())){
cornerToGo = tl;
dirToGo = GetLocalDirection(tl);
@@ -13831,6 +13837,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
cornerToGo = tr;
m_walkAroundType = 2;
+
+ if (m_vehEnterType == CAR_DOOR_RR)
+ iWouldPreferGoingBack = 2;
} else if (CanWeSeeTheCorner(tr, GetForward())) {
cornerToGo = tr;
dirToGo = GetLocalDirection(tr);
@@ -13863,7 +13872,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
#ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector br = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMin.y, 0.0f) - GetPosition();
- if (br.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ if (iWouldPreferGoingBack == 2)
+ m_walkAroundType = 4;
+ else if (br.Magnitude2D() < cornerToGo.Magnitude2D()) {
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) {
cornerToGo = br;
m_walkAroundType = 5;
@@ -13899,7 +13910,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
#ifdef NEW_WALK_AROUND_ALGORITHM
else {
CVector bl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMin.y, 0.0f) - GetPosition();
- if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) {
+ if (iWouldPreferGoingBack == 1)
+ m_walkAroundType = 7;
+ else if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) {
if (goingToEnterCar && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) {
cornerToGo = bl;
m_walkAroundType = 6;
@@ -14300,7 +14313,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
m_ped_flagH10 = false;
bOnBoat = false;
} else {
- m_pCurrentPhysSurface = collidingEnt;
+ m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);
m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();
m_pCurSurface = collidingEnt;
@@ -14505,7 +14518,7 @@ CPed::WillChat(CPed *stranger)
}
if (m_nSurfaceTouched == SURFACE_TARMAC)
return false;
- if (this == stranger)
+ if (stranger == this)
return false;
if (m_nPedType == stranger->m_nPedType)
return true;
@@ -14784,7 +14797,7 @@ CPed::ProcessBuoyancy(void)
float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f);
#endif
- if (mod_Buoyancy.ProcessBuoyancy(this, 0.008f * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
+ if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
m_flagD8 = true;
CEntity *entity;
CColPoint point;
@@ -16209,6 +16222,338 @@ CPed::UpdateFromLeader(void)
}
}
+void
+CPed::UpdatePosition(void)
+{
+ if (CReplay::IsPlayingBack() || !bIsStanding)
+ return;
+
+ CVector2D velocityChange;
+
+ SetHeading(m_fRotationCur);
+ if (m_pCurrentPhysSurface) {
+ CVector2D velocityOfSurface;
+ CPhysical *curSurface = m_pCurrentPhysSurface;
+ if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
+
+ // It seems R* didn't like m_vecOffsetFromPhysSurface for boats
+ CVector offsetToSurface = GetPosition() - curSurface->GetPosition();
+ offsetToSurface.z -= FEET_OFFSET;
+
+ CVector surfaceMoveVelocity = curSurface->m_vecMoveSpeed;
+ CVector surfaceTurnVelocity = CrossProduct(curSurface->m_vecTurnSpeed, offsetToSurface);
+
+ // Also we use that weird formula instead of friction if it's boat
+ float slideMult = -curSurface->m_vecTurnSpeed.MagnitudeSqr();
+ velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);
+ m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);
+ } else {
+ velocityOfSurface = curSurface->GetSpeed(m_vecOffsetFromPhysSurface);
+ }
+ // Reminder: m_moved is displacement from walking/running.
+ velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;
+ m_fRotationCur += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ m_fRotationDest += curSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ } else if (m_nSurfaceTouched != SURFACE_STONE || m_vecDamageNormal.x == 0.0f && m_vecDamageNormal.y == 0.0f) {
+ velocityChange = m_moved - m_vecMoveSpeed;
+ } else {
+ // Ped got damaged by steep slope
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
+ // some kind of
+ CVector2D reactionForce = m_vecDamageNormal * (1.0f / m_vecDamageNormal.Magnitude2D());
+
+ velocityChange = 0.02f * reactionForce + m_moved;
+
+ float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);
+ // they're in same direction
+ if (reactionAndVelocityDotProd < 0.0f) {
+ velocityChange -= reactionAndVelocityDotProd * reactionForce;
+ }
+ }
+
+ // Take time step into account
+ if (m_pCurrentPhysSurface) {
+ float speedChange = velocityChange.Magnitude();
+ float changeMult = speedChange;
+ if (m_nPedState != PED_DIE || !m_pCurrentPhysSurface->IsVehicle()) {
+ if (!m_pCurrentPhysSurface->IsVehicle() || !((CVehicle*)m_pCurrentPhysSurface)->IsBoat())
+ changeMult = 0.01f * CTimer::GetTimeStep();
+ } else {
+ changeMult = 0.002f * CTimer::GetTimeStep();
+ }
+
+ if (speedChange > changeMult) {
+ velocityChange = velocityChange * (changeMult / speedChange);
+ }
+ }
+ m_vecMoveSpeed.x += velocityChange.x;
+ m_vecMoveSpeed.y += velocityChange.y;
+}
+
+void
+CPed::SetPedPositionInCar(void)
+{
+ if (CReplay::IsPlayingBack())
+ return;
+
+ 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;
+ }
+ }
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pMyVehicle->m_modelIndex);
+ CMatrix newMat(m_pMyVehicle->GetMatrix());
+ CVector seatPos;
+ if (m_pMyVehicle->pDriver == this) {
+ if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
+ seatPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ else
+ seatPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+
+ if (!m_pMyVehicle->IsBoat() && m_pMyVehicle->m_vehType != VEHICLE_TYPE_BIKE)
+ seatPos.x = -seatPos.x;
+
+ } else if (m_pMyVehicle->pPassengers[0] == this) {
+ if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
+ seatPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ else
+ seatPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+ } 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];
+ } else if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) {
+ seatPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ } else {
+ seatPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+ }
+ }
+ newMat.GetPosition() += Multiply3x3(newMat, seatPos);
+ // Already done below (SetTranslate(0.0f, 0.0f, 0.0f))
+ // tempMat.SetUnity();
+
+ // 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 = HALFPI + m_pMyVehicle->GetForward().Heading();
+ tempMat.SetTranslate(0.0f, 0.0f, 0.0f);
+ tempMat.RotateZ(HALFPI);
+ newMat = newMat * tempMat;
+ } else {
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading();
+ }
+ } else {
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading();
+ }
+ GetMatrix() = newMat;
+}
+
+static RwObject*
+CloneAtomicToFrameCB(RwObject *frame, void *data)
+{
+ RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);
+ RpAtomicSetFrame(newAtomic, (RwFrame*)data);
+ RpClumpAddAtomic(flyingClumpTemp, newAtomic);
+ CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);
+ return frame;
+}
+
+static RwFrame*
+RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)
+{
+ RwFrame *newFrame = RwFrameCreate();
+ RwFrameAddChild((RwFrame*)data, newFrame);
+ RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);
+ RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);
+ RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);
+ return newFrame;
+}
+
+CObject*
+CPed::SpawnFlyingComponent(int pedNode, int8 direction)
+{
+ if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
+ return nil;
+
+ CObject *obj = new CObject();
+ if (!obj)
+ return nil;
+
+ RwFrame *frame = RwFrameCreate();
+ RpClump *clump = RpClumpCreate();
+ RpClumpSetFrame(clump, frame);
+ RwMatrix *matrix = RwFrameGetLTM(GetNodeFrame(pedNode));
+ *RwFrameGetMatrix(frame) = *matrix;
+
+ flyingClumpTemp = clump;
+ RwFrameForAllObjects(GetNodeFrame(pedNode), CloneAtomicToFrameCB, frame);
+ RwFrameForAllChildren(GetNodeFrame(pedNode), RecurseFrameChildrenToCloneCB, frame);
+ flyingClumpTemp = nil;
+ switch (pedNode) {
+ case PED_HEAD:
+ // So popping head would have wheel collision. They disabled it anyway
+ obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
+ break;
+ case PED_UPPERARML:
+ case PED_UPPERARMR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTB);
+ obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
+ break;
+ case PED_UPPERLEGL:
+ case PED_UPPERLEGR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTA);
+ obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
+ break;
+ default:
+ break;
+ }
+ obj->RefModelInfo(m_modelIndex);
+ obj->AttachToRwObject((RwObject*)clump);
+ obj->m_fMass = 15.0f;
+ obj->m_fTurnMass = 5.0f;
+ obj->m_fAirResistance = 0.99f;
+ obj->m_fElasticity = 0.03f;
+ obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
+ obj->ObjectCreatedBy = TEMP_OBJECT;
+ obj->bIsStatic = false;
+ obj->bIsPickup = false;
+ obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SPLIT_MODEL;
+
+ // life time - the more objects the are, the shorter this one will live
+ CObject::nNoTempObjects++;
+ if (CObject::nNoTempObjects > 20)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
+ else if (CObject::nNoTempObjects > 10)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
+ else
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
+
+ CVector localForcePos, forceDir;
+
+ if (direction == 2) {
+ obj->m_vecMoveSpeed = 0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = GetForward();
+ } else {
+ obj->m_vecMoveSpeed = -0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = -GetForward();
+ }
+ obj->ApplyTurnForce(forceDir, localForcePos);
+ CWorld::Add(obj);
+
+ return obj;
+}
+
+void
+CPed::WarpPedIntoCar(CVehicle *car)
+{
+ bInVehicle = true;
+ m_pMyVehicle = car;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_carInObjective = car;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_nPedState = PED_DRIVING;
+ bUsesCollision = false;
+ bIsInTheAir = false;
+ m_ped_flagI4 = true;
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ car->SetDriver(this);
+ car->pDriver->RegisterReference((CEntity **) &car->pDriver);
+
+ } 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
+ return;
+
+ if (IsPlayer()) {
+ car->m_status = STATUS_PLAYER;
+ AudioManager.PlayerJustGotInCar();
+ CCarCtrl::RegisterVehicleOfInterest(car);
+ } else {
+ car->m_status = STATUS_PHYSICS;
+ }
+
+ CWorld::Remove(this);
+ GetPosition() = car->GetPosition();
+ CWorld::Add(this);
+
+ if (car->bIsAmbulanceOnDuty) {
+ car->bIsAmbulanceOnDuty = false;
+ --CCarCtrl::NumAmbulancesOnDuty;
+ }
+ 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);
+ }
+ if (car->IsBoat()) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ } else {
+
+ // Because we can use Uzi for drive by
+ // RemoveWeaponWhenEnteringVehicle in VC
+ if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
+ if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
+ m_storedWeapon = GetWeapon()->m_eWeaponType;
+ SetCurrentWeapon(WEAPONTYPE_UZI);
+ } else {
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ }
+
+ 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);
+ }
+ StopNonPartialAnims();
+ if (car->bIsBus)
+ bRenderPedInCar = false;
+
+ bChangedSeat = true;
+}
+
class CPed_ : public CPed
{
public:
@@ -16430,4 +16775,6 @@ STARTPATCHES
InjectHook(0x4E5870, &CPed::ServiceTalking, PATCH_JUMP);
InjectHook(0x4E7780, &CPed::StartFightDefend, PATCH_JUMP);
InjectHook(0x4D8F30, &CPed::UpdateFromLeader, PATCH_JUMP);
+ InjectHook(0x4D4970, &CPed::SetPedPositionInCar, PATCH_JUMP);
+ InjectHook(0x4D7D20, &CPed::WarpPedIntoCar, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 7e049464..50a8bfec 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -15,6 +15,7 @@
struct CPathNode;
class CAccident;
+class CObject;
struct CPedAudioData
{
@@ -362,7 +363,7 @@ public:
uint8 bShakeFist : 1; // test shake hand at look entity
uint8 bNoCriticalHits : 1; // if set, limbs won't came off
- uint8 m_ped_flagI4 : 1; // seems like related with cars
+ uint8 m_ped_flagI4 : 1; // we've been put to car by script? - related with cars
uint8 bHasAlreadyBeenRecorded : 1;
uint8 bFallenDown : 1;
#ifdef VC_PED_PORTS
@@ -430,7 +431,7 @@ public:
float m_headingRate;
uint16 m_vehEnterType; // TODO: this is more like a door, not a type
int16 m_walkAroundType;
- CEntity *m_pCurrentPhysSurface;
+ CPhysical *m_pCurrentPhysSurface;
CVector m_vecOffsetFromPhysSurface;
CEntity *m_pCurSurface;
CVector m_vecSeekPos;
@@ -532,7 +533,6 @@ public:
void SetDead(void);
void ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer);
void RemoveBodyPart(PedNode nodeId, int8 direction);
- void SpawnFlyingComponent(int, int8);
bool OurPedCanSeeThisOne(CEntity *target);
void Avoid(void);
void Attack(void);
@@ -670,7 +670,6 @@ public:
void ProcessBuoyancy(void);
void ServiceTalking(void);
void SetJump(void);
- void UpdatePosition(void);
void WanderPath(void);
void ReactToPointGun(CEntity*);
void SeekCar(void);
@@ -767,6 +766,8 @@ public:
void WanderRange(void);
void SetFollowRoute(int16, int16);
void SeekBoatPosition(void);
+ void UpdatePosition(void);
+ CObject *SpawnFlyingComponent(int, int8);
#ifdef VC_PED_PORTS
bool CanPedJumpThis(CEntity*, CVector*);
#else
@@ -796,9 +797,12 @@ public:
static CPedAudioData (&CommentWaitTime)[38];
#ifndef MASTER
+ static bool bUnusedFightThingOnPlayer;
+ static bool bPopHeadsOnHeadshot;
+
+ // Mobile things
static void SwitchDebugDisplay(void);
void DebugRenderOnePedText(void);
- static bool bUnusedFightThingOnPlayer;
#endif
};
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 0fa8547e..30446894 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -2474,8 +2474,8 @@ CAutomobile::TankControl(void)
int lifeSpan = 250;
if(m_vecMoveSpeed.Magnitude() > 0.08f){
lifeSpan = 125;
- flashPos.x += 0.5f*m_vecMoveSpeed.x;
- flashPos.y += 0.5f*m_vecMoveSpeed.y;
+ flashPos.x += 5.0f*m_vecMoveSpeed.x;
+ flashPos.y += 5.0f*m_vecMoveSpeed.y;
}
CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.4f, black, 0, 0, 0, lifeSpan);
flashPos += 0.3f*shotDir;
@@ -4210,7 +4210,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type)
if(atomic == nil)
return nil;
- obj = new CObject;
+ obj = new CObject();
if(obj == nil)
return nil;