Merge pull request #195 from erorcun/erorcun

AnimViewer messages, Particle fix, Peds
This commit is contained in:
aap 2019-08-17 21:24:26 +02:00 committed by GitHub
commit ed9ab6c55f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 595 additions and 15 deletions

View File

@ -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,6 +72,7 @@ CAnimViewer::Initialise(void) {
}
gbModelViewer = true;
CHud::m_Wants_To_Draw_Hud = false;
ThePaths.Init();
ThePaths.AllocatePathFindInfoMem(4500);
@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -297,7 +297,11 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
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)

View File

@ -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

View File

@ -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

View File

@ -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
{

View File

@ -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");

View File

@ -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 )
{

View File

@ -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

View File

@ -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]; }