diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 8f6ef4c3..d7d22174 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -110,6 +110,9 @@ public: static CVehicle *pPlayerVehicle; static CVector StaticCamCoors; static uint32 StaticCamStartTime; + +//TODO(MIAMI) + static void RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType) {} }; extern uint16 AmmoForWeapon[20]; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index b99110b0..6898d574 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3772,7 +3772,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CPed* pNearPed = ped->m_nearPeds[i]; if (pNearPed->m_leader == ped) { pNearPed->Teleport(pos); - pNearPed->PositionPedOutOfCollision(); // TODO(MIAMI): this is PositionAnyPedOutOfCollision!!! + pNearPed->PositionAnyPedOutOfCollision(); } } } diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 54c97d06..5559b1c4 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -18,6 +18,8 @@ // TODO: figure out the meaning of this enum { SOME_FLAG = 0x80 }; +bool CTrafficLights::bGreenLightsCheat; + void CTrafficLights::DisplayActualLight(CEntity *ent) { @@ -310,6 +312,12 @@ CTrafficLights::LightForPeds(void) uint8 CTrafficLights::LightForCars1(void) { + if (CWeather::Wind > 1.1f) + return CAR_LIGHTS_GREEN; + + if (bGreenLightsCheat) + return CAR_LIGHTS_GREEN; + uint32 period = CTimer::GetTimeInMilliseconds() % 16384; if(period < 5000) @@ -323,6 +331,12 @@ CTrafficLights::LightForCars1(void) uint8 CTrafficLights::LightForCars2(void) { + if (CWeather::Wind > 1.1f) + return CAR_LIGHTS_GREEN; + + if (bGreenLightsCheat) + return CAR_LIGHTS_GREEN; + uint32 period = CTimer::GetTimeInMilliseconds() % 16384; if(period < 6000) diff --git a/src/control/TrafficLights.h b/src/control/TrafficLights.h index f3df6cd5..6cd5e04a 100644 --- a/src/control/TrafficLights.h +++ b/src/control/TrafficLights.h @@ -16,6 +16,8 @@ enum { class CTrafficLights { public: + static bool bGreenLightsCheat; + static void DisplayActualLight(CEntity *ent); static void ScanForLightsOnMap(void); static int FindTrafficLightType(CEntity *light); diff --git a/src/core/EventList.h b/src/core/EventList.h index 0531aed7..dcca1270 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -24,6 +24,7 @@ enum eEventType EVENT_CAR_SET_ON_FIRE, EVENT_ASSAULT_NASTYWEAPON, EVENT_ASSAULT_NASTYWEAPON_POLICE, + EVENT_UNK, // Not on SA it seems EVENT_ICECREAM, EVENT_ATM, EVENT_SHOPSTALL, diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 715e9061..cdecb8b4 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5369,6 +5369,7 @@ CMenuManager::ConstructStatLine(int rowIdx) STAT_LINE("FEST_CC", &CStats::CriminalsCaught, false, nil); STAT_LINE("FEST_FE", &CStats::FiresExtinguished, false, nil); STAT_LINE("DAYPLC", &(nTemp = CTimer::GetTimeInMilliseconds() + 100), false, nil); + //TODO(MIAMI): move this function to the CStats and add reading of Stat lines tied with "MEDIA" for the "CHASESTAT" cheatcode return counter; #undef STAT_LINE diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 42b26c63..193ca1c5 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -47,6 +47,7 @@ #include "platform.h" #include "Stats.h" #include "CarCtrl.h" +#include "TrafficLights.h" #ifdef GTA_PS2 #include "eetypes.h" @@ -208,15 +209,20 @@ void HealthCheat() } } -void VehicleCheat(bool something, int model) +void VehicleCheat(int model) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - CStreaming::RequestModel(model, 0); - CStreaming::LoadAllRequestedModels(something); + CStreaming::RequestModel(model, STREAMFLAGS_DONT_REMOVE); + CStreaming::LoadAllRequestedModels(false); if (CStreaming::ms_aInfoForModel[model].m_loadState == STREAMSTATE_LOADED) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f); + if (!(CStreaming::ms_aInfoForModel[model].m_loadState & STREAMFLAGS_DONT_REMOVE)) { + CStreaming::SetModelIsDeletable(model); + CStreaming::SetModelTxdIsDeletable(model); + } + + int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f); if (node < 0) return; #ifdef FIX_BUGS @@ -362,18 +368,18 @@ void SunnyWeatherCheat() CWeather::ForceWeatherNow(WEATHER_SUNNY); } +void ExtraSunnyWeatherCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); + CWeather::ForceWeatherNow(WEATHER_EXTRA_SUNNY); +} + void CloudyWeatherCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); CWeather::ForceWeatherNow(WEATHER_CLOUDY); } -void StormyWeatherCheat() -{ - CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); - CWeather::ForceWeatherNow(WEATHER_HURRICANE); -} - void RainyWeatherCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); @@ -442,6 +448,12 @@ void PinkCarsCheat() gbPinkCars = true; } +void TrafficLightsCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CTrafficLights::bGreenLightsCheat = true; +} + void MadCarsCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); @@ -548,6 +560,11 @@ void FlyingFishCheat(void) CVehicle::bCheat8 = !CVehicle::bCheat8; } +void DoShowChaseStatCheat(void) { + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CStats::ShowChaseStatOnScreen = 1; +} + bool CControllerState::CheckForInput(void) { @@ -1030,7 +1047,7 @@ void CPad::AddToCheatString(char c) // "CCCCCC321TCT" - CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE else if ( !_CHEATCMP("TCT123CCCCCC") ) - VehicleCheat(true, MI_RHINO); + VehicleCheat(MI_RHINO); // "CCCSSSSS1TCT" - CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE else if ( !_CHEATCMP("TCT1SSSSSCCC") ) @@ -1142,19 +1159,22 @@ void CPad::AddToPCCheatString(char c) // "APLEASANTDAY" else if (!Cheat_strncmp(KeyBoardCheatString, "\\FKU[\\VHFW]I")) { KeyBoardCheatString[0] = ' '; - CloudyWeatherCheat(); + SunnyWeatherCheat(); } // "ALOVELYDAY" else if (!Cheat_strncmp(KeyBoardCheatString, "\\FKZY`YVML")) { KeyBoardCheatString[0] = ' '; - SunnyWeatherCheat(); + ExtraSunnyWeatherCheat(); } // "ABITDRIEG" - + else if (!Cheat_strncmp(KeyBoardCheatString, "JJPSQoLIB")) { + KeyBoardCheatString[0] = ' '; + CloudyWeatherCheat(); + } // "CATSANDDOGS" else if (!Cheat_strncmp(KeyBoardCheatString, "VLVEQiDZULP")) { KeyBoardCheatString[0] = ' '; - StormyWeatherCheat(); + RainyWeatherCheat(); } // "CANTSEEATHING" else if (!Cheat_strncmp(KeyBoardCheatString, "JSPIa\\HLT_[IJ")) { @@ -1164,10 +1184,13 @@ void CPad::AddToPCCheatString(char c) // "PANZER" else if (!Cheat_strncmp(KeyBoardCheatString, "UJaONk")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_RHINO); + VehicleCheat(MI_RHINO); } // "LIFEISPASSINGMEBY" - + else if (!Cheat_strncmp(KeyBoardCheatString, "\\GLNTiLZTL][PeSOh")) { + KeyBoardCheatString[0] = ' '; + FastWeatherCheat(); + } // "BIGBANG" else if (!Cheat_strncmp(KeyBoardCheatString, "JSHCTdE")) { KeyBoardCheatString[0] = ' '; @@ -1221,6 +1244,7 @@ void CPad::AddToPCCheatString(char c) // "CHASESTAT" else if (!Cheat_strncmp(KeyBoardCheatString, "WF[TRnDOD")) { KeyBoardCheatString[0] = ' '; + DoShowChaseStatCheat(); } // "CHICKSWITHGUNS" else if (!Cheat_strncmp(KeyBoardCheatString, "VS\\HUoL^TVPQOc")) { @@ -1235,6 +1259,7 @@ void CPad::AddToPCCheatString(char c) // "GREENLIGHT" else if (!Cheat_strncmp(KeyBoardCheatString, "WMNJYiHLSR")) { KeyBoardCheatString[0] = ' '; + TrafficLightsCheat(); } // "MIAMITRAFFIC" else if (!Cheat_strncmp(KeyBoardCheatString, "FNMGNmWPNLVU")) { @@ -1254,47 +1279,47 @@ void CPad::AddToPCCheatString(char c) // "TRAVELINSTYLE" else if (!Cheat_strncmp(KeyBoardCheatString, "HQ`U`iLSFaNZ[")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_BLOODRA); + VehicleCheat(MI_BLOODRA); } // "THELASTRIDE" else if (!Cheat_strncmp(KeyBoardCheatString, "HIPSanDSFSa")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_ROMERO); + VehicleCheat(MI_ROMERO); } // "ROCKANDROLLCAR" else if (!Cheat_strncmp(KeyBoardCheatString, "UFJMYjUKOLXKVr")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_LOVEFIST); + VehicleCheat(MI_LOVEFIST); } // "RUBBISHCAR" else if (!Cheat_strncmp(KeyBoardCheatString, "UFJI`dEIV]")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_TRASH); + VehicleCheat(MI_TRASH); } // "GETTHEREQUICKLY" else if (!Cheat_strncmp(KeyBoardCheatString, "\\QRDVpTLSPU\\[eT")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_BLOODRB); + VehicleCheat(MI_BLOODRB); } // "GETTHEREFAST" else if (!Cheat_strncmp(KeyBoardCheatString, "WXHGRmHOU_RO")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_SABRETUR); + VehicleCheat(MI_SABRETUR); } // "BETTERTHANWALKING" else if (!Cheat_strncmp(KeyBoardCheatString, "JSPLY\\ZUBSaZLtaK^")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_CADDY); + VehicleCheat(MI_CADDY); } // "GETTHEREFASTINDEED" else if (!Cheat_strncmp(KeyBoardCheatString, "GJLE[dWZBQfZLvRXa[^WHL")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_HOTRINA); + VehicleCheat(MI_HOTRINA); } // "GETTHEREAMAZINGLYFAST" else if (!Cheat_strncmp(KeyBoardCheatString, "WXHGfgJUJeNUHe_Kdg^HJ")) { KeyBoardCheatString[0] = ' '; - VehicleCheat(true, MI_HOTRINB); + VehicleCheat(MI_HOTRINB); } // LOOKLIKELANCE else if (!Cheat_strncmp(KeyBoardCheatString, "HHUBY`NPMV\\WS")) { @@ -1346,6 +1371,16 @@ void CPad::AddToPCCheatString(char c) KeyBoardCheatString[0] = ' '; ChangePlayerModel("igdiaz"); } + // DEEPFRIEDMARSBARS + else if (!Cheat_strncmp(KeyBoardCheatString, "VWHC`mDTEPVZMpRK")) { + KeyBoardCheatString[0] = ' '; + gfTommyFatness = 0.26f; + } + // PROGRAMMER + else if (!Cheat_strncmp(KeyBoardCheatString, "UJTNNmJVS[")) { + KeyBoardCheatString[0] = ' '; + gfTommyFatness = -0.3f; + } // SEAWAYS else if (!Cheat_strncmp(KeyBoardCheatString, "V^HXN`V")) { KeyBoardCheatString[0] = ' '; @@ -1366,17 +1401,6 @@ void CPad::AddToPCCheatString(char c) KeyBoardCheatString[0] = ' '; FannyMagnetCheat(); } - // "ILOVESCOTLAND" - if (!_CHEATCMP("DNALTOCSEVOLI")) - RainyWeatherCheat(); - - // "MADWEATHER" - if (!_CHEATCMP("REHTAEWDAM")) - FastWeatherCheat(); - - // "CHITTYCHITTYBB" - if (!_CHEATCMP("BBYTTIHCYTTIHC")) - ChittyChittyBangBangCheat(); // "NASTYLIMBSCHEAT" if (!_CHEATCMP("TAEHCSBMILYTSAN")) @@ -3117,6 +3141,8 @@ void CPad::ResetCheats(void) gbBlackCars = false; gbPinkCars = false; CCarCtrl::bMadDriversCheat = false; + CTrafficLights::bGreenLightsCheat = false; + CStats::ShowChaseStatOnScreen = 0; gbFastTime = false; CTimer::SetTimeScale(1.0f); } diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 1efcee01..9c3ad084 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -341,6 +341,30 @@ wchar *CStats::FindCriminalRatingString() return TheText.Get(CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney > 10000000 ? "RATNG52" : "RATNG51"); } +wchar *CStats::FindChaseString(float fMediaLevel) { + if (fMediaLevel < 20.0f) return TheText.Get("MEDIA1"); + if (fMediaLevel < 50.0f) return TheText.Get("MEDIA2"); + if (fMediaLevel < 75.0f) return TheText.Get("MEDIA3"); + if (fMediaLevel < 100.0f) return TheText.Get("MEDIA4"); + if (fMediaLevel < 150.0f) return TheText.Get("MEDIA5"); + if (fMediaLevel < 200.0f) return TheText.Get("MEDIA6"); + if (fMediaLevel < 250.0f) return TheText.Get("MEDIA7"); + if (fMediaLevel < 300.0f) return TheText.Get("MEDIA8"); + if (fMediaLevel < 350.0f) return TheText.Get("MEDIA9"); + if (fMediaLevel < 400.0f) return TheText.Get("MEDIA10"); + if (fMediaLevel < 500.0f) return TheText.Get("MEDIA11"); + if (fMediaLevel < 600.0f) return TheText.Get("MEDIA12"); + if (fMediaLevel < 700.0f) return TheText.Get("MEDIA13"); + if (fMediaLevel < 800.0f) return TheText.Get("MEDIA14"); + if (fMediaLevel < 900.0f) return TheText.Get("MEDIA15"); + if (fMediaLevel < 1000.0f) return TheText.Get("MEDIA16"); + if (fMediaLevel < 1200.0f) return TheText.Get("MEDIA17"); + if (fMediaLevel < 1400.0f) return TheText.Get("MEDIA18"); + if (fMediaLevel < 1600.0f) return TheText.Get("MEDIA19"); + if (fMediaLevel < 1800.0f) return TheText.Get("MEDIA20"); + return TheText.Get("MEDIA21"); +} + int32 CStats::FindCriminalRatingNumber() { int32 rating; diff --git a/src/core/Stats.h b/src/core/Stats.h index f9ad4174..ad6fe516 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -118,6 +118,7 @@ public: static void RegisterLevelFireMission(int32); static void AnotherFireExtinguished(); static wchar *FindCriminalRatingString(); + static wchar *FindChaseString(float fMediaLevel); static void AnotherKillFrenzyPassed(); static void SetTotalNumberKillFrenzies(int32); static void SetTotalNumberMissions(int32); diff --git a/src/core/World.cpp b/src/core/World.cpp index fb2dbad3..6d5e8a81 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -49,6 +49,7 @@ bool CWorld::bProcessCutsceneOnly; bool CWorld::bDoingCarCollisions; bool CWorld::bIncludeCarTyres; +bool CWorld::bIncludeBikers; CColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS]; @@ -63,6 +64,7 @@ CWorld::Initialise() bIncludeDeadPeds = false; bForceProcessControl = false; bIncludeCarTyres = false; + bIncludeBikers = false; } void @@ -272,7 +274,9 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin { float mindist = dist; bool deadPeds = !!bIncludeDeadPeds; + bool bikers = !!bIncludeBikers; bIncludeDeadPeds = false; + bIncludeBikers = false; if(checkBuildings) { ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, @@ -290,11 +294,13 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin if(checkPeds) { if(deadPeds) bIncludeDeadPeds = true; + if(bikers) bIncludeBikers = true; ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, ignoreSeeThrough, false, ignoreShootThrough); ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, false, ignoreShootThrough); bIncludeDeadPeds = false; + bIncludeBikers = false; } if(checkObjects) { @@ -312,6 +318,7 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin } bIncludeDeadPeds = deadPeds; + bIncludeBikers = bikers; if(mindist < dist) { dist = mindist; @@ -325,22 +332,24 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough) { bool deadPeds = false; + bool bikers = false; float mindist = dist; CPtrNode *node; CEntity *e; CColModel *colmodel; if(list.first && bIncludeDeadPeds && ((CEntity *)list.first->item)->IsPed()) deadPeds = true; + if(list.first && bIncludeBikers && ((CEntity *)list.first->item)->IsPed()) bikers = true; for(node = list.first; node; node = node->next) { e = (CEntity *)node->item; - if(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds) && + if(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds || bikers) && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { colmodel = nil; e->m_scanCode = GetCurrentScanCode(); if(e->IsPed()) { - if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) { + if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD || bikers) { colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump()); } else colmodel = nil; diff --git a/src/core/World.h b/src/core/World.h index 8d539061..606a3466 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -71,6 +71,7 @@ public: static bool bProcessCutsceneOnly; static bool bDoingCarCollisions; static bool bIncludeCarTyres; + static bool bIncludeBikers; static CColPoint m_aTempColPts[MAX_COLLISION_POINTS]; static void Remove(CEntity *entity); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 0b80862e..1393314c 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -80,7 +80,7 @@ void WeaponCheat1(); void WeaponCheat2(); void WeaponCheat3(); void HealthCheat(); -void VehicleCheat(bool something, int model); +void VehicleCheat(int model); void BlowUpCarsCheat(); void ChangePlayerCheat(); void MayhemCheat(); @@ -353,7 +353,7 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Cheats", "Health", HealthCheat); DebugMenuAddCmd("Cheats", "Wanted level up", WantedLevelUpCheat); DebugMenuAddCmd("Cheats", "Wanted level down", WantedLevelDownCheat); - DebugMenuAddCmd("Cheats", "Tank", []() { VehicleCheat(true, MI_TAXI); }); + DebugMenuAddCmd("Cheats", "Tank", []() { VehicleCheat(MI_TAXI); }); DebugMenuAddCmd("Cheats", "Blow up cars", BlowUpCarsCheat); DebugMenuAddCmd("Cheats", "Change player", ChangePlayerCheat); DebugMenuAddCmd("Cheats", "Mayhem", MayhemCheat); diff --git a/src/objects/Stinger.cpp b/src/objects/Stinger.cpp new file mode 100644 index 00000000..f33125ee --- /dev/null +++ b/src/objects/Stinger.cpp @@ -0,0 +1,232 @@ +#include "common.h" +#include "Stinger.h" +#include "CopPed.h" +#include "ModelIndices.h" +#include "RpAnimBlend.h" +#include "World.h" +#include "Automobile.h" +#include "Bike.h" +#include "Particle.h" +#include "AnimBlendAssociation.h" +#include "General.h" + +uint32 NumOfStingerSegments; + +/* -- CStingerSegment -- */ + +CStingerSegment::CStingerSegment() +{ + m_fMass = 1.0f; + m_fTurnMass = 1.0f; + m_fAirResistance = 0.99999f; + m_fElasticity = 0.75f; + m_fBuoyancy = GRAVITY * m_fMass * 0.1f; + bExplosionProof = true; + SetModelIndex(MI_PLC_STINGER); + ObjectCreatedBy = ESCALATOR_OBJECT; + NumOfStingerSegments++; +} + +CStingerSegment::~CStingerSegment() +{ + NumOfStingerSegments--; +} + +/* -- CStinger -- */ + +CStinger::CStinger() +{ + bIsDeployed = false; +} + +void +CStinger::Init(CPed *pPed) +{ + int32 i; + + pOwner = pPed; + for (i = 0; i < NUM_STINGER_SEGMENTS; i++) { + pSpikes[i] = new CStingerSegment; + pSpikes[i]->bUsesCollision = false; + } + bIsDeployed = true; + m_vPos = pPed->GetPosition(); + m_vPos.z -= 1.0f; + m_fMax_Z = Atan2(-pPed->GetForward().x, pPed->GetForward().y) + HALFPI; + + for (i = 0; i < NUM_STINGER_SEGMENTS; i++) { + pSpikes[i]->SetOrientation(0.0f, 0.0f, Atan2(-pPed->GetForward().x, pPed->GetForward().y)); + pSpikes[i]->SetPosition(m_vPos); + } + + CVector2D fwd2d(pPed->GetForward().x, pPed->GetForward().y); + + for (i = 0; i < ARRAY_SIZE(m_vPositions); i++) + m_vPositions[i] = fwd2d * 1.8f * Sin(DEGTORAD(i)); + + m_nSpikeState = STINGERSTATE_NONE; + m_nTimeOfDeploy = CTimer::GetTimeInMilliseconds(); +} + +void +CStinger::Remove() +{ + if (!bIsDeployed) return; + + for (int32 i = 0; i < NUM_STINGER_SEGMENTS; i++) { + CStingerSegment *spikeSegment = pSpikes[i]; + if (spikeSegment->m_entryInfoList.first != nil) + spikeSegment->bRemoveFromWorld = true; + else + delete spikeSegment; + } + bIsDeployed = false; +} + +void +CStinger::Deploy(CPed *pPed) +{ + if (NumOfStingerSegments < NUM_STINGER_SEGMENTS*2 && !pPed->bInVehicle && pPed->IsPedInControl()) { + if (!bIsDeployed && RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_WEAPON_THROWU) == nil) { + Init(pPed); + pPed->SetPedState(PED_DEPLOY_STINGER); + CAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU); + } + } +} + +void +CStinger::CheckForBurstTyres() +{ + CVector firstPos = pSpikes[0]->GetPosition(); + firstPos.z += 0.2f; + CVector lastPos = pSpikes[NUM_STINGER_SEGMENTS - 1]->GetPosition(); + lastPos.z += 0.2f; + float dist = (lastPos - firstPos).Magnitude(); + if (dist < 0.1f) return; + + CVehicle *vehsInRange[16]; + int16 numObjects; + CEntity entity; + + CWorld::FindObjectsInRange((lastPos + firstPos) / 2.0f, + dist, true, &numObjects, 15, (CEntity**)vehsInRange, + false, true, false, false, false); + + for (int32 i = 0; i < numObjects; i++) { + CAutomobile *pAutomobile = nil; + CBike *pBike = nil; + + if (vehsInRange[i]->IsCar()) + pAutomobile = (CAutomobile*)vehsInRange[i]; + else if (vehsInRange[i]->IsBike()) + pBike = (CBike*)vehsInRange[i]; + + if (pAutomobile == nil && pBike == nil) continue; + + float maxWheelDistToSpike = sq(((CVehicleModelInfo*)CModelInfo::GetModelInfo(vehsInRange[i]->GetModelIndex()))->m_wheelScale + 0.1f); + + for (int wheelId = 0; wheelId < 4; wheelId++) { + if ((pAutomobile != nil && pAutomobile->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f) || + (pBike != nil && pBike->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f)) { + CVector vecWheelPos; + if (pAutomobile != nil) + vecWheelPos = pAutomobile->m_aWheelColPoints[wheelId].point; + else if (pBike != nil) + vecWheelPos = pBike->m_aWheelColPoints[wheelId].point; + + for (int32 spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) { + if ((pSpikes[spike]->GetPosition() - vecWheelPos).Magnitude() < maxWheelDistToSpike) { + if (pBike) { + if (wheelId < 2) + vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true); + else + vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LR, true); + } + else { + switch (wheelId) { + case 0: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true); break; + case 1: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LR, true); break; + case 2: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_RF, true); break; + case 3: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_RR, true); break; + } + } + vecWheelPos.z += 0.15f; + for (int j = 0; j < 4; j++) + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, vecWheelPos, vehsInRange[i]->GetRight() * 0.1f); + } + } + } + } + } +} + +void +CStinger::Process() +{ + switch (m_nSpikeState) + { + case STINGERSTATE_NONE: + if (pOwner != nil + && !pOwner->bInVehicle + && pOwner->GetPedState() == PED_DEPLOY_STINGER + && RpAnimBlendClumpGetAssociation(pOwner->GetClump(), ANIM_WEAPON_THROWU)->currentTime > 0.39f) + { + m_nSpikeState = STINGERSTATE_DEPLOYING; + for (int i = 0; i < NUM_STINGER_SEGMENTS; i++) + CWorld::Add(pSpikes[i]); + pOwner->SetIdle(); + } + break; + case STINGERSTATE_DEPLOYED: + if (pOwner != nil && pOwner->m_nPedType == PEDTYPE_COP) + ((CCopPed*)pOwner)->m_bThrowsSpikeTrap = false; + break; + case STINGERSTATE_UNDEPLOYING: + if (CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500) + m_nSpikeState = STINGERSTATE_REMOVE; + // no break + case STINGERSTATE_DEPLOYING: + if (m_nSpikeState == STINGERSTATE_DEPLOYING && CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500) + m_nSpikeState = STINGERSTATE_DEPLOYED; + else { + float progress = (CTimer::GetTimeInMilliseconds() - m_nTimeOfDeploy) / 2500.0f; + if (m_nSpikeState != STINGERSTATE_DEPLOYING) + progress = 1.0f - progress; + + float degangle = progress * ARRAY_SIZE(m_vPositions); + float angle1 = m_fMax_Z + DEGTORAD(degangle); + float angle2 = m_fMax_Z - DEGTORAD(degangle); + int pos = clamp(degangle, 0, ARRAY_SIZE(m_vPositions)-1); + + CVector2D pos2d = m_vPositions[pos]; + CVector pos3d = m_vPos; + CColPoint colPoint; + CEntity *pEntity; + if (CWorld::ProcessVerticalLine(CVector(pos3d.x, pos3d.y, pos3d.z - 10.0f), pos3d.z, colPoint, pEntity, true, false, false, false, true, false, nil)) + pos3d.z = colPoint.point.z + 0.15f; + + angle1 = CGeneral::LimitRadianAngle(angle1); + angle2 = CGeneral::LimitRadianAngle(angle2); + + for (int spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) { + if (CWorld::TestSphereAgainstWorld(pos3d + CVector(pos2d.x, pos2d.y, 0.6f), 0.3f, nil, true, false, false, true, false, false)) + pos2d = CVector2D(0.0f, 0.0f); + + if (spike % 2 == 0) { + pSpikes[spike]->SetOrientation(0.0f, 0.0f, angle1); + pos3d.x += pos2d.x; + pos3d.y += pos2d.y; + } else { + pSpikes[spike]->SetOrientation(0.0f, 0.0f, angle2); + } + pSpikes[spike]->SetPosition(pos3d); + } + } + break; + case STINGERSTATE_REMOVE: + Remove(); + break; + } + CheckForBurstTyres(); +} \ No newline at end of file diff --git a/src/objects/Stinger.h b/src/objects/Stinger.h new file mode 100644 index 00000000..250cf62d --- /dev/null +++ b/src/objects/Stinger.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Object.h" + +class CStingerSegment : public CObject +{ +public: + CStingerSegment(); + ~CStingerSegment(); +}; + +#define NUM_STINGER_SEGMENTS (12) + +enum { + STINGERSTATE_NONE = 0, + STINGERSTATE_DEPLOYING, + STINGERSTATE_DEPLOYED, + STINGERSTATE_UNDEPLOYING, + STINGERSTATE_REMOVE, +}; + +class CStinger +{ +public: + bool bIsDeployed; + uint32 m_nTimeOfDeploy; + CVector m_vPos; + float m_fMax_Z; + float m_fMin_Z; + CVector2D m_vPositions[60]; + CStingerSegment *pSpikes[NUM_STINGER_SEGMENTS]; + class CPed *pOwner; + uint8 m_nSpikeState; + CStinger(); + void Init(CPed *pPed); + void Remove(); + void Deploy(CPed *pPed); + void CheckForBurstTyres(); + void Process(); +}; \ No newline at end of file diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 6c9eb276..9160319b 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -18,6 +18,7 @@ #include "Camera.h" #include "PedPlacement.h" #include "Ropes.h" +#include "Stinger.h" CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) { @@ -92,14 +93,17 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_nHassleTimer = 0; field_61C = 0; field_624 = 0; + m_pStinger = new CStinger; if (m_pPointGunAt) - m_pPointGunAt->CleanUpOldReference((CEntity**)&m_pPointGunAt); + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); m_pPointGunAt = nil; } CCopPed::~CCopPed() { ClearPursuit(); + m_pStinger->Remove(); + delete m_pStinger; } // --MIAMI: Done @@ -597,7 +601,7 @@ CCopPed::CopAI(void) } } -// --MIAMI: Done except commented things +// --MIAMI: Done void CCopPed::ProcessControl(void) { @@ -607,15 +611,13 @@ CCopPed::ProcessControl(void) CPed::ProcessControl(); if (m_bThrowsSpikeTrap) { - // TODO(Miami) - /* if (CGame::currArea != AREA_MALL) ProcessStingerCop(); - */ return; } - // TODO(Miami): CStinger::Process + if (m_pStinger && m_pStinger->bIsDeployed && m_pStinger->m_nSpikeState == STINGERSTATE_DEPLOYED && CGame::currArea != AREA_MALL) + m_pStinger->Process(); if (bWasPostponed) return; @@ -854,4 +856,36 @@ CCopPed::ProcessHeliSwat(void) SetInTheAir(); bKnockedUpIntoAir = true; } +} + +// --MIAMI: Done +void +CCopPed::ProcessStingerCop(void) +{ + if (m_pStinger->bIsDeployed || FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) { + if (m_pStinger->bIsDeployed) { + m_pStinger->Process(); + } else { + CVector2D vehDist = GetPosition() - FindPlayerVehicle()->GetPosition(); + CVector2D dirVehGoing = FindPlayerVehicle()->m_vecMoveSpeed; + if (vehDist.MagnitudeSqr() < sq(30.0f)) { + if (dirVehGoing.MagnitudeSqr() > 0.0f) { + vehDist.Normalise(); + dirVehGoing.Normalise(); + if (DotProduct2D(vehDist, dirVehGoing) > 0.8f) { + float angle = (CrossProduct2D(vehDist, dirVehGoing - vehDist) < 0.0f ? + FindPlayerVehicle()->GetForward().Heading() - HALFPI : + HALFPI + FindPlayerVehicle()->GetForward().Heading()); + + SetHeading(angle); + m_fRotationCur = angle; + m_fRotationDest = angle; + m_pStinger->Deploy(this); + } + } + } + } + } else { + ClearPursuit(); + } } \ No newline at end of file diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index edec145e..190d619e 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -30,6 +30,7 @@ public: uintptr m_nRopeID; uint32 m_nHassleTimer; uint32 field_61C; + class CStinger *m_pStinger; int32 field_624; int8 field_628; @@ -44,6 +45,7 @@ public: void ScanForCrimes(void); void CopAI(void); void ProcessHeliSwat(void); + void ProcessStingerCop(void); }; #ifndef PED_SKIN diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 0cc5eeaf..f197ae2c 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -65,6 +65,7 @@ #include "Bike.h" #include "WindModifiers.h" #include "CutsceneShadow.h" +#include "Clock.h" #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) @@ -145,6 +146,8 @@ void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->N void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); } void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((CPed*)p); } +float gfTommyFatness = 1.0f; + // --MIAMI: Done CPed::~CPed(void) { @@ -285,7 +288,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_fleeFromPosX = 0; m_fleeFromPosY = 0; m_fleeTimer = 0; - pThreatEx = nil; + m_threatEx = nil; m_vecSeekPosEx = CVector(0.0f, 0.0f, 0.0f); m_distanceToCountSeekDoneEx = 0.0f; m_nWaitState = WAITSTATE_FALSE; @@ -422,8 +425,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bHasAlreadyUsedAttractor = false; b155_2 = false; bCarPassenger = false; - b155_8 = false; - b155_10 = false; + bFleeWhenStanding = false; + bGotUpOfMyOwnAccord = false; bMiamiViceCop = false; bMoneyHasBeenGivenByScript = false; bHasBeenPhotographed = false; @@ -444,7 +447,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bDoomAim = true; bCanBeShotInVehicle = true; bPushedAlongByCar = false; - b157_40 = false; + bRemoveMeWhenIGotIntoCar = false; bIgnoreThreatsBehindObjects = false; bNeverEverTargetThisPed = false; @@ -453,7 +456,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) b158_8 = false; bCollectBusFare = false; bBoughtIceCream = false; - b158_40 = false; + bDonePositionOutOfCollision = false; b158_80 = false; if (CGeneral::GetRandomNumber() & 3) @@ -462,9 +465,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bHasACamera = true; if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) <= 0.95f) - b157_8 = false; + bCanGiveUpSunbathing = false; else - b157_8 = true; + bCanGiveUpSunbathing = true; m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this); DMAudio.SetEntityStatus(m_audioEntityId, 1); @@ -2097,6 +2100,8 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) m_fRotationDest = veh->GetForward().Heading(); } else if (veh->bIsBus) { m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); + } else if (m_vehEnterType == CAR_WINDSCREEN) { + m_fRotationDest = veh->GetForward().Heading() + PI; } else { m_fRotationDest = veh->GetForward().Heading(); } @@ -2317,7 +2322,6 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (seatPosMult > 0.2f || vehIsUpsideDown || veh->IsBike()) { SetPosition(neededPos); - SetHeading(m_fRotationCur); } else { CMatrix vehDoorMat(veh->GetMatrix()); @@ -4082,7 +4086,7 @@ CPed::ClearAll(void) m_fleeFromPosY = 0.0f; m_fleeFrom = nil; m_fleeTimer = 0; - pThreatEx = nil; + m_threatEx = nil; bUsesCollision = true; ClearPointGunAt(); bIsPointingGunAt = false; @@ -4181,6 +4185,7 @@ CPed::SetStoredState(void) } } +// --MIAMI: Done void CPed::SetDie(AnimationId animId, float delta, float speed) { @@ -4196,6 +4201,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) if (DyingOrDead()) return; + CAnimBlendAssociation *dieAssoc = nil; if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) delta *= 0.5f; @@ -4203,7 +4209,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) ClearAll(); m_fHealth = 0.0f; if (m_nPedState == PED_DRIVING) { - if (!IsPlayer()) + if (!IsPlayer() && (!m_pMyVehicle || !m_pMyVehicle->IsBike())) FlagToDestroyWhenNextProcessed(); } else if (bInVehicle) { if (m_pVehicleAnim) @@ -4212,11 +4218,11 @@ CPed::SetDie(AnimationId animId, float delta, float speed) QuitEnteringCar(); } - m_nPedState = PED_DIE; + SetPedState(PED_DIE); if (animId == NUM_STD_ANIMS) { bIsPedDieAnimPlaying = false; } else { - CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta); + dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta); if (speed > 0.0f) dieAssoc->speed = speed; @@ -4230,10 +4236,17 @@ CPed::SetDie(AnimationId animId, float delta, float speed) Say(SOUND_PED_DEATH); if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK) QuitEnteringCar(); + if (!bInVehicle) StopNonPartialAnims(); m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds(); + if (!CGame::nastyGame && animId == ANIM_FLOOR_HIT) { + if (dieAssoc) { + dieAssoc->SetCurrentTime(dieAssoc->hierarchy->totalLength - 0.01f); + dieAssoc->SetRun(); + } + } } // --MIAMI: Done except commented things @@ -4787,6 +4800,7 @@ CPed::ClearFall(void) SetGetUp(); } +// --MIAMI: Done void CPed::SetGetUp(void) { @@ -4809,7 +4823,7 @@ CPed::SetGetUp(void) CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity; CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition()); - if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE || + if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE && veh != m_attachedTo || collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE && ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 || CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(), @@ -4829,6 +4843,7 @@ CPed::SetGetUp(void) bGetUpAnimStarted = true; m_pCollidingEntity = nil; bKnockedUpIntoAir = false; + bKnockedOffBike = false; CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT); if (animAssoc) { if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) { @@ -4839,12 +4854,21 @@ CPed::SetGetUp(void) animAssoc->flags |= ASSOC_DELETEFADEDOUT; } - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) + if (m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) { + m_headingRate = 0.0f; + + // TODO(Miami): Looks like that should've been another getup anim but R* forgot it. Visit here later + if (bFleeWhenStanding && m_threatEx) + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + else + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); + + } else if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f); else animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f); - animAssoc->SetFinishCallback(PedGetupCB,this); + animAssoc->SetFinishCallback(PedGetupCB, this); } else { m_fHealth = 0.0f; SetDie(NUM_STD_ANIMS, 4.0f, 0.0f); @@ -6478,7 +6502,7 @@ CPed::SetFlee(CVector2D const &from, int time) } } -// --MIAMI: Only some part is done +// --MIAMI: Done void CPed::SetWaitState(eWaitState state, void *time) { @@ -6630,7 +6654,7 @@ CPed::SetWaitState(eWaitState state, void *time) case WAITSTATE_SIT_DOWN: animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_DOWN, 4.0f); animAssoc->SetFinishCallback(FinishedWaitCB, this); - m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000; + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; break; case WAITSTATE_SIT_UP: animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_UP, 4.0f); @@ -6638,7 +6662,7 @@ CPed::SetWaitState(eWaitState state, void *time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; break; case WAITSTATE_SIT_IDLE: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_IDLE, 5000.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_IDLE, 128.f); animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -6646,13 +6670,19 @@ CPed::SetWaitState(eWaitState state, void *time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000); break; case WAITSTATE_USE_ATM: - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ATM, 5000.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ATM, 4.0f); animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; else m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000; break; + case WAITSTATE_SUN_BATHE_IDLE: + m_headingRate = 0.0f; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_SUNBATHE, ANIM_SUNBATHE, 4.0f); + animAssoc->SetDeleteCallback(DeleteSunbatheIdleAnimCB, this); + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(50000, 100000); + break; case WAITSTATE_FAST_FALL: SetFall(-1, ANIM_KO_SKID_FRONT, true); break; @@ -6660,14 +6690,31 @@ CPed::SetWaitState(eWaitState state, void *time) CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_BOMBER, 4.0f); m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; break; + case WAITSTATE_GROUND_ATTACK: + { + CWeaponInfo* currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + if (!currentWeapon) + break; + if (GetFireAnimGround(currentWeapon, false)) { + if (!RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(currentWeapon, false))) { + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000; + CAnimBlendAssociation* newAnim = CAnimManager::BlendAnimation(GetClump(), + currentWeapon->m_AnimToPlay, GetFireAnimGround(currentWeapon, false), 8.0f); + newAnim->SetDeleteCallback(FinishedWaitCB, this); + } + } + break; + } case WAITSTATE_LANCESITTING: CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_LANCE, ANIM_SUNBATHE, 4.0f); break; - case WAITSTATE_SUN_BATHE_PRE: - case WAITSTATE_SUN_BATHE_DOWN: - case WAITSTATE_SUN_BATHE_IDLE: - case WAITSTATE_GROUND_ATTACK: case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE: + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 4.0f); + animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE; + animAssoc->flags |= ASSOC_DELETEFADEDOUT; + animAssoc->SetDeleteCallback(FinishedWaitCB, this); + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; + break; default: ClearWaitState(); RestoreHeadingRate(); @@ -8374,7 +8421,7 @@ CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg) ped->Wait(); } -// --MIAMI: Some part is done +// --MIAMI: Done void CPed::Wait(void) { @@ -8575,28 +8622,24 @@ CPed::Wait(void) } else if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) { if (GetWeapon()->IsTypeMelee()) { -#ifdef VC_PED_PORTS if(m_pedStats->m_flags & STAT_GUN_PANIC) { -#endif - SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); - if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { + SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); + if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { - bUsePedNodeSeek = true; - m_pNextPathNode = nil; - } - if (m_nMoveState != PEDMOVE_RUN) - SetMoveState(PEDMOVE_WALK); + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + } + if (m_nMoveState != PEDMOVE_RUN) + SetMoveState(PEDMOVE_WALK); - if (m_nPedType != PEDTYPE_COP) { - ProcessObjective(); - SetMoveState(PEDMOVE_WALK); - } -#ifdef VC_PED_PORTS + if (m_nPedType != PEDTYPE_COP) { + ProcessObjective(); + SetMoveState(PEDMOVE_WALK); + } } else { SetObjective(OBJECTIVE_NONE); SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f)); } -#endif } else { SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget); SetObjectiveTimer(20000); @@ -8646,9 +8689,7 @@ CPed::Wait(void) bBoughtIceCream = true; } ClearWaitState(); - } -#ifdef VC_PED_PORTS - else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) { + } else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) { if (m_pedInObjective) { if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { @@ -8660,7 +8701,6 @@ CPed::Wait(void) } } } -#endif break; case WAITSTATE_FINISH_FLEE: @@ -8689,7 +8729,14 @@ CPed::Wait(void) if (m_attractor) GetPedAttractorManager()->BroadcastDeparture(this, m_attractor); ClearWaitState(); - //TODO(MIAMI): scan for threats! + if (bFleeWhenStanding) { + if (m_threatEx) { + SetFlee(m_threatEx, 10000); + bFleeWhenStanding = false; + m_threatEx = nil; + Say(SOUND_PED_FLEE_SPRINT); + } + } } break; case WAITSTATE_SIT_IDLE: @@ -8699,10 +8746,26 @@ CPed::Wait(void) m_fRotationDest = m_fRotationCur; bTurnedAroundOnAttractor = false; } - // TODO(MIAMI): scan for threats! if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { ClearWaitState(); SetWaitState(WAITSTATE_SIT_UP, 0); + } else { + if (m_fleeFrom && m_fleeFrom->IsVehicle()) { + m_pNextPathNode = nil; + m_threatEx = m_threatEntity; + bFleeWhenStanding = true; + ClearWaitState(); + SetWaitState(WAITSTATE_SIT_UP, 0); + } else { + uint32 threatFlag = ScanForThreats(); + if (threatFlag == PED_FLAG_GUN || threatFlag == PED_FLAG_EXPLOSION || threatFlag == PED_FLAG_DEADPEDS) { + m_pNextPathNode = nil; + m_threatEx = m_threatEntity; + bFleeWhenStanding = true; + ClearWaitState(); + SetWaitState(WAITSTATE_SIT_UP, 0); + } + } } break; case WAITSTATE_USE_ATM: @@ -8712,6 +8775,56 @@ CPed::Wait(void) ClearWaitState(); } break; + case WAITSTATE_SUN_BATHE_IDLE: + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer && bCanGiveUpSunbathing) { + m_pNextPathNode = nil; + bGotUpOfMyOwnAccord = true; + SetGetUp(); + ClearWaitState(); + + } else if (CWeather::Rain <= 0.1f) { + if (CClock::GetHours() <= 18 || CGeneral::GetRandomNumberInRange(0.f, 1.0f) < 0.005f) { + uint32 threatFlag = ScanForThreats(); + if (threatFlag == PED_FLAG_GUN || threatFlag == PED_FLAG_EXPLOSION || threatFlag == PED_FLAG_DEADPEDS) { + // Get up in case of danger + m_pNextPathNode = nil; + m_threatEx = m_threatEntity; + bFleeWhenStanding = true; + SetGetUp(); + ClearWaitState(); + } + CPlayerPed *player = FindPlayerPed(); + if (player) { + // Get up if player coming towards us with a car + if (player->InVehicle()){ + CVector vehSpeedPerSec = player->m_pMyVehicle->m_vecMoveSpeed * GAME_SPEED_TO_METERS_PER_SECOND; + CVector vehPos = player->m_pMyVehicle->GetPosition(); + CVector ourPos = GetPosition(); + float timeUntilVehReachPed = DotProduct(ourPos - vehPos, vehSpeedPerSec) / vehSpeedPerSec.MagnitudeSqr(); + if (timeUntilVehReachPed > 0.0 && timeUntilVehReachPed < 8.0f) { + if ((ourPos - (timeUntilVehReachPed * vehSpeedPerSec + vehPos)).Magnitude() < 5.0f) { + m_pNextPathNode = nil; + m_threatEx = player; + bFleeWhenStanding = true; + SetGetUp(); + ClearWaitState(); + } + } + } + } + } else { + m_pNextPathNode = nil; + bGotUpOfMyOwnAccord = true; + SetGetUp(); + ClearWaitState(); + } + } else { + m_pNextPathNode = nil; + bGotUpOfMyOwnAccord = true; + SetGetUp(); + ClearWaitState(); + } + break; case WAITSTATE_RIOT: if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ATTACK) { ClearWaitState(); @@ -8741,11 +8854,10 @@ CPed::Wait(void) case WAITSTATE_STRIPPER: PlayRandomAnimationsFromAnimBlock(this, ASSOCGRP_STRIP, ANIM_STRIP_A, ANIM_STRIP_G - ANIM_STRIP_A + 1); break; - case WAITSTATE_SUN_BATHE_PRE: - case WAITSTATE_SUN_BATHE_DOWN: - case WAITSTATE_SUN_BATHE_IDLE: case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE: - assert(0); + if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) + ClearWaitState(); + break; default: break; } @@ -9522,6 +9634,7 @@ CPed::SetLanding(void) bIsLanding = true; } +// --MIAMI: Done void CPed::Initialise(void) { @@ -9694,6 +9807,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void) CAnimManager::RemoveAnimBlockRef(bikedBlock); } +// --MIAMI: Done void CPed::InvestigateEvent(void) { @@ -9707,7 +9821,7 @@ CPed::InvestigateEvent(void) if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { if (m_standardTimer) { - if (m_eventType < EVENT_ASSAULT_NASTYWEAPON) + if (m_eventType < EVENT_UNK) SetWaitState(WAITSTATE_TURN180, nil); m_standardTimer = 0; @@ -9761,13 +9875,14 @@ CPed::InvestigateEvent(void) animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) { - CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 14.0f); + CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.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); + if (!CGame::germanGame) + Say(SOUND_PED_CHAT_EVENT); } else { m_standardTimer = 0; @@ -9788,7 +9903,7 @@ CPed::InvestigateEvent(void) animToPlay = ANIM_XPRESS_SCRATCH; CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f); - SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); + SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000)); } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) { animAssoc->blendDelta = -8.0f; @@ -9816,7 +9931,8 @@ CPed::InvestigateEvent(void) CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f); SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500)); } - Say(SOUND_PED_CHAT_EVENT); + if (!CGame::germanGame) + Say(SOUND_PED_CHAT_EVENT); } break; case EVENT_ICECREAM: @@ -9878,19 +9994,22 @@ CPed::InvestigateEvent(void) SetMoveState(PEDMOVE_WALK); return; } - if (distSqr > 1.44f) { + if (distSqr > sq(1.2f)) { SetMoveState(PEDMOVE_WALK); return; } + bool willStandStill = false; for (int i = 0; i < m_numNearPeds; i++) { if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) { SetMoveState(PEDMOVE_STILL); - return; + willStandStill = true; + break; } } - SetMoveState(PEDMOVE_WALK); + if (!willStandStill) + SetMoveState(PEDMOVE_WALK); } } @@ -10184,12 +10303,12 @@ CPed::Look(void) TurnBody(); } +// --MIAMI: Done bool CPed::LookForInterestingNodes(void) { CBaseModelInfo *model; CPtrNode *ptrNode; - CVector effectPos; CVector effectDist; C2dEffect *effect; CMatrix *objMat; @@ -10230,7 +10349,7 @@ CPed::LookForInterestingNodes(void) effect = model->Get2dEffect(e); if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { objMat = &veh->GetMatrix(); - effectPos = veh->GetMatrix() * effect->pos; + CVector effectPos = veh->GetMatrix() * effect->pos; effectDist = effectPos - GetPosition(); if (effectDist.MagnitudeSqr() < sq(8.0f)) { found = true; @@ -10248,7 +10367,7 @@ CPed::LookForInterestingNodes(void) effect = model->Get2dEffect(e); if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { objMat = &obj->GetMatrix(); - effectPos = obj->GetMatrix() * effect->pos; + CVector effectPos = obj->GetMatrix() * effect->pos; effectDist = effectPos - GetPosition(); if (effectDist.MagnitudeSqr() < sq(8.0f)) { found = true; @@ -10266,7 +10385,7 @@ CPed::LookForInterestingNodes(void) effect = model->Get2dEffect(e); if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { objMat = &building->GetMatrix(); - effectPos = building->GetMatrix() * effect->pos; + CVector effectPos = building->GetMatrix() * effect->pos; effectDist = effectPos - GetPosition(); if (effectDist.MagnitudeSqr() < sq(8.0f)) { found = true; @@ -10284,7 +10403,7 @@ CPed::LookForInterestingNodes(void) effect = model->Get2dEffect(e); if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) { objMat = &building->GetMatrix(); - effectPos = building->GetMatrix() * effect->pos; + CVector effectPos = building->GetMatrix() * effect->pos; effectDist = effectPos - GetPosition(); if (effectDist.MagnitudeSqr() < sq(8.0f)) { found = true; @@ -10310,12 +10429,13 @@ CPed::LookForInterestingNodes(void) return false; } + CVector2D effectPos = *objMat * effect->pos; switch (effect->attractor.type) { case ATTRACTORTYPE_ICECREAM: - SetInvestigateEvent(EVENT_ICECREAM, CVector2D(effectPos), 0.1f, 15000, angleToFace); + SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace); break; case ATTRACTORTYPE_STARE: - SetInvestigateEvent(EVENT_SHOPSTALL, CVector2D(effectPos), 1.0f, + SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f, CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500), angleToFace); break; @@ -10325,6 +10445,7 @@ CPed::LookForInterestingNodes(void) return true; } +// --MIAMI: Done void CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle) { @@ -10333,7 +10454,7 @@ CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCount SetStoredState(); bFindNewNodeAfterStateRestore = false; - m_nPedState = PED_INVESTIGATE; + SetPedState(PED_INVESTIGATE); m_standardTimer = CTimer::GetTimeInMilliseconds() + time; m_eventType = event; m_eventOrThreat = pos; @@ -10861,7 +10982,7 @@ CPed::ProcessControl(void) CVisibilityPlugins::SetClumpAlpha(GetClump(), alpha); bIsShooting = false; - b158_40 = false; + bDonePositionOutOfCollision = false; BuildPedLists(); bIsInWater = false; bIsDrowning = false; @@ -13017,8 +13138,8 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) } } - if (ped->b157_40) { - ped->b157_40 = false; + if (ped->bRemoveMeWhenIGotIntoCar) { + ped->bRemoveMeWhenIGotIntoCar = false; ped->bRemoveFromWorld = true; } if (ped->bCollectBusFare) { @@ -13435,6 +13556,7 @@ CPed::ReactToPointGun(CEntity *entWithGun) } } +// --MIAMI: Done void CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) { @@ -13458,8 +13580,17 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) } ped->bInVehicle = false; - if (veh && (veh->IsCar() || veh->IsBike()) && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) { - ped->PositionPedOutOfCollision(); + if (veh && (veh->IsCar() || veh->IsBike())) { + CWorld::pIgnoreEntity = veh; + if (CWorld::TestSphereAgainstWorld(ped->GetPosition() - CVector(0.f, 0.f, 0.2f), + 0.4f, veh, true, true, false, false, false, false) + || CWorld::TestSphereAgainstWorld(ped->GetPosition() + CVector(0.f, 0.f, 0.2f), + 0.4f, veh, true, true, false, false, false, false) + || !CWorld::GetIsLineOfSightClear(veh->GetPosition(), ped->GetPosition(), true, false, false, true, false, false, false)) { + CWorld::pIgnoreEntity = nil; + ped->PositionPedOutOfCollision(); + } + CWorld::pIgnoreEntity = nil; } if (ped->m_nPedState == PED_EXIT_CAR) { @@ -13543,6 +13674,7 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) } } } + // NB: Probably VC doesn't use a function for that, so it's GetBikeDoorFlag doesn't check for CAR_WINDSCREEN if (veh && veh->IsBike()) veh->m_nGettingOutFlags &= ~GetBikeDoorFlag(ped->m_vehEnterType); else @@ -13555,6 +13687,11 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) veh->m_nDoorLock = CARLOCK_UNLOCKED; if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle()) veh->ChangeLawEnforcerState(false); + if (veh->IsBike()) { + if (Abs(veh->m_vecMoveSpeed.x) < 0.1 && Abs(veh->m_vecMoveSpeed.y) < 0.1f) { + ((CBike*)veh)->bIsStanding = true; + } + } } else { veh->RemovePassenger(ped); } @@ -13817,6 +13954,146 @@ CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void bool CPed::PositionPedOutOfCollision(void) +{ + CVehicle *veh = m_pMyVehicle; + if (!veh) + return false; + + if (bDonePositionOutOfCollision) + return true; + + bool foundAPos = false; + CColModel *vehCol = veh->GetColModel(); + CVector vehPos = veh->GetPosition(); + CVector ourPos = GetPosition(); + CVector newPos = ourPos; + CWorld::pIgnoreEntity = veh; + bUsesCollision = false; + bJustCheckCollision = true; + m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + if (veh->IsOnItsSide()) { + // Top of the veh. + newPos = vehPos; + newPos.z = FEET_OFFSET + vehCol->boundingBox.max.x + vehPos.z; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + + } else if (m_vehEnterType != 0) { + // Try the normal way + CVector pos = GetPositionToOpenCarDoor(m_pMyVehicle, m_vehEnterType); + newPos = pos; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + + float vehRelativeExitX = vehCol->boundingBox.min.x - 0.355f; + if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) + vehRelativeExitX = 0.355f + vehCol->boundingBox.max.x; + + if (!foundAPos) { + // Check sides of veh., respective to seat column-veh. center difference(why?) + float exitOffset = vehRelativeExitX - DotProduct(ourPos - vehPos, veh->GetRight()); + newPos = exitOffset * veh->GetRight() + ourPos; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + if (!foundAPos) { + // Iterate through sections of veh. length + static offset on X + float minY = vehCol->boundingBox.min.y; + float ySection = (vehCol->boundingBox.max.y - minY) / 3.f; + for (int i = 0; i < 4; i++) { + float fwdMult = i * ySection + minY; + newPos = vehRelativeExitX * veh->GetRight() + fwdMult * veh->GetForward() + vehPos; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) { + foundAPos = true; + break; + } + } + } + } + if (!foundAPos) { + // Back of veh. + newPos = (vehCol->boundingBox.min.y - 0.355f) * veh->GetForward() + vehPos; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + if (!foundAPos) { + // Front of veh. + newPos = (0.355f + vehCol->boundingBox.max.y) * veh->GetForward() + vehPos; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + if (!foundAPos) { + // Opposite X side + back + newPos = vehCol->boundingBox.min.y * veh->GetForward() + vehPos - vehRelativeExitX * veh->GetRight(); + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + if (!foundAPos) { + // Opposite X side + front + newPos = vehCol->boundingBox.max.y * veh->GetForward() + vehPos - vehRelativeExitX * veh->GetRight(); + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + if (!foundAPos) { + // Top of veh. + if (veh->m_vehType == 0) { + newPos = vehCol->boundingBox.max.z * veh->GetUp() + vehPos; + newPos.z += FEET_OFFSET; + GetMatrix().SetTranslate(newPos); + if (!CheckCollision()) { + if (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) + foundAPos = true; + } + } + } + m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + m_vecTurnSpeed = CVector(0.f, 0.f, 0.f); + veh->m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + veh->m_vecTurnSpeed = CVector(0.f, 0.f, 0.f); + CWorld::pIgnoreEntity = nil; + bUsesCollision = true; + bJustCheckCollision = false; + bDonePositionOutOfCollision = true; + if (foundAPos) + return true; + int foundNode = ThePaths.FindNodeClosestToCoors(vehPos, PATH_PED, 999999.9f, true, false, false, false); + if (foundNode < 0) + return false; + newPos = ThePaths.m_pathNodes[foundNode].GetPosition(); + CPedPlacement::FindZCoorForPed(&newPos); + GetMatrix().SetTranslate(newPos); + SetHeading(m_pMyVehicle->GetForward().Heading()); + return true; +} + +// --MIAMI: Done +// "Any" means he shouldn't have to be in vehicle. +bool +CPed::PositionAnyPedOutOfCollision(void) { CVehicle *veh; CVector posNearVeh; @@ -13826,9 +14103,6 @@ CPed::PositionPedOutOfCollision(void) int smallestDistNearVeh = 999; int smallestDistSomewhereClose = 999; - if (!m_pMyVehicle) - return false; - CVector vehPos = m_pMyVehicle->GetPosition(); CVector potentialPos; potentialPos.y = GetPosition().y - 3.5f; @@ -13839,15 +14113,7 @@ CPed::PositionPedOutOfCollision(void) for (int xTry = 0; xTry < 15; xTry++) { CPedPlacement::FindZCoorForPed(&potentialPos); - CVector distVec = potentialPos - vehPos; - float dist = distVec.Magnitude(); - - // Makes close distances bigger for some reason. - float mult = (0.6f + dist) / dist; - CVector adjustedPotentialPos = distVec * mult + vehPos; - if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false) - && !CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) { - + if (!CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) { float potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr(); veh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false); if (veh) { @@ -13881,6 +14147,7 @@ CPed::PositionPedOutOfCollision(void) return true; } +// --MIAMI: Done bool CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh) { @@ -14060,6 +14327,7 @@ CPed::Render(void) } } +// --MIAMI: Done void CPed::ProcessObjective(void) { @@ -14097,15 +14365,6 @@ CPed::ProcessObjective(void) } switch (m_objective) { - case OBJECTIVE_NONE: - case OBJECTIVE_GUARD_AREA: - case OBJECTIVE_FOLLOW_CAR_IN_CAR: - case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: - case OBJECTIVE_DESTROY_OBJECT: - case OBJECTIVE_GOTO_AREA_IN_CAR: - case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: - case OBJECTIVE_SET_LEADER: - break; case OBJECTIVE_WAIT_ON_FOOT: if (GetPedState() == PED_DRIVING) m_objective = OBJECTIVE_NONE; @@ -14190,7 +14449,7 @@ CPed::ProcessObjective(void) { if (m_pedInObjective) { if (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR - && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops + && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0 && !bKindaStayInSamePlace) { SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); @@ -14230,7 +14489,7 @@ CPed::ProcessObjective(void) float closestVehDist = 60.0f; int16 lastVehicle; CEntity* vehicles[8]; - CWorld::FindObjectsInRange(GetPosition(), 30.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); CVehicle *foundVeh = nil; for(int i = 0; i < lastVehicle; i++) { CVehicle *nearVeh = (CVehicle*)vehicles[i]; @@ -14303,7 +14562,6 @@ CPed::ProcessObjective(void) SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); break; } - if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) { bObjectiveCompleted = true; ClearLookFlag(); @@ -14553,7 +14811,7 @@ CPed::ProcessObjective(void) if (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) { distWithTarget = m_carInObjective->GetPosition() - GetPosition(); if (!bInVehicle) { - if (nEnterCarRangeMultiplier * 30.0f < distWithTarget.Magnitude()) { + if (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) { if (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen()) WarpPedToNearEntityOffScreen(m_carInObjective); @@ -14579,6 +14837,15 @@ CPed::ProcessObjective(void) } break; } + case OBJECTIVE_DESTROY_OBJECT: + if (m_pPointGunAt) { + if (m_nPedState != PED_ATTACK) + SetAttack(m_pPointGunAt); + } else { + bScriptObjectiveCompleted = true; + RestorePreviousObjective(); + } + break; case OBJECTIVE_DESTROY_CAR: { if (!m_carInObjective) { @@ -14602,9 +14869,7 @@ CPed::ProcessObjective(void) break; } - if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE - && distWithTargetSc < wepRange) { - + if (m_attackTimer < CTimer::GetTimeInMilliseconds() && distWithTargetSc < wepRange) { // I hope so CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); CVector maxShotPos = m_carInObjective->GetPosition() - ourHead; @@ -14619,6 +14884,8 @@ CPed::ProcessObjective(void) CWorld::bIncludeDeadPeds = false; if (foundEnt == m_carInObjective) { SetAttack(m_carInObjective); + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference((CEntity**)&m_pPointGunAt); m_pPointGunAt = m_carInObjective; if (m_pPointGunAt) m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt); @@ -14632,75 +14899,30 @@ CPed::ProcessObjective(void) } } } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) { + if (wepRange <= 5.0f) { + if (Abs(distWithTarget.x) > wepRange || Abs(distWithTarget.y) > wepRange || + (distWithTarget.z > -1.0f && distWithTarget.z < 0.3)) { + SetSeek(m_carInObjective, 3.0f); + SetMoveState(PEDMOVE_RUN); + } else { + SetIdle(); + } + } else { + float safeDistance = wepRange * 0.25f; - float safeDistance; - if (wepRange <= 5.0f) - safeDistance = 3.0f; - else - safeDistance = wepRange * 0.25f; - - SetSeek(m_carInObjective, safeDistance); - SetMoveState(PEDMOVE_RUN); + SetSeek(m_carInObjective, safeDistance); + SetMoveState(PEDMOVE_RUN); + } } SetLookFlag(m_carInObjective, false); TurnBody(); break; } - case OBJECTIVE_GOTO_AREA_ANY_MEANS: - { - distWithTarget = m_nextRoutePointPos - GetPosition(); - distWithTarget.z = 0.0f; - if (InVehicle()) { - CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos); - CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle); - if (distWithTarget.MagnitudeSqr() < sq(20.0f)) { - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); - SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); - } - break; - } - if (distWithTarget.Magnitude() > 30.0f) { - if (m_pMyVehicle) { - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - } else { - float closestVehDist = SQR(60.0f); - int16 lastVehicle; - CEntity* vehicles[8]; - CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); - CVehicle* foundVeh = nil; - for (int i = 0; i < lastVehicle; i++) { - CVehicle* nearVeh = (CVehicle*)vehicles[i]; - /* - Not used. - CVector vehSpeed = nearVeh->GetSpeed(); - CVector ourSpeed = GetSpeed(); - */ - CVector vehDistVec = nearVeh->GetPosition() - GetPosition(); - if (vehDistVec.MagnitudeSqr() < closestVehDist - && m_pedInObjective->m_pMyVehicle != nearVeh) - { - foundVeh = nearVeh; - closestVehDist = vehDistVec.MagnitudeSqr(); - } - } - m_pMyVehicle = foundVeh; - if (m_pMyVehicle) { - m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); - } - } - break; - } - // fall through - } case OBJECTIVE_GOTO_AREA_ON_FOOT: case OBJECTIVE_RUN_TO_AREA: case OBJECTIVE_SPRINT_TO_AREA: { - if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA) - && InVehicle()) { + if (InVehicle()) { SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } else { distWithTarget = m_nextRoutePointPos - GetPosition(); @@ -14717,7 +14939,6 @@ CPed::ProcessObjective(void) if (!m_pNextPathNode) { bool found = FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); if (m_pNextPathNode) { - // Because it already does that if it finds better coords. if (!found) { bestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); @@ -14731,6 +14952,7 @@ CPed::ProcessObjective(void) if (m_pNextPathNode) m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); } + CVector seekPos = m_vecSeekPos; SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); } } @@ -14767,7 +14989,8 @@ CPed::ProcessObjective(void) int nextPoint = GetNextPointOnRoute(); m_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint); } else { - SetSeek(m_nextRoutePointPos, 0.8f); + CVector seekPos = m_nextRoutePointPos; + SetSeek(seekPos, 0.8f); } break; case OBJECTIVE_SOLICIT_VEHICLE: @@ -14831,31 +15054,27 @@ CPed::ProcessObjective(void) } case OBJECTIVE_BUY_ICE_CREAM: if (m_carInObjective) { - if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM) + if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM && m_nPedState != PED_CHAT) SetSeekCar(m_carInObjective, 0); - } else { - RestorePreviousObjective(); - RestorePreviousState(); - if (IsPedInControl()) - m_pMyVehicle = nil; } break; case OBJECTIVE_STEAL_ANY_CAR: + case OBJECTIVE_STEAL_ANY_MISSION_CAR: { if (bInVehicle) { bScriptObjectiveCompleted = true; RestorePreviousObjective(); } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) { CVehicle *carToSteal = nil; - float closestCarDist = 30.0f; + float closestCarDist = nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST; CVector pos = GetPosition(); int16 lastVehicle; CEntity *vehicles[8]; - CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + CWorld::FindObjectsInRange(pos, closestCarDist, true, &lastVehicle, 6, vehicles, false, true, false, false, false); for(int i = 0; i < lastVehicle; i++) { CVehicle *nearVeh = (CVehicle*)vehicles[i]; - if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { + if (m_objective == OBJECTIVE_STEAL_ANY_MISSION_CAR || nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) { if (nearVeh->CanPedOpenLocks(this)) { CVector vehDistVec = GetPosition() - nearVeh->GetPosition(); @@ -14968,60 +15187,6 @@ CPed::ProcessObjective(void) CPed::SetWanderPath(m_nPathDir); } break; - case OBJECTIVE_FLEE_CAR: - if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) { - RestorePreviousObjective(); - SetFlee(m_pMyVehicle, 6000); - break; - } - // fall through - case OBJECTIVE_LEAVE_CAR: - if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (InVehicle() && - (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() || bBusJacked)) { - - if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN - && (m_nPedType != PEDTYPE_COP - || m_pMyVehicle->IsBoat() - || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) { -#ifdef GTA_TRAIN - if (m_pMyVehicle->IsTrain()) - SetExitTrain(m_pMyVehicle); - else -#endif - if (m_pMyVehicle->IsBoat()) - SetExitBoat(m_pMyVehicle); - else - SetExitCar(m_pMyVehicle, 0); - } - } else { - RestorePreviousObjective(); - } - } - if (bHeldHostageInCar) { - if (CTheScripts::IsPlayerOnAMission()) { - CVehicle *playerVeh = FindPlayerVehicle(); - if (playerVeh && playerVeh->IsPassenger(this)) { - if (m_leaveCarTimer != 0) - m_leaveCarTimer = 0; - } - } - } - break; - case OBJECTIVE_AIM_GUN_AT: - if (m_pedInObjective) { - if (!bObstacleShowedUpDuringKillObjective) - SetPointGunAt(m_pedInObjective); - - if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { - SetLookFlag(m_pedInObjective, false); - TurnBody(); - } - } else { - ClearObjective(); - } - break; -#ifdef VC_PED_PORTS case OBJECTIVE_LEAVE_CAR_AND_DIE: { if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { @@ -15049,6 +15214,59 @@ CPed::ProcessObjective(void) } break; } + case OBJECTIVE_GOTO_AREA_ANY_MEANS: + { + distWithTarget = m_nextRoutePointPos - GetPosition(); + distWithTarget.z = 0.0f; + if (InVehicle()) { + CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos); + CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle); + if (distWithTarget.MagnitudeSqr() < sq(20.0f)) { + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + } + break; + } + if (distWithTarget.Magnitude() > 30.0f) { + if (m_pMyVehicle) { + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + } else { + float closestVehDist = SQR(60.0f); + int16 lastVehicle; + CEntity* vehicles[8]; + // NB: 25.0f in here is prolly a forgotten setting, all other places now use 30.0f (ENTER_CAR_MAX_DIST) + CWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); + CVehicle* foundVeh = nil; + for (int i = 0; i < lastVehicle; i++) { + CVehicle* nearVeh = (CVehicle*)vehicles[i]; + /* + Not used. + CVector vehSpeed = nearVeh->GetSpeed(); + CVector ourSpeed = GetSpeed(); + */ + CVector vehDistVec = nearVeh->GetPosition() - GetPosition(); + if (vehDistVec.MagnitudeSqr() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh) { + foundVeh = nearVeh; + closestVehDist = vehDistVec.MagnitudeSqr(); + } + } + m_pMyVehicle = foundVeh; + if (m_pMyVehicle) { + m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle); + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); + } + } + break; + } + // Falls to different objectives in III and VC +#ifdef FIX_BUGS + break; +#else + // fall through +#endif + } case OBJECTIVE_GOTO_SEAT_ON_FOOT: case OBJECTIVE_GOTO_ATM_ON_FOOT: case OBJECTIVE_GOTO_BUS_STOP_ON_FOOT: @@ -15059,8 +15277,7 @@ CPed::ProcessObjective(void) m_objectiveTimer = 0; if (m_attractor) GetPedAttractorManager()->DeRegisterPed(this, m_attractor); - } - else { + } else { CVector distance = m_nextRoutePointPos - GetPosition(); distance.z = 0.0f; if (m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT) { @@ -15176,6 +15393,59 @@ CPed::ProcessObjective(void) } } return; + case OBJECTIVE_FLEE_CAR: + if (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) { + RestorePreviousObjective(); + SetFlee(m_pMyVehicle, 6000); + break; + } + // fall through + case OBJECTIVE_LEAVE_CAR: + if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { + if (InVehicle() && + (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() || bBusJacked)) { + + if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN + && (m_nPedType != PEDTYPE_COP + || m_pMyVehicle->IsBoat() + || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) { +#ifdef GTA_TRAIN + if (m_pMyVehicle->IsTrain()) + SetExitTrain(m_pMyVehicle); + else +#endif + if (m_pMyVehicle->IsBoat()) + SetExitBoat(m_pMyVehicle); + else + SetExitCar(m_pMyVehicle, 0); + } + } else { + RestorePreviousObjective(); + } + } + if (bHeldHostageInCar) { + if (CTheScripts::IsPlayerOnAMission()) { + CVehicle *playerVeh = FindPlayerVehicle(); + if (playerVeh && playerVeh->IsPassenger(this)) { + if (m_leaveCarTimer != 0) + m_leaveCarTimer = 0; + } + } + } + break; + case OBJECTIVE_AIM_GUN_AT: + if (m_pedInObjective) { + if (!bObstacleShowedUpDuringKillObjective) + SetPointGunAt(m_pedInObjective); + + if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { + SetLookFlag(m_pedInObjective, false); + TurnBody(); + } + } else { + ClearObjective(); + } + break; case OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER: SetIdle(); if (m_attractor && CWeather::Rain < 0.2f) @@ -15207,8 +15477,8 @@ CPed::ProcessObjective(void) } else if (m_pedInObjective) { SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, m_pedInObjective); } - } else { SetMoveAnim(); + } else { ClearLookFlag(); SetMoveAnim(); if (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle()) @@ -15268,7 +15538,7 @@ CPed::ProcessObjective(void) GetPedAttractorManager()->DeRegisterPed(this, m_attractor); SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus); bDontDragMeOutCar = true; - b157_40 = true; + bRemoveMeWhenIGotIntoCar = true; CPlayerPed *player = FindPlayerPed(); if (pBus->IsPassenger(player) || pBus->IsDriver(player)) { bCollectBusFare = true; @@ -15309,7 +15579,6 @@ CPed::ProcessObjective(void) } break; } -#endif } if (bObjectiveCompleted || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { @@ -15329,6 +15598,7 @@ CPed::ProcessObjective(void) } } +// --MIAMI: Done void CPed::SetShootTimer(uint32 time) { @@ -16441,7 +16711,78 @@ CPed::PreRender(void) RwMatrixScale(head, &zero, rwCOMBINEPRECONCAT); } - // TODO(Miami): Some cheat?? + if (IsPlayer() && gfTommyFatness != 1.0f) { + RpHAnimHierarchy* hier = GetAnimHierarchyFromSkinClump(GetClump()); + int32 idx; + RwV3d scale; + + scale.x = 1.0f; + scale.y = 1.0f + gfTommyFatness * 0.7f; + scale.z = 1.0f + gfTommyFatness * 0.7f; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD)); + RwMatrix* head = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(head, &scale, rwCOMBINEPRECONCAT); + + scale.y = 1.0f + gfTommyFatness * 0.2f; + scale.z = 1.0f + gfTommyFatness * 0.2f; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_NECK)); + RwMatrix* neck = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(neck, &scale, rwCOMBINEPRECONCAT); + + scale.y = 1.0f + gfTommyFatness * 0.5f; + scale.z = 1.0f + gfTommyFatness * 0.5f; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_MID)); + RwMatrix* mid = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(mid, &scale, rwCOMBINEPRECONCAT); + + scale.y = 1.0f + gfTommyFatness; + scale.z = 1.0f + gfTommyFatness; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERLEGL)); + RwMatrix* upperLegL = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(upperLegL, &scale, rwCOMBINEPRECONCAT); + + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERLEGR)); + RwMatrix* upperLegR = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(upperLegR, &scale, rwCOMBINEPRECONCAT); + + scale.y = 1.0f + gfTommyFatness * 0.5f; + scale.z = 1.0f + gfTommyFatness * 0.5f; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_LOWERLEGR)); + RwMatrix* lowerLegR = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(lowerLegR, &scale, rwCOMBINEPRECONCAT); + + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_LOWERLEGL)); + RwMatrix* lowerLegL = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(lowerLegL, &scale, rwCOMBINEPRECONCAT); + + scale.y = 1.0f + gfTommyFatness * 0.23f; + scale.z = 1.0f + gfTommyFatness * 0.23f; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOOTL)); + RwMatrix* footL = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(footL, &scale, rwCOMBINEPRECONCAT); + + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOOTR)); + RwMatrix* footR = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(footR, &scale, rwCOMBINEPRECONCAT); + + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERARML)); + RwMatrix* upperArmL = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(upperArmL, &scale, rwCOMBINEPRECONCAT); + + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERARMR)); + RwMatrix* upperArmR = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(upperArmR, &scale, rwCOMBINEPRECONCAT); + + scale.y = 1.0f + gfTommyFatness * 0.2f; + scale.z = 1.0f + gfTommyFatness * 0.2f; + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOREARML)); + RwMatrix* foreArmL = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(foreArmL, &scale, rwCOMBINEPRECONCAT); + + idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOREARMR)); + RwMatrix* foreArmR = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwMatrixScale(foreArmR, &scale, rwCOMBINEPRECONCAT); + } if (bBodyPartJustCameOff && bIsPedDieAnimPlaying && m_bodyPartBleeding != -1 && (CTimer::GetFrameCounter() & 7) > 3) { CVector bloodDir(0.0f, 0.0f, 0.0f); @@ -16512,15 +16853,14 @@ CPed::PreRender(void) } } +// --MIAMI: Done void CPed::ProcessBuoyancy(void) { + float buoyancyLevel = 1.1f; static uint32 nGenerateRaindrops = 0; static uint32 nGenerateWaterCircles = 0; - CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f), - ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f), - ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f), - (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48); + CRGBA color; if (bInVehicle) return; @@ -16528,26 +16868,27 @@ CPed::ProcessBuoyancy(void) CVector buoyancyPoint; CVector buoyancyImpulse; -#ifndef VC_PED_PORTS - float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f); -#else - float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f); -#endif + if (DyingOrDead()) + buoyancyLevel = 1.8f; if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) { bTouchingWater = true; CEntity *entity; CColPoint point; if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil) - && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) { + && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat() && !entity->bRenderScorched) { bIsInWater = false; return; } + color.r = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f; + color.g = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f; + color.b = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f; + color.a = (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48; bIsInWater = true; ApplyMoveForce(buoyancyImpulse); if (!DyingOrDead()) { if (bTryingToReachDryLand) { - if (buoyancyImpulse.z / m_fMass > 0.0032f * CTimer::GetTimeStep()) { + if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) { bTryingToReachDryLand = false; CVector pos = GetPosition(); if (PlacePedOnDryLand()) { @@ -16559,19 +16900,15 @@ CPed::ProcessBuoyancy(void) bIsInTheAir = false; } pos.z = pos.z - 0.8f; -#ifdef PC_PARTICLE CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true); -#else - CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true); -#endif m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); return; } } } float speedMult = 0.0f; - if (buoyancyImpulse.z / m_fMass > 0.006f * CTimer::GetTimeStep() + if (buoyancyImpulse.z / m_fMass > GRAVITY * CTimer::GetTimeStep() || mod_Buoyancy.m_waterlevel > GetPosition().z) { speedMult = pow(0.9f, CTimer::GetTimeStep()); m_vecMoveSpeed.x *= speedMult; @@ -16581,7 +16918,7 @@ CPed::ProcessBuoyancy(void) bIsDrowning = true; InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); } - if (buoyancyImpulse.z / m_fMass > 0.002f * CTimer::GetTimeStep()) { + if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) { if (speedMult == 0.0f) { speedMult = pow(0.9f, CTimer::GetTimeStep()); } @@ -16593,7 +16930,6 @@ CPed::ProcessBuoyancy(void) } else { m_vecMoveSpeed.z = -0.01f; DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f); -#ifdef PC_PARTICLE CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition(); float level = 0.0f; if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) @@ -16602,18 +16938,6 @@ CPed::ProcessBuoyancy(void) CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true); nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80; nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100; -#else - CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition(); - float level = 0.0f; - if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) - aBitForward.z = level + 0.5f; - - CVector vel = m_vecMoveSpeed * 0.1f; - vel.z = 0.18f; - CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true); - nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300; - nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60; -#endif } } } else @@ -16630,15 +16954,9 @@ CPed::ProcessBuoyancy(void) if (pos.z != 0.0f) { nGenerateWaterCircles = 0; for(int i = 0; i < 4; i++) { -#ifdef PC_PARTICLE pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0); -#else - pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); - pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); - CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f)); -#endif } } } @@ -16650,17 +16968,9 @@ CPed::ProcessBuoyancy(void) pos.z = level; if (pos.z >= 0.0f) { -#ifdef PC_PARTICLE pos.z += 0.25f; -#else - pos.z += 0.5f; -#endif nGenerateRaindrops = 0; -#ifdef PC_PARTICLE CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true); -#else - CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true); -#endif } } } @@ -19399,10 +19709,7 @@ CPed::Solicit(void) void CPed::SetExitBoat(CVehicle *boat) { - if (m_nPedState == PED_FOLLOW_PATH) { - ClearFollowPath(); - } - m_nPedState = PED_IDLE; + SetPedState(PED_IDLE); CVector newPos = GetPosition(); RemoveInCarAnims(); CColModel* boatCol = boat->GetColModel(); @@ -20871,6 +21178,46 @@ CPed::ScanForDelayedResponseThreats(void) m_threatCheckTimer = 0; } +// --MIAMI: Done +void +CPed::DeleteSunbatheIdleAnimCB(CAnimBlendAssociation *assoc, void *arg) +{ + CPed *ped = (CPed*) arg; + + if (CTimer::GetTimeInMilliseconds() <= ped->m_nWaitTimer + && !ped->bGotUpOfMyOwnAccord && !ped->bFleeWhenStanding && !ped->m_threatEx) { + ped->m_pNextPathNode = nil; + ped->bFleeWhenStanding = true; + ped->m_threatEx = FindPlayerPed(); + ped->SetGetUp(); + ped->ClearWaitState(); + } + ped->m_nWaitTimer = 0; + ped->RestoreHeadingRate(); + ped->Wait(); +} + +// --MIAMI: Done +void +CPed::PedSetPreviousStateCB(CAnimBlendAssociation* assoc, void* arg) +{ + CPed* ped = (CPed*)arg; + ped->RestorePreviousState(); + ped->m_pVehicleAnim = nil; +} + +// --MIAMI: Done +void +CPed::PedAnimShuffleCB(CAnimBlendAssociation* assoc, void* arg) +{ + CPed *ped = (CPed*)arg; + if (ped->EnteringCar()) { + PedSetInCarCB(nil, ped); + } else if (ped->m_nPedState != PED_DRIVING) { + ped->QuitEnteringCar(); + } +} + // --MIAMI: Done void PlayRandomAnimationsFromAnimBlock(CPed* ped, AssocGroupId animGroup, uint32 first, uint32 amount) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 815d9c2d..752973bc 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -14,6 +14,7 @@ #define FEET_OFFSET 1.04f #define CHECK_NEARBY_THINGS_MAX_DIST 15.0f +#define ENTER_CAR_MAX_DIST 30.0f class CAccident; class CObject; @@ -358,6 +359,8 @@ enum eMoveState { PEDMOVE_THROWN }; +extern float gfTommyFatness; + class CVehicle; class CPed : public CPhysical @@ -457,8 +460,8 @@ public: uint32 bHasAlreadyUsedAttractor : 1; uint32 b155_2 : 1; uint32 bCarPassenger : 1; - uint32 b155_8 : 1; - uint32 b155_10 : 1; + uint32 bFleeWhenStanding : 1; + uint32 bGotUpOfMyOwnAccord : 1; uint32 bMiamiViceCop : 1; uint32 bMoneyHasBeenGivenByScript : 1; // uint32 bHasBeenPhotographed : 1; // @@ -475,10 +478,10 @@ public: uint32 bDontFight : 1; uint32 bDoomAim : 1; uint32 bCanBeShotInVehicle : 1; - uint32 b157_8 : 1; + uint32 bCanGiveUpSunbathing : 1; uint32 bMakeFleeScream : 1; uint32 bPushedAlongByCar : 1; - uint32 b157_40 : 1; + uint32 bRemoveMeWhenIGotIntoCar : 1; uint32 bIgnoreThreatsBehindObjects : 1; uint32 bNeverEverTargetThisPed : 1; @@ -487,7 +490,7 @@ public: uint32 b158_8 : 1; uint32 bCollectBusFare : 1; uint32 bBoughtIceCream : 1; - uint32 b158_40 : 1; + uint32 bDonePositionOutOfCollision : 1; uint32 b158_80 : 1; // our own flags @@ -580,7 +583,7 @@ public: float m_fleeFromPosY; CEntity *m_fleeFrom; uint32 m_fleeTimer; - CEntity* pThreatEx; // TODO(Miami): What is this? + CEntity* m_threatEx; // TODO(Miami): What is this? CEntity* m_collidingEntityWhileFleeing; uint32 m_collidingThingTimer; CEntity *m_pCollidingEntity; @@ -831,6 +834,7 @@ public: void ReactToPointGun(CEntity*); void SeekCar(void); bool PositionPedOutOfCollision(void); + bool PositionAnyPedOutOfCollision(void); bool RunToReportCrime(eCrimeType); bool PlacePedOnDryLand(void); bool PossiblyFindBetterPosToSeekCar(CVector*, CVehicle*); @@ -905,6 +909,9 @@ public: static void RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg); static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); + static void DeleteSunbatheIdleAnimCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetPreviousStateCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimShuffleCB(CAnimBlendAssociation *assoc, void *arg); bool IsPlayer(void); bool IsFemale(void) { return m_nPedType == PEDTYPE_CIVFEMALE || m_nPedType == PEDTYPE_PROSTITUTE; } diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 77d2af2a..31bf92a8 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -1611,13 +1611,13 @@ void CScriptPath::Clear(void) { m_state = SCRIPT_PATH_DISABLED; } -void CScriptPath::InitialiseOne(int32 numNodes, float width) { +void CScriptPath::InitialiseOne(int32 numNodes, float length) { char Dest[32]; sprintf(Dest, "data\\paths\\spath%d.dat", numNodes); m_pNode = CPlane::LoadPath(Dest, m_numNodes, m_fTotalLength, false); m_fSpeed = 1.0f; m_fPosition = 0.0f; - m_fObjectLength = width; + m_fObjectLength = length; m_state = SCRIPT_PATH_INITIALIZED; } @@ -1697,7 +1697,7 @@ INITSAVEBUF VALIDATESAVEBUF(*size); } -CObject* g_pScriptPathObjects[18]; +CObject *g_pScriptPathObjects[18]; void CScriptPaths::Load_ForReplay(void) { for (int i = 0; i < 3; i++) { diff --git a/src/render/Fluff.h b/src/render/Fluff.h index a31ac335..0fc57c73 100644 --- a/src/render/Fluff.h +++ b/src/render/Fluff.h @@ -24,7 +24,7 @@ public: void Clear(void); void Update(void); - void InitialiseOne(int32 numNodes, float width); + void InitialiseOne(int32 numNodes, float length); void FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ); void SetObjectToControl(CObject *pObj); }; diff --git a/src/render/Glass.h b/src/render/Glass.h index 736e5205..937ab6a9 100644 --- a/src/render/Glass.h +++ b/src/render/Glass.h @@ -53,4 +53,5 @@ public: //TODO(MIAMI) static void CarWindscreenShatters(CVehicle *vehicle, bool unk) {} + static void BreakGlassPhysically(CVector, float) {} }; \ No newline at end of file diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index cbf3c7f2..c05a3d31 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -21,6 +21,8 @@ #include "User.h" #include "World.h" #include "CutsceneMgr.h" +#include "Stats.h" +#include "main.h" // Game has colors inlined in code. // For easier modification we collect them here: @@ -91,6 +93,8 @@ float CHud::PagerXOffset; int16 CHud::PagerTimer; int16 CHud::PagerOn; +wchar *prevChaseString; + uint32 CHud::m_WantedFadeTimer; uint32 CHud::m_WantedState; uint32 CHud::m_WantedTimer; @@ -524,6 +528,53 @@ void CHud::Draw() } } + static int32 nMediaLevelCounter = 0; + if (CStats::ShowChaseStatOnScreen != 0) { + float fCurAttentionLevel = CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention; + if (0.7f * CStats::HighestChaseValue > fCurAttentionLevel + || fCurAttentionLevel <= 40.0f || CTheScripts::IsPlayerOnAMission()) { + nMediaLevelCounter = 0; + } + else { + if (fCurAttentionLevel == CStats::HighestChaseValue) { + sprintf(gString, "%s %d", UnicodeToAscii(TheText.Get("CHSE")), (int32)fCurAttentionLevel); + } + else { + sprintf(gString, "%s %d" "-%d-", UnicodeToAscii(TheText.Get("CHSE")), (int32)fCurAttentionLevel, (int32)CStats::HighestChaseValue); + } + AsciiToUnicode(gString, gUString); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetPropOff(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + + CRGBA colour; + if (CTimer::GetTimeInMilliseconds() & 0x200) + colour = CRGBA(204, 0, 185, 180); + else + colour = CRGBA(178, 0, 162, 180); + CFont::SetColor(colour); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(113.0f), gUString); + + if (CStats::FindChaseString(fCurAttentionLevel) != prevChaseString) { + prevChaseString = CStats::FindChaseString(fCurAttentionLevel); + nMediaLevelCounter = 100; + } + + if (nMediaLevelCounter != 0) { + nMediaLevelCounter--; + UnicodeMakeUpperCase(gUString, CStats::FindChaseString(fCurAttentionLevel)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(138.0f), gUString); + } + } + } + /* DrawZoneName */ diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index e9079bef..fa8379f0 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -32,6 +32,7 @@ RwIm3DVertex TraceVertices[6]; RwImVertexIndex TraceIndexList[12]; bool CSpecialFX::bSnapShotActive; +int32 CSpecialFX::SnapShotFrames; void CSpecialFX::Init(void) diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h index 8c79856b..8bd0d5e1 100644 --- a/src/render/SpecialFX.h +++ b/src/render/SpecialFX.h @@ -4,6 +4,7 @@ class CSpecialFX { public: static bool bSnapShotActive; + static int32 SnapShotFrames; static void Render(void); static void Update(void); @@ -56,6 +57,13 @@ public: static void AddTrace(CVector*, CVector*); static void Render(void); static void Update(void); + +//TODO(MIAMI) + static void AddTrace(CVector *, CVector *, float, unsigned int, unsigned char) {} + static void AddTrace(CVector *a, CVector *b, int32 weapontype, class CEntity *shooter) + { + AddTrace(a, b); //TODO: temp + } }; enum diff --git a/src/text/Text.cpp b/src/text/Text.cpp index dab1cae3..64f303eb 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -494,6 +494,20 @@ UnicodeToAsciiForMemoryCard(wchar *src) return aStr; } +void +UnicodeMakeUpperCase(wchar *dst, wchar *src) //idk what to do with it, seems to be incorrect implementation by R* +{ + while (*src != '\0') { + if (*src < 'a' || *src > 'z') + *dst = *src; + else + *dst = *src - 32; + dst++; + src++; + } + *dst = '\0'; +} + void UnicodeStrcpy(wchar *dst, const wchar *src) { diff --git a/src/text/Text.h b/src/text/Text.h index d163b9c9..0bad9a83 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -8,6 +8,7 @@ void UnicodeStrcpy(wchar *dst, const wchar *src); void UnicodeStrcat(wchar *dst, wchar *append); int UnicodeStrlen(const wchar *str); void TextCopy(wchar *dst, const wchar *src); +void UnicodeMakeUpperCase(wchar *dst, wchar *src); struct CKeyEntry { diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 0cd439c2..48f90897 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -32,51 +32,20 @@ #include "World.h" #include "SurfaceTable.h" #include "Bike.h" +#include "Glass.h" +#include "Sprite.h" +#include "Pickups.h" // TODO(Miami) #define AUDIO_NOT_READY -// TODO(Miami): Those are mostly placeholders!!! -uint16 gReloadSampleTime[] = -{ - 0, // UNARMED - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, // GRENADE - 0, // DETONATEGRENADE - 0, // TEARGAS - 0, // MOLOTOV - 0, // ROCKET - 250, // COLT45 - 250, // PYTHON - 650, // SHOTGUN - 650, // SPAS12 SHOTGUN - 650, // STUBBY SHOTGUN - 400, // TEC9 - 400, // UZIhec - 400, // SILENCED_INGRAM - 400, // MP5 - 300, // M16 - 300, // AK47 - 423, // SNIPERRIFLE - 423, // LASERSCOPE - 400, // ROCKETLAUNCHER - 0, // FLAMETHROWER - 0, // M60 - 0, // MINIGUN - 0, // DETONATOR - 0, // HELICANNON - 0 // CAMERA -}; +float fReloadAnimSampleFraction[5] = { 0.5f, 0.7f, 0.75f, 0.75f, 0.7f }; +float fSeaSparrowAimingAngle = 10.0f; +float fHunterAimingAngle = 30.0f; +float fPlayerAimScaleDist = 5.0f; +float fPlayerAimScale = 2.5f; + +bool CWeapon::bPhotographHasBeenTaken; CWeaponInfo * CWeapon::GetInfo() @@ -86,6 +55,17 @@ CWeapon::GetInfo() return info; } +CWeapon::CWeapon(eWeaponType type, int32 ammo) +{ + m_eWeaponType = type; + m_eWeaponState = WEAPONSTATE_READY; + m_nAmmoTotal = Min(ammo, 99999); + m_nAmmoInClip = 0; + Reload(); + m_nTimer = 0; + m_bAddRotOffset = false; +} + void CWeapon::InitialiseWeapons(void) { @@ -94,6 +74,7 @@ CWeapon::InitialiseWeapons(void) CExplosion::Initialise(); CProjectileInfo::Initialise(); CBulletInfo::Initialise(); + bPhotographHasBeenTaken = false; } void @@ -115,19 +96,7 @@ CWeapon::UpdateWeapons(void) CBulletInfo::Update(); } -//--MIAMI: done -CWeapon::CWeapon(eWeaponType type, int32 ammo) -{ - m_eWeaponType = type; - m_eWeaponState = WEAPONSTATE_READY; - m_nAmmoTotal = Min(ammo, 99999); - m_nAmmoInClip = 0; - Reload(); - m_nTimer = 0; - m_bAddRotOffset = false; -} -// --MIAMI: Done void CWeapon::Initialise(eWeaponType type, int32 ammo) { @@ -137,24 +106,23 @@ CWeapon::Initialise(eWeaponType type, int32 ammo) m_nAmmoInClip = 0; Reload(); m_nTimer = 0; - int modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId; - if (modelId != -1) + int32 modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId; + int32 model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id; + + if ( modelId != -1 ) CModelInfo::GetModelInfo(modelId)->AddRef(); - - int model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id; - if (model2Id != -1) + if ( model2Id != -1 ) CModelInfo::GetModelInfo(model2Id)->AddRef(); } -// --MIAMI: Done void CWeapon::Shutdown() { - int modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId; + int32 modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId; if (modelId != -1) CModelInfo::GetModelInfo(modelId)->RemoveRef(); - int model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id; + int32 model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id; if (model2Id != -1) CModelInfo::GetModelInfo(model2Id)->RemoveRef(); @@ -172,12 +140,18 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) CVector fireOffset(0.0f, 0.0f, 0.6f); CVector *source = fireSource; +#ifdef FIX_BUGS + static CVector shooterSource; +#else + CVector shooterSource; +#endif - if (!fireSource) { - static CVector tmp; - tmp = shooter->GetMatrix() * fireOffset; - source = &tmp; + if ( !fireSource ) + { + shooterSource = shooter->GetMatrix() * fireOffset; + source = &shooterSource; } + if ( m_bAddRotOffset ) { float heading = RADTODEG(shooter->GetForward().Heading()); @@ -213,6 +187,17 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) break; } + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + { + if (shooter == FindPlayerPed()) + fired = FireSniper(shooter); + else + fired = FireInstantHit(shooter, source); + + break; + } + case WEAPONTYPE_COLT45: case WEAPONTYPE_PYTHON: case WEAPONTYPE_UZI: @@ -236,17 +221,6 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) break; } - case WEAPONTYPE_SNIPERRIFLE: - case WEAPONTYPE_LASERSCOPE: - { - if (shooter == FindPlayerPed()) { - fired = FireSniper(shooter); - } else { - fired = FireInstantHit(shooter, source); - } - break; - } - case WEAPONTYPE_ROCKETLAUNCHER: { if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) @@ -272,8 +246,6 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if ( shooter == FindPlayerPed() ) { fired = FireProjectile(shooter, source, ((CPlayerPed*)shooter)->m_fAttackButtonCounter*0.0375f); - if ( m_eWeaponType == WEAPONTYPE_GRENADE ) - CStats::KgsOfExplosivesUsed++; } else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) { @@ -309,6 +281,13 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) break; } + + case WEAPONTYPE_CAMERA: + { + fired = TakePhotograph(shooter); + + break; + } default: { @@ -324,14 +303,59 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if (shooter->IsPed()) { CPed* shooterPed = (CPed*)shooter; - - shooterPed->bIsShooting = true; - - if (shooterPed->IsPlayer()) - isPlayer = true; - + + if ( m_eWeaponType != WEAPONTYPE_CAMERA ) + { + shooterPed->bIsShooting = true; + + if (shooterPed->IsPlayer()) + isPlayer = true; + } + DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + + if ( isPlayer ) + { + CPed *aimPed = (CPed *)shooterPed->m_pSeekTarget; + if ( aimPed ) + { + if ( aimPed->IsPed() ) + shooterPed->Say(SOUND_PED_ON_FIRE); + } + } } + + switch ( m_eWeaponType ) + { + case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + CStats::RoundsFiredByPlayer++; + break; + + case WEAPONTYPE_GRENADE: + case WEAPONTYPE_DETONATOR_GRENADE: + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_ROCKET: + case WEAPONTYPE_ROCKETLAUNCHER: + case WEAPONTYPE_DETONATOR: + case WEAPONTYPE_HELICANNON: + CStats::KgsOfExplosivesUsed++; + break; + } + if (m_nAmmoInClip > 0) m_nAmmoInClip--; @@ -365,13 +389,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) return true; } - if (addFireRateAsDelay) + if ( addFireRateAsDelay ) m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nFiringRate; else m_nTimer = CTimer::GetTimeInMilliseconds(); - - if (shooter == FindPlayerPed()) - CStats::RoundsFiredByPlayer++; } } else @@ -380,12 +401,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) { m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; m_eWeaponState = WEAPONSTATE_FIRING; -#ifndef AUDIO_NOT_READY + if (shooter->IsPed() && m_eWeaponType != WEAPONTYPE_CHAINSAW) { - DMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, 188, m_eWeaponType << 8); + DMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, SOUND_MELEE_ATTACK_START, m_eWeaponType << 8); } -#endif } fired = FireMelee(shooter, *source); @@ -397,7 +417,6 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) return fired; } -// --MIAMI: Done bool CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right) { @@ -438,7 +457,6 @@ CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right) return true; } -// --MIAMI: Done, except commented things bool CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { @@ -446,20 +464,27 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) CWeaponInfo *info = GetInfo(); - bool anim2Playing = RpAnimBlendClumpGetAssociation(shooter->GetClump(), CPed::GetFireAnimGround(info, false)); - + bool anim2Playing = false; + + if ( CPed::GetFireAnimGround(info, false) != (AnimationId)0 ) + { + if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), CPed::GetFireAnimGround(info, false)) ) + anim2Playing = true; + } + ASSERT(shooter->IsPed()); CPed *shooterPed = (CPed*)shooter; - if (shooterPed == FindPlayerPed()) { + if (shooterPed == FindPlayerPed()) + { if (m_eWeaponType == WEAPONTYPE_GOLFCLUB || m_eWeaponType == WEAPONTYPE_NIGHTSTICK || - (m_eWeaponType >= WEAPONTYPE_BASEBALLBAT && m_eWeaponType <= WEAPONTYPE_CHAINSAW)) { + (m_eWeaponType >= WEAPONTYPE_BASEBALLBAT && m_eWeaponType <= WEAPONTYPE_CHAINSAW)) + { + CGlass::BreakGlassPhysically(fireSource, info->m_fRadius); - // TODO(Miami): BreakGlassPhysically - if (m_eWeaponType == WEAPONTYPE_CHAINSAW) { + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); - } } } @@ -505,11 +530,10 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { CColSphere *sphere = &victimPedCol->spheres[s]; - if (useLocalPos) { + if (useLocalPos) collisionDist = sphere->center - (*fireSource); - } else { + else collisionDist = victimPedPos + sphere->center - (*fireSource); - } if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) { @@ -532,21 +556,26 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) bool isHeavy = m_eWeaponType >= WEAPONTYPE_GOLFCLUB && m_eWeaponType <= WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_HAMMER; - if (shooterPed->m_fDamageImpulse == 0.0f) { + if (shooterPed->m_fDamageImpulse == 0.0f) + { shooterPed->m_pDamageEntity = victimPed; victimPed->RegisterReference(&shooterPed->m_pDamageEntity); } damageEntityRegistered = 3; - if (victimPed->bInVehicle) { + if (victimPed->bInVehicle) + { CVehicle *victimVeh = victimPed->m_pMyVehicle; - if (victimVeh) { - if (victimVeh->IsBike()) { + if (victimVeh) + { + if (victimVeh->IsBike()) + { CBike *victimBike = (CBike*)victimVeh; victimBike->KnockOffRider(m_eWeaponType, localDir, victimPed, false); - if (victimBike->pDriver) { + if (victimBike->pDriver) victimBike->pDriver->ReactToAttack(shooterPed); - } else { + else + { if (victimVeh->pPassengers[0]) victimVeh->pPassengers[0]->ReactToAttack(shooterPed); } @@ -625,9 +654,7 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) } if (info->m_AnimToPlay == ASSOCGRP_KNIFE) { - dir.x += 0.1f * shooterPed->GetUp().x + 0.05f * shooterPed->GetRight().x; - dir.y += 0.1f * shooterPed->GetUp().y + 0.05f * shooterPed->GetRight().y; - dir.z += 0.1f * shooterPed->GetUp().z + 0.05f * shooterPed->GetRight().z; + dir += 0.1f * shooterPed->GetUp() + 0.05f * shooterPed->GetRight(); CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); @@ -637,7 +664,7 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) if ( !victimPed->OnGround() ) { if ( victimPed->m_fHealth > 0.0f - && (victimPed->m_fHealth < 30.0f && victimPedHealth > 20.0f || + && (victimPed->m_fHealth < 30.0f && victimPedHealth > 30.0f || (isHeavy || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) && !victimPed->IsPlayer()) ) { posOffset.Normalise(); @@ -703,7 +730,8 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) float oldHealth = nearCar->m_fHealth; if (m_eWeaponType == WEAPONTYPE_CHAINSAW) { - for(int i=0; i<4; i++) { + for( int32 i=0; i<4; i++ ) + { CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f)); CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, gaTempSphereColPoints[0].normal * 0.1f); } @@ -716,7 +744,7 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) } else { - nearCar->VehicleDamage(info->m_nDamage* (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB); + nearCar->VehicleDamage(info->m_nDamage* (0.01f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB); } if (nearCar->m_fHealth < oldHealth) { @@ -808,7 +836,6 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) return true; } -// --MIAMI: Done except comments bool CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { @@ -856,13 +883,13 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) target = threatAttack->GetPosition(); target -= *fireSource; - float distToTarget = target.Magnitude(); + float distToTarget = Max(target.Magnitude(), 0.01f); target *= info->m_fRange / distToTarget; target += *fireSource; if (shooter == FindPlayerPed() && inaccuracy != 0.f) { - float newInaccuracy = 2.5f * FindPlayerPed()->m_fAttackButtonCounter * (inaccuracy * Min(1.f, 5.f / distToTarget)); + float newInaccuracy = fPlayerAimScale * FindPlayerPed()->m_fAttackButtonCounter * (inaccuracy * Min(1.f, fPlayerAimScaleDist / distToTarget)); if (FindPlayerPed()->bIsDucking) newInaccuracy *= 0.4f; @@ -886,10 +913,10 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) if (shooter == FindPlayerPed()) CWorld::bIncludeDeadPeds = true; - // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami) + CWorld::bIncludeBikers = true; CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true); CWorld::bIncludeDeadPeds = false; - // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami) + CWorld::bIncludeBikers = false; } else { @@ -899,9 +926,9 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) shooterPed->TransformToNode(target, PED_HANDR); - // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami) + CWorld::bIncludeBikers = true; CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true); - // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami) + CWorld::bIncludeBikers = false; } } else if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) @@ -909,11 +936,11 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) CVector src, trgt; TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); - // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami) + CWorld::bIncludeBikers = true; CWorld::bIncludeDeadPeds = true; CWorld::bIncludeCarTyres = true; CWorld::ProcessLineOfSight(src, trgt, point, victim, true, true, true, true, true, false, false, true); - // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami) + CWorld::bIncludeBikers = false; CWorld::bIncludeDeadPeds = false; CWorld::bIncludeCarTyres = false; @@ -990,9 +1017,9 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) CWeapon::DoDoomAiming(shooter, fireSource, &target); } - // CWorld::bProcessPedsOnBoatsAndBikes = 1; // TODO(Miami) + CWorld::bIncludeBikers = true; CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true); - // CWorld::bProcessPedsOnBoatsAndBikes = 0; // TODO(Miami) + CWorld::bIncludeBikers = false; int32 rotSpeed = 1; if (m_eWeaponType == WEAPONTYPE_M4) @@ -1007,7 +1034,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } } - if (victim && shooter->IsPed()) + if ( shooter->IsPed() && victim) { if (victim == ((CPed*)shooter)->m_leader) return false; @@ -1133,6 +1160,71 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) return true; } +void +CWeapon::AddGunFlashBigGuns(CVector start, CVector end) +{ + CPointLights::AddLight(CPointLights::LIGHT_POINT, + start, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + CVector gunflashPos = start; + + CVector shootVec = end - start; + + // Wtf did you do there R*? + shootVec.Normalise(); + CVector2D ahead = shootVec; + ahead.Normalise(); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); + gunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); + gunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos.z += 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos.z -= 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + offset.Normalise2D(); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos += CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos += CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); + gunflashPos += CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos -= CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos -= CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); + gunflashPos -= CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + CVector gunsmokePos = start; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x * rnd, ahead.y * rnd, 0.0f)); +} + void CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size) { @@ -1162,7 +1254,7 @@ CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &d } } -// --MIAMI: Done? + void CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead) @@ -1227,7 +1319,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CGlass::WasGlassHitByBullet(victim, point->point); CVector traceTarget = point->point; - CBulletTraces::AddTrace(source, &traceTarget); + CBulletTraces::AddTrace(source, &traceTarget, m_eWeaponType, shooter); if (victim->IsPed() && shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver) shooter = ((CVehicle*)shooter)->pDriver; @@ -1492,7 +1584,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } } else - CBulletTraces::AddTrace(source, target); + CBulletTraces::AddTrace(source, target, m_eWeaponType, shooter); if ( shooter == FindPlayerPed() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); @@ -1500,7 +1592,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, BlowUpExplosiveThings(victim); } -// --MIAMI: Done except comments, and didn't check particle coords precisely + bool CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { @@ -1576,6 +1668,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { float shootAngle = DEGTORAD(RADTODEG(halfAngleRange - angleBetweenTwoShot * i) + shooterAngle); CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); + shootRot.Normalise(); CVector source, target; CColPoint point; @@ -1590,10 +1683,9 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target = f * Left + target - source; target *= info->m_fRange; target += source; - CWorld::bIncludeDeadPeds = true; CWorld::bIncludeCarTyres = true; - //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes - + CWorld::bIncludeBikers = true; + CWorld::bIncludeDeadPeds = true; CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true); CWorld::bIncludeDeadPeds = false; CWorld::bIncludeCarTyres = false; @@ -1626,11 +1718,11 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if (shooter == FindPlayerPed()) CWorld::bIncludeDeadPeds = true; - //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes + CWorld::bIncludeBikers = true; CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true); CWorld::bIncludeDeadPeds = false; } - //bProcessPedsOnBoatsAndBikes = false; // TODO(Miami): bProcessPedsOnBoatsAndBikes + CWorld::bIncludeBikers = false; if ( victim ) { @@ -1684,7 +1776,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } } } - CBulletTraces::AddTrace(fireSource, &point.point); + CBulletTraces::AddTrace(fireSource, &point.point, m_eWeaponType, shooter); if ( victim->IsPed() ) { @@ -1899,7 +1991,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { CVector traceTarget = *fireSource; traceTarget += (target - (*fireSource)) * Min(info->m_fRange, 30.0f) / info->m_fRange; - CBulletTraces::AddTrace(fireSource, &traceTarget); + CBulletTraces::AddTrace(fireSource, &traceTarget, m_eWeaponType, shooter); } } @@ -1980,6 +2072,14 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) } else CProjectileInfo::AddProjectile(shooter, projectileType, *fireSource, power); + + + CWorld::pIgnoreEntity = nil; + + if ( shooter->IsPed() ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); + else if ( shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000); return true; } @@ -2032,24 +2132,76 @@ CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) CShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target); CWeapon::GenerateFlameThrowerParticles(*fireSource, dir); + + if ( shooter == (CEntity *)FindPlayerPed() ) + { + for ( int32 i = 0; i < FindPlayerPed()->m_numNearPeds; i++ ) + { + if ( FindPlayerPed()->m_nearPeds[i]->CharCreatedBy == RANDOM_CHAR ) + { + if ( FindPlayerPed()->m_nearPeds[i]->IsPedInControl() && FindPlayerPed()->m_nearPeds[i]->m_nPedState != PED_FLEE_ENTITY ) + FindPlayerPed()->m_nearPeds[i]->SetFlee(shooter, 10000); + } + } + } return true; } +bool +CWeapon::LaserScopeDot(CVector *pOutPos, float *pOutSize) +{ + CWeaponInfo *info = GetInfo(); + + float range = info->m_fRange; + + CVector source, target; + CEntity *foundEnt = nil; + CColPoint foundCol; + + source = 0.5f * TheCamera.Cams[TheCamera.ActiveCam].Front + TheCamera.Cams[TheCamera.ActiveCam].Source; + target = TheCamera.Cams[TheCamera.ActiveCam].Front; + target.Normalise(); + target *= range; + target += source; + + if ( CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, true, true, true, false, false, false) ) + { + CVector pos = foundCol.point; + float w, h; + + if ( CSprite::CalcScreenCoors(foundCol.point, pos, &w, &h, true) ) + { + *pOutPos = pos; + *pOutSize = w * 0.05f; + + CCoronas::RegisterCorona((uintptr)this + 7, 128, 0, 0, 255, pos, 1.2f, 50.0f, CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f); + + return true; + } + } + + return false; +} + bool CWeapon::FireSniper(CEntity *shooter) { ASSERT(shooter!=nil); - - int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - if (!( mode == CCam::MODE_M16_1STPERSON - || mode == CCam::MODE_SNIPER - || mode == CCam::MODE_ROCKETLAUNCHER - || mode == CCam::MODE_M16_1STPERSON_RUNABOUT - || mode == CCam::MODE_SNIPER_RUNABOUT - || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + + if ( (CEntity *)FindPlayerPed() == shooter ) { - return false; + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_CAMERA + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + { + return false; + } } #ifndef FIX_BUGS @@ -2076,14 +2228,74 @@ CWeapon::FireSniper(CEntity *shooter) FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + CParticle::HandleShootableBirdsStuff(shooter, source); CamShakeNoPos(&TheCamera, 0.2f); } + if ( shooter->IsPed() ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); + else if ( shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000); + return true; } -// --MIAMI: Done +bool +CWeapon::TakePhotograph(CEntity *shooter) +{ + if ( TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAMERA ) + { + CSpecialFX::bSnapShotActive = true; + CSpecialFX::SnapShotFrames = 0; + CStats::PhotosTaken++; + bPhotographHasBeenTaken = true; + + for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) + { + CPed *ped = CPools::GetPedPool()->GetSlot(i); + if ( ped ) + { + if ( (ped->GetPosition() - TheCamera.GetPosition()).Magnitude() < 125.0f ) + { + CVector pedPos = ped->GetPosition(); + pedPos.z += 0.8f; + + CVector pos; + float w, h; + + if ( CSprite::CalcScreenCoors(pedPos, pos, &w, &h, false) ) + { + if ( SCREEN_WIDTH * 0.1f < pos.x && SCREEN_WIDTH * 0.9f > pos.x + && SCREEN_HEIGHT * 0.1f < pos.y && SCREEN_HEIGHT * 0.9f > pos.y ) + { + CVector source, target; + CEntity *foundEnt = nil; + CColPoint foundCol; + + target = pedPos; + source = TheCamera.GetForward() * 2.0f + TheCamera.GetPosition(); + + if ( CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, true, true, true, true, true, false) ) + { + if ( foundEnt != (CEntity*)ped ) + continue; + } + + ped->bHasBeenPhotographed = true; + } + } + } + } + } + + return true; + } + + return false; +} + bool CWeapon::FireM16_1stPerson(CEntity *shooter) { @@ -2106,7 +2318,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) CWeaponInfo *info = GetInfo(); CWorld::bIncludeCarTyres = true; - // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami) + CWorld::bIncludeBikers = true; CColPoint point; CEntity *victim; @@ -2125,7 +2337,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) } CWorld::pIgnoreEntity = nil; CWorld::bIncludeDeadPeds = false; - // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami) + CWorld::bIncludeBikers = false; CWorld::bIncludeCarTyres = false; CVector2D front(cam->Front.x, cam->Front.y); @@ -2180,41 +2392,81 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) bool CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) { -// TODO(MIAMI): bikes CWeaponInfo *info = GetInfo(); CVehicleModelInfo *modelInfo = shooter->GetModelInfo(); - + CVector source, target; - if ( left ) + + if ( shooter->IsBike() ) { - source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, - float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y, - modelInfo->GetFrontSeatPosn().z + 0.5f); - source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - - - target = shooter->GetMatrix() * CVector(-info->m_fRange, - modelInfo->GetFrontSeatPosn().y, + if ( shooter->pDriver ) + { + source = info->m_vecFireOffset; + + shooter->pDriver->TransformToNode(source, PED_HANDR); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + if ( left ) + target = source - info->m_fRange * shooter->GetRight(); + else if ( right ) + target = source + info->m_fRange * shooter->GetRight(); + else + target = source + info->m_fRange * shooter->GetForward(); + + } + else if ( left ) + { + source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.25f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y - 0.05f, + modelInfo->GetFrontSeatPosn().z + 0.63f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + + target = shooter->GetMatrix() * CVector(-info->m_fRange, + modelInfo->GetFrontSeatPosn().y, + modelInfo->GetFrontSeatPosn().z + 0.6f); + } + else if ( right ) + { + source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.25f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y - 0.18f, + modelInfo->GetFrontSeatPosn().z + 0.52f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + target = shooter->GetMatrix() * CVector(info->m_fRange, + modelInfo->GetFrontSeatPosn().y, + modelInfo->GetFrontSeatPosn().z + 0.5f); + } + else + { + source = shooter->GetMatrix() * CVector(float(CGeneral::GetRandomNumber() & 255) * 0.001f + -0.4f, + modelInfo->GetFrontSeatPosn().y + shooter->GetColModel()->boundingBox.max.y + 0.2f, + modelInfo->GetFrontSeatPosn().z + 0.55f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + target = shooter->GetMatrix() * CVector(0.0f, + info->m_fRange, modelInfo->GetFrontSeatPosn().z + 0.5f); + } } else { - source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, - float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y, - modelInfo->GetFrontSeatPosn().z + 0.5f); + if ( left ) + source = info->m_vecFireOffset; + else + { + source = 1.8f * info->m_vecFireOffset; + source.z -= 0.1f; + } + + shooter->pDriver->TransformToNode(source, PED_HANDR); source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - - target = shooter->GetMatrix() * CVector(info->m_fRange, - modelInfo->GetFrontSeatPosn().y, - modelInfo->GetFrontSeatPosn().z + 0.5f); - } - #undef FRONTSEATPOS - - if ( TheCamera.GetLookingLRBFirstPerson() && !left ) - { - source -= 0.3f * shooter->GetForward(); - target -= 0.3f * shooter->GetForward(); + + if ( left ) + target = source - info->m_fRange * shooter->GetRight(); + else + target = source + info->m_fRange * shooter->GetRight(); } target += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, @@ -2226,9 +2478,14 @@ CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); if ( !TheCamera.GetLookingLRBFirstPerson() ) - CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); + { + if ( !shooter->IsBike() ) + CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); + else + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, source, 1.4f*shooter->m_vecMoveSpeed); + } else - CamShakeNoPos(&TheCamera, 0.01f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, source, 1.6f*shooter->m_vecMoveSpeed, nil, 0.18f); CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000); @@ -2237,7 +2494,12 @@ CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) CColPoint point; CEntity *victim; + + CWorld::bIncludeBikers = true; + CWorld::pIgnoreEntity = shooter; ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::pIgnoreEntity = NULL; + CWorld::bIncludeBikers = false; if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot(shooter, &source, &target); @@ -2245,7 +2507,7 @@ CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) if ( victim ) { CVector traceTarget = point.point; - CBulletTraces::AddTrace(&source, &traceTarget); + CBulletTraces::AddTrace(&source, &traceTarget, m_eWeaponType, shooter); if ( victim->IsPed() ) { @@ -2332,7 +2594,7 @@ CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) { float norm = 30.0f/info->m_fRange; CVector traceTarget = (target-source)*norm + source; - CBulletTraces::AddTrace(&source, &traceTarget); + CBulletTraces::AddTrace(&source, &traceTarget, m_eWeaponType, shooter); } if ( shooter == FindPlayerVehicle() ) @@ -2341,7 +2603,6 @@ CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) return true; } -// --MIAMI: Done void CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) { @@ -2484,7 +2745,7 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV } } -// --MIAMI: Done + void CWeapon::DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source, CVector *target) { @@ -2538,11 +2799,11 @@ CWeapon::DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source float maxAimDistance = CAR_DRIVEBYAUTOAIMING_MAXDIST; if (model == MI_HUNTER) { - maxAimDistance = Tan(DEGTORAD(30.f)); + maxAimDistance = Tan(DEGTORAD(fHunterAimingAngle)); } else if (model == MI_SEASPAR || model == MI_SPARROW) { - maxAimDistance = Tan(DEGTORAD(10.f)); + maxAimDistance = Tan(DEGTORAD(fSeaSparrowAimingAngle)); } if ( closestEntityDist < maxAimDistance ) @@ -2587,7 +2848,7 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) { if ( IsShotgun(m_eWeaponType) && AEHANDLE_IS_OK(audioEntity) ) { - uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; + uint32 timePassed = m_nTimer - CWeaponInfo::ms_aReloadSampleTime[m_eWeaponType]; if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } @@ -2596,7 +2857,7 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) { if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) { m_eWeaponState = WEAPONSTATE_OUT_OF_AMMO; - // TODO(Miami): CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo + CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(m_eWeaponType); } else m_eWeaponState = WEAPONSTATE_READY; } @@ -2621,20 +2882,20 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) float soundStart = 0.75f; switch (info->m_AnimToPlay) { case ASSOCGRP_PYTHON: - soundStart = 0.5f; + soundStart = fReloadAnimSampleFraction[0]; break; case ASSOCGRP_COLT: case ASSOCGRP_TEC: - soundStart = 0.7f; + soundStart = fReloadAnimSampleFraction[1]; break; case ASSOCGRP_UZI: - soundStart = 0.75f; + soundStart = fReloadAnimSampleFraction[2]; break; case ASSOCGRP_RIFLE: - soundStart = 0.75f; + soundStart = fReloadAnimSampleFraction[3]; break; case ASSOCGRP_M60: - soundStart = 0.7f; + soundStart = fReloadAnimSampleFraction[4]; break; default: break; @@ -2650,8 +2911,9 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) m_nTimer = CTimer::GetTimeInMilliseconds(); } } else { - uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; - if (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed) { + uint32 timePassed = m_nTimer - CWeaponInfo::ms_aReloadSampleTime[m_eWeaponType]; + if (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed) + { #ifdef AUDIO_NOT_READY DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); #else @@ -2745,17 +3007,20 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) } case ENTITY_TYPE_VEHICLE: { + CStats::BulletsThatHit++; DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); break; } case ENTITY_TYPE_PED: { + CStats::BulletsThatHit++; DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); break; } case ENTITY_TYPE_OBJECT: { + CStats::BulletsThatHit++; PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); break; } @@ -2863,7 +3128,6 @@ CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) return false; } -// --MIAMI: Done void CWeapon::BlowUpExplosiveThings(CEntity *thing) { @@ -2898,11 +3162,11 @@ bool CWeapon::HasWeaponAmmoToBeUsed(void) { // FIX: This is better (not bug tho) -#if 0 +//#if 0 if (m_eWeaponType <= WEAPONTYPE_CHAINSAW) -#else - if (CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE) -#endif +//#else +// if (CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE) +//#endif return true; else return m_nAmmoTotal != 0; @@ -2914,72 +3178,7 @@ CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPo return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects); } -void -CWeapon::AddGunFlashBigGuns(CVector start, CVector end) -{ - CPointLights::AddLight(CPointLights::LIGHT_POINT, - start, CVector(0.0f, 0.0f, 0.0f), 5.0f, - 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - CVector gunflashPos = start; - CVector shootVec = end - start; - - // Wtf did you do there R*? - shootVec.Normalise(); - CVector2D ahead = shootVec; - ahead.Normalise(); - - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); - gunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); - gunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); - - gunflashPos = start; - gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); - gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - gunflashPos.z += 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - gunflashPos = start; - gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); - gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - gunflashPos.z -= 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); - offset.Normalise2D(); - - gunflashPos = start; - gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); - gunflashPos += CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos += CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); - gunflashPos += CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - gunflashPos = start; - gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); - gunflashPos -= CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos -= CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); - gunflashPos -= CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - CVector gunsmokePos = start; - float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x * rnd, ahead.y * rnd, 0.0f)); -} - -// --MIAMI: Done void CWeapon::CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target) { diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index cb59582f..f720b312 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -21,7 +21,9 @@ public: int32 m_nAmmoTotal; uint32 m_nTimer; bool m_bAddRotOffset; - + + static bool bPhotographHasBeenTaken; + CWeapon() { m_bAddRotOffset = false; } @@ -41,6 +43,7 @@ public: bool FireMelee (CEntity *shooter, CVector &fireSource); bool FireInstantHit(CEntity *shooter, CVector *fireSource); + static void AddGunFlashBigGuns(CVector start, CVector end); void AddGunshell (CEntity *shooter, CVector const &source, CVector2D const &direction, float size); void DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead); @@ -50,13 +53,15 @@ public: static void GenerateFlameThrowerParticles(CVector pos, CVector dir); bool FireAreaEffect (CEntity *shooter, CVector *fireSource); + bool LaserScopeDot (CVector *pOutPos, float *pOutSize); bool FireSniper (CEntity *shooter); + bool TakePhotograph (CEntity *shooter); bool FireM16_1stPerson (CEntity *shooter); bool FireInstantHitFromCar(CVehicle *shooter, bool left, bool right); - static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target); - static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target); - static void DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source, CVector *target); + static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target); + static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target); + static void DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source, CVector *target); void Reload(void); void Update(int32 audioEntity, CPed *pedToAdjustSound); @@ -68,14 +73,12 @@ public: bool HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo); static void BlowUpExplosiveThings(CEntity *thing); bool HasWeaponAmmoToBeUsed(void); - static void AddGunFlashBigGuns(CVector, CVector); static bool IsShotgun(int weapon) { return weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_SPAS12_SHOTGUN || weapon == WEAPONTYPE_STUBBY_SHOTGUN; } - // TODO(Miami): Is that still used? static bool ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects); - static void CheckForShootingVehicleOccupant(CEntity**, CColPoint*, eWeaponType, CVector const&, CVector const&); + static void CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target); #ifdef COMPATIBLE_SAVES void Save(uint8*& buf); diff --git a/src/weapons/WeaponEffects.cpp b/src/weapons/WeaponEffects.cpp index fb50bbe0..7a5be722 100644 --- a/src/weapons/WeaponEffects.cpp +++ b/src/weapons/WeaponEffects.cpp @@ -3,6 +3,9 @@ #include "WeaponEffects.h" #include "TxdStore.h" #include "Sprite.h" +#include "PlayerPed.h" +#include "World.h" +#include "WeaponType.h" RwTexture *gpCrossHairTex; RwRaster *gpCrossHairRaster; @@ -24,10 +27,10 @@ CWeaponEffects::Init(void) { gCrossHair.m_bActive = false; gCrossHair.m_vecPos = CVector(0.0f, 0.0f, 0.0f); - gCrossHair.m_nRed = 0; + gCrossHair.m_nRed = 255; gCrossHair.m_nGreen = 0; gCrossHair.m_nBlue = 0; - gCrossHair.m_nAlpha = 255; + gCrossHair.m_nAlpha = 127; gCrossHair.m_fSize = 1.0f; gCrossHair.m_fRotation = 0.0f; @@ -46,9 +49,7 @@ void CWeaponEffects::Shutdown(void) { RwTextureDestroy(gpCrossHairTex); -#ifdef GTA3_1_1_PATCH gpCrossHairTex = nil; -#endif } void @@ -56,10 +57,6 @@ CWeaponEffects::MarkTarget(CVector pos, uint8 red, uint8 green, uint8 blue, uint { gCrossHair.m_bActive = true; gCrossHair.m_vecPos = pos; - gCrossHair.m_nRed = red; - gCrossHair.m_nGreen = green; - gCrossHair.m_nBlue = blue; - gCrossHair.m_nAlpha = alpha; gCrossHair.m_fSize = size; } @@ -72,12 +69,32 @@ CWeaponEffects::ClearCrossHair(void) void CWeaponEffects::Render(void) { + static float aCrossHairSize[WEAPONTYPE_TOTALWEAPONS] = + { + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 0.4f, 0.4f, + 0.5f, + 0.3f, + 0.9f, 0.9f, 0.9f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.1f, 0.1f, + 1.0f, + 0.6f, + 0.7f, + 0.0f, 0.0f + }; + + + if ( gCrossHair.m_bActive ) { + float size = aCrossHairSize[FindPlayerPed()->GetWeapon()->m_eWeaponType]; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVDESTALPHA); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpCrossHairRaster); RwV3d pos; @@ -85,15 +102,25 @@ CWeaponEffects::Render(void) if ( CSprite::CalcScreenCoors(gCrossHair.m_vecPos, &pos, &w, &h, true) ) { float recipz = 1.0f / pos.z; - CSprite::RenderOneXLUSprite(pos.x, pos.y, pos.z, - gCrossHair.m_fSize * w, gCrossHair.m_fSize * h, - gCrossHair.m_nRed, gCrossHair.m_nGreen, gCrossHair.m_nBlue, 255, - recipz, 255); + CSprite::RenderOneXLUSprite_Rotate_Aspect(pos.x, pos.y, pos.z, + w, h, + 255, 88, 100, 158, + recipz, gCrossHair.m_fRotation, gCrossHair.m_nAlpha); + + float recipz2 = 1.0f / pos.z; + + CSprite::RenderOneXLUSprite_Rotate_Aspect(pos.x, pos.y, pos.z, + size*w, size*h, + 107, 134, 247, 158, + recipz2, TWOPI - gCrossHair.m_fRotation, gCrossHair.m_nAlpha); + + gCrossHair.m_fRotation += 0.02f; + if ( gCrossHair.m_fRotation > TWOPI ) + gCrossHair.m_fRotation = 0.0; } - + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); } } \ No newline at end of file diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index 0f71aeda..6debf725 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -9,16 +9,57 @@ #include "ModelInfo.h" #include "ModelIndices.h" +uint16 CWeaponInfo::ms_aReloadSampleTime[WEAPONTYPE_TOTALWEAPONS] = +{ + 0, // UNARMED + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, // GRENADE + 0, // DETONATEGRENADE + 0, // TEARGAS + 0, // MOLOTOV + 0, // ROCKET + 250, // COLT45 + 250, // PYTHON + 650, // SHOTGUN + 650, // SPAS12 SHOTGUN + 650, // STUBBY SHOTGUN + 400, // TEC9 + 400, // UZIhec + 400, // SILENCED_INGRAM + 400, // MP5 + 300, // M16 + 300, // AK47 + 423, // SNIPERRIFLE + 423, // LASERSCOPE + 400, // ROCKETLAUNCHER + 0, // FLAMETHROWER + 0, // M60 + 0, // MINIGUN + 0, // DETONATOR + 0, // HELICANNON + 0 // CAMERA +}; + // Yeah... -int32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] = { +int32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] = +{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; - -// --MIAMI: Todo -static char ms_aWeaponNames[][32] = { +char CWeaponInfo::ms_aWeaponNames[WEAPONTYPE_TOTALWEAPONS][32] = +{ "Unarmed", "BrassKnuckle", "ScrewDriver", @@ -61,7 +102,7 @@ static char ms_aWeaponNames[][32] = { CWeaponInfo* CWeaponInfo::GetWeaponInfo(eWeaponType weaponType) { - return &CWeaponInfo::ms_apWeaponInfos[weaponType]; + return &ms_apWeaponInfos[weaponType]; } // --MIAMI: done except WEAPONTYPE_TOTALWEAPONS value diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index e7013004..7ce3d861 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -8,7 +8,9 @@ enum AssocGroupId; class CWeaponInfo { static CWeaponInfo ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; + static char ms_aWeaponNames[WEAPONTYPE_TOTALWEAPONS][32]; public: + static uint16 ms_aReloadSampleTime[WEAPONTYPE_TOTALWEAPONS]; static int32 ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS]; eWeaponFire m_eWeaponFire;