summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md11
-rw-r--r--src/core/Camera.cpp2
-rw-r--r--src/core/CutsceneMgr.cpp6
-rw-r--r--src/core/FileLoader.cpp2
-rw-r--r--src/core/Pad.cpp266
-rw-r--r--src/core/Radar.cpp3001
-rw-r--r--src/core/Stats.cpp237
-rw-r--r--src/core/Stats.h27
-rw-r--r--src/core/World.cpp2
-rw-r--r--src/core/World.h2
-rw-r--r--src/core/config.h5
-rw-r--r--src/core/re3.cpp2
-rw-r--r--src/entities/Entity.cpp14
-rw-r--r--src/modelinfo/PedModelInfo.cpp2
-rw-r--r--src/modelinfo/VehicleModelInfo.cpp14
-rw-r--r--src/objects/CutsceneHead.cpp2
-rw-r--r--src/objects/ParticleObject.cpp2
-rw-r--r--src/peds/Ped.cpp4
-rw-r--r--src/peds/PedIK.cpp4
-rw-r--r--src/peds/PedIK.h4
-rw-r--r--src/peds/PedType.h1
-rw-r--r--src/render/Clouds.cpp14
-rw-r--r--src/render/Fluff.cpp4
-rw-r--r--src/render/MBlur.cpp3
-rw-r--r--src/render/Skidmarks.cpp247
-rw-r--r--src/render/Skidmarks.h26
-rw-r--r--src/render/SpecialFX.cpp465
-rw-r--r--src/render/Sprite.cpp2
-rw-r--r--src/render/Sprite2d.cpp30
-rw-r--r--src/render/Timecycle.h1
-rw-r--r--src/render/VisibilityPlugins.cpp2
-rw-r--r--src/render/Weather.cpp470
-rw-r--r--src/render/Weather.h22
-rw-r--r--src/vehicles/Automobile.cpp10
-rw-r--r--src/vehicles/Bike.h15
-rw-r--r--src/vehicles/Boat.cpp54
-rw-r--r--src/vehicles/Vehicle.h1
-rw-r--r--src/weapons/Explosion.cpp428
-rw-r--r--src/weapons/Explosion.h25
39 files changed, 3481 insertions, 1948 deletions
diff --git a/README.md b/README.md
index a0e93bae..9237e8e3 100644
--- a/README.md
+++ b/README.md
@@ -16,12 +16,6 @@ such that we have a working game at all times.
- Since re3 is a DLL that works with original GTA III for now, you need Simple DLL Loader. You can get it [here](https://github.com/aap/simpledllloader).
- Build re3 or download it from one of the above links (Debug or Release).
- Make sure you included the re3 in `plugins.cfg` or `dlls.cfg`.
-- re3 starts the script `main_freeroam.scm` that comes along with it by default, so you should copy it to from `gamefiles/` to your game's `data/` directory.
-
-![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice**
-
-If you want to load original script/story, press and hold G while game is loading.
-This includes both starting new game and loading save game.
![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice if you will build it**
@@ -41,21 +35,16 @@ to reverse at the time, calling the original functions is acceptable.
cAudioManager - WIP
CBoat
CBulletInfo
-CExplosion
CMenuManager - WIP
CObject
CPacManPickups
-CPad - only cheats
CPedPath
CPools - save/loading
CRecordDataForChase
CRecordDataForGame
CRoadBlocks
-CSkidmarks
-CStats
CTrafficLights
CWeapon
-CWeather
CWorld
GenericLoad
```
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 00c838cf..d79c9218 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -3269,7 +3269,7 @@ void
CCamera::SetRwCamera(RwCamera *cam)
{
m_pRwCamera = cam;
- m_viewMatrix.Attach(&m_pRwCamera->viewMatrix, false);
+ m_viewMatrix.Attach(RwCameraGetViewMatrix(m_pRwCamera), false);
CMBlur::MotionBlurOpen(m_pRwCamera);
}
diff --git a/src/core/CutsceneMgr.cpp b/src/core/CutsceneMgr.cpp
index 283f34b8..39066958 100644
--- a/src/core/CutsceneMgr.cpp
+++ b/src/core/CutsceneMgr.cpp
@@ -134,8 +134,8 @@ uint32 &CCutsceneMgr::ms_cutsceneLoadStatus = *(uint32*)0x95CB40;
RpAtomic *
CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data)
{
- float radius = RpAtomicGetBoundingSphereMacro(atomic)->radius;
- RwV3d center = RpAtomicGetBoundingSphereMacro(atomic)->center;
+ float radius = RpAtomicGetBoundingSphere(atomic)->radius;
+ RwV3d center = RpAtomicGetBoundingSphere(atomic)->center;
for (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))
RwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame));
@@ -326,7 +326,7 @@ CCutsceneMgr::CreateCutsceneObject(int modelId)
pModelInfo->SetColModel(pColModel);
clump = (RpClump*)pModelInfo->GetRwObject();
- assert(RwObjectGetType(clump) == rpCLUMP);
+ assert(RwObjectGetType((RwObject*)clump) == rpCLUMP);
RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);
pColModel->boundingSphere.radius = radius;
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index 6305bf33..e0c8b01e 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -311,7 +311,7 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
int n;
RpClump *clump = (RpClump*)data;
- nodename = GetFrameNodeName(RpClumpGetFrame(atomic));
+ nodename = GetFrameNodeName(RpAtomicGetFrame(atomic));
GetNameAndLOD(nodename, name, &n);
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil);
if(mi){
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index 6bbe00f2..079a3ea7 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -28,6 +28,10 @@
#include "Replay.h"
#include "Weather.h"
#include "win.h"
+#include "Streaming.h"
+#include "PathFind.h"
+#include "Wanted.h"
+#include "General.h"
CPad *Pads = (CPad*)0x6F0360; // [2]
CMousePointerStateHelper &MousePointerStateHelper = *(CMousePointerStateHelper*)0x95CC8C;
@@ -49,29 +53,217 @@ CMouseControllerState &CPad::PCTempMouseControllerState = *(CMouseControllerStat
_TODO("gbFastTime");
extern bool &gbFastTime;
-WRAPPER void WeaponCheat() { EAXJMP(0x490D90); }
-WRAPPER void HealthCheat() { EAXJMP(0x490E70); }
-WRAPPER void TankCheat() { EAXJMP(0x490EE0); }
-WRAPPER void BlowUpCarsCheat() { EAXJMP(0x491040); }
-WRAPPER void ChangePlayerCheat() { EAXJMP(0x4910B0); }
-WRAPPER void MayhemCheat() { EAXJMP(0x4911C0); }
-WRAPPER void EverybodyAttacksPlayerCheat() { EAXJMP(0x491270); }
-WRAPPER void WeaponsForAllCheat() { EAXJMP(0x491370); }
-WRAPPER void FastTimeCheat() { EAXJMP(0x4913A0); }
-WRAPPER void SlowTimeCheat() { EAXJMP(0x4913F0); }
-WRAPPER void MoneyCheat() { EAXJMP(0x491430); }
-WRAPPER void ArmourCheat() { EAXJMP(0x491460); }
-WRAPPER void WantedLevelUpCheat() { EAXJMP(0x491490); }
-WRAPPER void WantedLevelDownCheat() { EAXJMP(0x4914F0); }
-WRAPPER void SunnyWeatherCheat() { EAXJMP(0x491520); }
-WRAPPER void CloudyWeatherCheat() { EAXJMP(0x491550); }
-WRAPPER void RainyWeatherCheat() { EAXJMP(0x491580); }
-WRAPPER void FoggyWeatherCheat() { EAXJMP(0x4915B0); }
-WRAPPER void FastWeatherCheat() { EAXJMP(0x4915E0); }
-WRAPPER void OnlyRenderWheelsCheat() { EAXJMP(0x491610); }
-WRAPPER void ChittyChittyBangBangCheat() { EAXJMP(0x491640); }
-WRAPPER void StrongGripCheat() { EAXJMP(0x491670); }
-WRAPPER void NastyLimbsCheat() { EAXJMP(0x4916A0); }
+void WeaponCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT2"), true);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_UZI, 100);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_M16, 200);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 5);
+ FindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200);
+}
+
+void HealthCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT3"), true);
+ FindPlayerPed()->m_fHealth = 100.0f;
+ if (FindPlayerVehicle()) {
+ FindPlayerVehicle()->m_fHealth = 1000.0f;
+ if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR)
+ ((CAutomobile*)FindPlayerVehicle())->Damage.SetEngineStatus(0);
+ }
+}
+
+void TankCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ CStreaming::RequestModel(MI_RHINO, 0);
+ CStreaming::LoadAllRequestedModels(false);
+ if (CStreaming::ms_aInfoForModel[MI_RHINO].m_loadState == STREAMSTATE_LOADED) {
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f);
+
+ if (node < 0) return;
+
+#ifdef FIX_BUGS
+ CAutomobile* tank = new CAutomobile(MI_RHINO, RANDOM_VEHICLE);
+#else
+ CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE);
+#endif
+ if (tank != nil) {
+ CVector pos = ThePaths.m_pathNodes[node].pos;
+ pos.z += 4.0f;
+ tank->GetPosition() = pos;
+ tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f));
+
+ tank->m_status = STATUS_ABANDONED;
+ tank->m_nDoorLock = CARLOCK_UNLOCKED;
+ CWorld::Add(tank);
+ }
+ }
+}
+
+void BlowUpCarsCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+
+ int i = CPools::GetVehiclePool()->GetSize();
+ while (i-- > 0) {
+ if (CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i))
+ veh->BlowUpCar(nil);
+ }
+}
+
+void ChangePlayerCheat()
+{
+ int modelId;
+
+ if (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo("player", nil)) {
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ CPlayerPed *ped = FindPlayerPed();
+ AssocGroupId AnimGrp = ped->m_animGroup;
+ do
+ {
+ do
+ modelId = CGeneral::GetRandomNumberInRange(0, MI_CAS_WOM+1);
+ while (!CModelInfo::GetModelInfo(modelId));
+ } while (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL04 || modelId == MI_TAXI_D);
+
+ uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags;
+ ped->DeleteRwObject();
+ CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE);
+ CStreaming::LoadAllRequestedModels(false);
+ ped->m_modelIndex = -1;
+ ped->SetModelIndex(modelId);
+ ped->m_animGroup = AnimGrp;
+ if (modelId != MI_PLAYER) {
+ if (!(flags & STREAMFLAGS_DONT_REMOVE))
+ CStreaming::SetModelIsDeletable(modelId);
+ }
+ }
+}
+
+void MayhemCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)
+ CPedType::SetThreats(i, PED_FLAG_PLAYER1 | PED_FLAG_PLAYER2 | PED_FLAG_PLAYER3 | PED_FLAG_PLAYER4 |
+ PED_FLAG_CIVMALE | PED_FLAG_CIVFEMALE | PED_FLAG_COP | PED_FLAG_GANG1 |
+ PED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 |
+ PED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 |
+ PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL );
+}
+
+void EverybodyAttacksPlayerCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)
+ CPedType::AddThreat(i, PED_FLAG_PLAYER1);
+}
+
+void WeaponsForAllCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ CPopulation::ms_bGivePedsWeapons = !CPopulation::ms_bGivePedsWeapons;
+}
+
+void FastTimeCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ if (CTimer::GetTimeScale() < 4.0f)
+ CTimer::SetTimeScale(CTimer::GetTimeScale() * 2.0f);
+}
+
+void SlowTimeCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ if (CTimer::GetTimeScale() > 0.25f)
+ CTimer::SetTimeScale(CTimer::GetTimeScale() * 0.5f);
+}
+
+void MoneyCheat()
+{
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250000;
+ CHud::SetHelpMessage(TheText.Get("CHEAT6"), true);
+}
+
+void ArmourCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT4"), true);
+ FindPlayerPed()->m_fArmour = 100.0f;
+}
+
+void WantedLevelUpCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT5"), true);
+ FindPlayerPed()->SetWantedLevel(min(FindPlayerPed()->m_pWanted->m_nWantedLevel + 2, 6));
+}
+
+void WantedLevelDownCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT5"), true);
+ FindPlayerPed()->SetWantedLevel(0);
+}
+
+void SunnyWeatherCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
+ CWeather::ForceWeatherNow(WEATHER_SUNNY);
+}
+
+void CloudyWeatherCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
+ CWeather::ForceWeatherNow(WEATHER_CLOUDY);
+}
+
+void RainyWeatherCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
+ CWeather::ForceWeatherNow(WEATHER_RAINY);
+}
+
+void FoggyWeatherCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
+ CWeather::ForceWeatherNow(WEATHER_FOGGY);
+}
+
+void FastWeatherCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ gbFastTime = !gbFastTime;
+}
+
+void OnlyRenderWheelsCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ CVehicle::bWheelsOnlyCheat = !CVehicle::bWheelsOnlyCheat;
+}
+
+
+void ChittyChittyBangBangCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ CVehicle::bAllDodosCheat = !CVehicle::bAllDodosCheat;
+}
+
+void StrongGripCheat()
+{
+ CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
+ CVehicle::bCheat3 = !CVehicle::bCheat3;
+}
+
+void NastyLimbsCheat()
+{
+ CPed::bNastyLimbsCheat = !CPed::bNastyLimbsCheat;
+}
//////////////////////////////////////////////////////////////////////////
#ifdef KANGAROO_CHEAT
@@ -88,7 +280,7 @@ void KangarooCheat()
string = TheText.Get("CHEAT1");
m_fMass = 15.0f;
}
- CHud::SetHelpMessage(string, 1);
+ CHud::SetHelpMessage(string, true);
playerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80;
playerPed->m_fMass = m_fMass;
@@ -2086,7 +2278,31 @@ int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize)
return pRsKeys;
}
-STARTPATCHES
+STARTPATCHES
+ InjectHook(0x490D90, &WeaponCheat, PATCH_JUMP);
+ InjectHook(0x490E70, &HealthCheat, PATCH_JUMP);
+ InjectHook(0x490EE0, &TankCheat, PATCH_JUMP);
+ InjectHook(0x491040, &BlowUpCarsCheat, PATCH_JUMP);
+ InjectHook(0x4910B0, &ChangePlayerCheat, PATCH_JUMP);
+ InjectHook(0x4911C0, &MayhemCheat, PATCH_JUMP);
+ InjectHook(0x491270, &EverybodyAttacksPlayerCheat, PATCH_JUMP);
+ InjectHook(0x491370, &WeaponsForAllCheat, PATCH_JUMP);
+ InjectHook(0x4913A0, &FastTimeCheat, PATCH_JUMP);
+ InjectHook(0x4913F0, &SlowTimeCheat, PATCH_JUMP);
+ InjectHook(0x491430, &MoneyCheat, PATCH_JUMP);
+ InjectHook(0x491460, &ArmourCheat, PATCH_JUMP);
+ InjectHook(0x491490, &WantedLevelUpCheat, PATCH_JUMP);
+ InjectHook(0x4914F0, &WantedLevelDownCheat, PATCH_JUMP);
+ InjectHook(0x491520, &SunnyWeatherCheat, PATCH_JUMP);
+ InjectHook(0x491550, &CloudyWeatherCheat, PATCH_JUMP);
+ InjectHook(0x491580, &RainyWeatherCheat, PATCH_JUMP);
+ InjectHook(0x4915B0, &FoggyWeatherCheat, PATCH_JUMP);
+ InjectHook(0x4915E0, &FastWeatherCheat, PATCH_JUMP);
+ InjectHook(0x491610, &OnlyRenderWheelsCheat, PATCH_JUMP);
+ InjectHook(0x491640, &ChittyChittyBangBangCheat, PATCH_JUMP);
+ InjectHook(0x491670, &StrongGripCheat, PATCH_JUMP);
+ InjectHook(0x4916A0, &NastyLimbsCheat, PATCH_JUMP);
+
InjectHook(0x4916C0, &CControllerState::Clear, PATCH_JUMP);
InjectHook(0x491760, &CKeyboardState::Clear, PATCH_JUMP);
InjectHook(0x491A10, &CPad::Clear, PATCH_JUMP);
diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp
index 07ddb5d8..afaceb6d 100644
--- a/src/core/Radar.cpp
+++ b/src/core/Radar.cpp
@@ -1,1504 +1,1501 @@
-#include "config.h"
-#include "common.h"
-#include "patcher.h"
-#include "RwHelper.h"
-#include "Radar.h"
-#include "Camera.h"
-#include "Hud.h"
-#include "World.h"
-#include "Frontend.h"
-#include "General.h"
-#include "Vehicle.h"
-#include "Pools.h"
-#include "Script.h"
-#include "TxdStore.h"
-#include "World.h"
-#include "Streaming.h"
-#include "SpecialFX.h"
-
-float &CRadar::m_radarRange = *(float*)0x8E281C;
-CBlip (&CRadar::ms_RadarTrace)[NUMRADARBLIPS] = *(CBlip(*)[NUMRADARBLIPS]) * (uintptr*)0x6ED5E0;
-CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8;
-int32 gRadarTxdIds[64];// = (int*)0x6299C0;
-
-CSprite2d CRadar::AsukaSprite;// = *(CSprite2d*)0x8F1A40;
-CSprite2d CRadar::BombSprite;// = (CSprite2d*)0x8F5FB4;
-CSprite2d CRadar::CatSprite;// = (CSprite2d*)0x885B24;
-CSprite2d CRadar::CentreSprite;// = (CSprite2d*)0x8F6268;
-CSprite2d CRadar::CopcarSprite;// = (CSprite2d*)0x8F1A2C;
-CSprite2d CRadar::DonSprite;// = (CSprite2d*)0x8F2BE0;
-CSprite2d CRadar::EightSprite;// = (CSprite2d*)0x8F2BCC;
-CSprite2d CRadar::ElSprite;// = (CSprite2d*)0x8F1B80;
-CSprite2d CRadar::IceSprite;// = (CSprite2d*)0x9415FC;
-CSprite2d CRadar::JoeySprite;// = (CSprite2d*)0x8F2C00;
-CSprite2d CRadar::KenjiSprite;// = (CSprite2d*)0x8F2C68;
-CSprite2d CRadar::LizSprite;// = (CSprite2d*)0x8F5830;
-CSprite2d CRadar::LuigiSprite;// = (CSprite2d*)0x8F1A3C;
-CSprite2d CRadar::NorthSprite;// = (CSprite2d*)0x8F6274;
-CSprite2d CRadar::RaySprite;// = (CSprite2d*)0x8E2A7C;
-CSprite2d CRadar::SalSprite;// = (CSprite2d*)0x8F29EC;
-CSprite2d CRadar::SaveSprite;// = (CSprite2d*)0x8F5F74;
-CSprite2d CRadar::SpraySprite;// = (CSprite2d*)0x94307C;
-CSprite2d CRadar::TonySprite;// = (CSprite2d*)0x885B58;
-CSprite2d CRadar::WeaponSprite;// = (CSprite2d*)0x941534;
-
-CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = {
- nil,
- &AsukaSprite,
- &BombSprite,
- &CatSprite,
- &CentreSprite,
- &CopcarSprite,
- &DonSprite,
- &EightSprite,
- &ElSprite,
- &IceSprite,
- &JoeySprite,
- &KenjiSprite,
- &LizSprite,
- &LuigiSprite,
- &NorthSprite,
- &RaySprite,
- &SalSprite,
- &SaveSprite,
- &SpraySprite,
- &TonySprite,
- &WeaponSprite
-};
-
-#define RADAR_NUM_TILES (8)
-#define RADAR_TILE_SIZE (WORLD_SIZE_X / RADAR_NUM_TILES)
-static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not a square");
-
-#define RADAR_MIN_RANGE (120.0f)
-#define RADAR_MAX_RANGE (350.0f)
-#define RADAR_MIN_SPEED (0.3f)
-#define RADAR_MAX_SPEED (0.9f)
-
-#ifdef MENU_MAP
-CRGBA CRadar::ArrowBlipColour1;
-CRGBA CRadar::ArrowBlipColour2;
-uint16 CRadar::MapLegendCounter;
-uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS];
-int CRadar::TargetMarkerId = -1;
-#endif
-
-// taken from VC
-float CRadar::cachedCos;
-float CRadar::cachedSin;
-
-uint8 CRadar::CalculateBlipAlpha(float dist)
-{
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive)
- return 255;
-#endif
- if (dist <= 1.0f)
- return 255;
-
- if (dist <= 5.0f)
- return (128.0f * ((dist - 1.0f) / 4.0f)) + ((1.0f - (dist - 1.0f) / 4.0f) * 255.0f);
-
- return 128;
-}
-
-void CRadar::ChangeBlipBrightness(int32 i, int32 bright)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_bDim = bright != 1;
-}
-
-void CRadar::ChangeBlipColour(int32 i, int32 color)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_nColor = color;
-}
-
-void CRadar::ChangeBlipDisplay(int32 i, eBlipDisplay display)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_eBlipDisplay = display;
-}
-
-void CRadar::ChangeBlipScale(int32 i, int32 scale)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1)
- ms_RadarTrace[index].m_wScale = scale;
-}
-
-void CRadar::ClearBlip(int32 i)
-{
- int index = GetActualBlipArrayIndex(i);
- if (index != -1) {
- SetRadarMarkerState(index, false);
- ms_RadarTrace[index].m_bInUse = false;
-#ifndef MENU_MAP
- // Ssshhh
- ms_RadarTrace[index].m_eBlipType = BLIP_NONE;
- ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
- ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE;
-#endif
- }
-}
-
-void CRadar::ClearBlipForEntity(eBlipType type, int32 id)
-{
- for (int i = 0; i < NUMRADARBLIPS; i++) {
- if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) {
- SetRadarMarkerState(i, false);
- ms_RadarTrace[i].m_bInUse = false;
- ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
- ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
- ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
- }
- };
-}
-
-// Why not a proper clipping algorithm?
-int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect)
-{
- CVector2D corners[4] = {
- { 1.0f, -1.0f }, // top right
- { 1.0f, 1.0f }, // bottom right
- { -1.0f, 1.0f }, // bottom left
- { -1.0f, -1.0f }, // top left
- };
- CVector2D tmp;
- int i, j, n;
- int laste, e, e1, e2;;
- bool inside[4];
-
- for (i = 0; i < 4; i++)
- inside[i] = IsPointInsideRadar(rect[i]);
-
- laste = -1;
- n = 0;
- for (i = 0; i < 4; i++)
- if (inside[i]) {
- // point is inside, just add
- poly[n++] = rect[i];
- }
- else {
- // point is outside but line to this point might be clipped
- e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]);
- if (e1 != -1) {
- laste = e1;
- n++;
- }
- // and line from this point might be clipped as well
- e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]);
- if (e2 != -1) {
- if (e1 == -1) {
- // if other line wasn't clipped, i.e. it was complete outside,
- // we may have to insert another vertex if last clipped line
- // was on a different edge
-
- // find the last intersection if we haven't seen it yet
- if (laste == -1)
- for (j = 3; j >= i; j--) {
- // game uses an if here for j == 0
- e = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]);
- if (e != -1) {
- laste = e;
- break;
- }
- }
- assert(laste != -1);
-
- // insert corners that were skipped
- tmp = poly[n];
- for (e = laste; e != e2; e = (e + 1) % 4)
- poly[n++] = corners[e];
- poly[n] = tmp;
- }
- n++;
- }
- }
-
- if (n == 0) {
- // If no points, either the rectangle is completely outside or completely surrounds the radar
- // no idea what's going on here...
- float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x);
- if ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
- m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x);
- if ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
- poly[0] = corners[0];
- poly[1] = corners[1];
- poly[2] = corners[2];
- poly[3] = corners[3];
- n = 4;
- }
- }
- }
-
- return n;
-}
-
-bool CRadar::DisplayThisBlip(int32 counter)
-{
- switch (ms_RadarTrace[counter].m_eRadarSprite) {
- case RADAR_SPRITE_BOMB:
- case RADAR_SPRITE_SPRAY:
- case RADAR_SPRITE_WEAPON:
- return true;
- default:
- return false;
- }
-}
-
-void CRadar::Draw3dMarkers()
-{
- for (int i = 0; i < NUMRADARBLIPS; i++) {
- if (ms_RadarTrace[i].m_bInUse) {
- switch (ms_RadarTrace[i].m_eBlipType) {
- case BLIP_CAR:
- {
- CEntity *entity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- CVector pos = entity->GetPosition();
- pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f;
- C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
- }
- break;
- }
- case BLIP_CHAR:
- {
- CEntity *entity = CPools::GetPedPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
- if (entity != nil) {
- if (((CPed*)entity)->InVehicle())
- entity = ((CPed * )entity)->m_pMyVehicle;
- }
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- CVector pos = entity->GetPosition();
- pos.z += 3.0f;
- C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
- }
- break;
- }
- case BLIP_OBJECT:
- {
- CEntity *entity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- CVector pos = entity->GetPosition();
- pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f;
- C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5);
- }
- break;
- }
- case BLIP_COORD:
- break;
- case BLIP_CONTACT_POINT:
- if (!CTheScripts::IsPlayerOnAMission()) {
- if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY)
- C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0);
- }
- break;
- }
- }
- }
-}
-
-void CRadar::DrawBlips()
-{
- if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
-
- CVector2D out;
- CVector2D in = CVector2D(0.0f, 0.0f);
- TransformRadarPointToScreenSpace(out, in);
-
-#ifdef MENU_MAP
- if (!CMenuManager::bMenuMapActive) {
-#endif
- float angle;
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN)
- angle = PI + FindPlayerHeading();
-#ifdef FIX_BUGS
- else if (TheCamera.GetLookDirection() != LOOKING_FORWARD)
- angle = FindPlayerHeading() - (PI + (TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind).Heading());
-#endif
- else
- angle = FindPlayerHeading() - (PI + TheCamera.GetForward().Heading());
-
- DrawRotatingRadarSprite(&CentreSprite, out.x, out.y, angle, 255);
-
- CVector2D vec2d;
- vec2d.x = vec2DRadarOrigin.x;
- vec2d.y = M_SQRT2 * m_radarRange + vec2DRadarOrigin.y;
- TransformRealWorldPointToRadarSpace(in, vec2d);
- LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255);
-#ifdef MENU_MAP
- }
-#endif
-
- CEntity *blipEntity = nil;
- for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
-#ifdef MENU_MAP
- // A little hack to reuse cleared blips in menu map. hehe
- if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR ||
- ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT)
-#endif
- if (!ms_RadarTrace[blipId].m_bInUse)
- continue;
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- case BLIP_CHAR:
- case BLIP_OBJECT:
- if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
- || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) {
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- case BLIP_CHAR:
- blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- if (blipEntity != nil) {
- if (((CPed*)blipEntity)->InVehicle())
- blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
- }
- break;
- case BLIP_OBJECT:
- blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- default:
- break;
- }
- if (blipEntity) {
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- } else {
-#ifdef TRIANGULAR_BLIPS
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = blipEntity->GetPosition();
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- }
- }
- break;
- case BLIP_COORD:
- case BLIP_CONTACT_POINT:
- if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
- || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON)
- && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
-
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- } else {
-#ifdef TRIANGULAR_BLIPS
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- }
- break;
- default:
- break;
- }
- }
- for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
- if (!ms_RadarTrace[blipId].m_bInUse)
- continue;
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- case BLIP_CHAR:
- case BLIP_OBJECT:
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
- && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) {
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_CAR:
- blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- case BLIP_CHAR:
- blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- if (blipEntity != nil) {
- if (((CPed*)blipEntity)->InVehicle())
- blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
- }
- break;
- case BLIP_OBJECT:
- blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
- break;
- default:
- break;
- }
-
- if (blipEntity) {
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- else
-#ifdef TRIANGULAR_BLIPS
- {
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = blipEntity->GetPosition();
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
- }
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- }
- break;
- default:
- break;
- }
- }
- for (int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
- if (!ms_RadarTrace[blipId].m_bInUse)
- continue;
-
- switch (ms_RadarTrace[blipId].m_eBlipType) {
- case BLIP_COORD:
- case BLIP_CONTACT_POINT:
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
- && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON
- && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
-
- uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
- if (CTheScripts::IsDebugOn()) {
- ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
- ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
- if (ms_RadarTrace[blipId].m_Radius < 1.0f)
- ms_RadarTrace[blipId].m_Radius = 5.0f;
- }
- }
- if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
- TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
- float dist = LimitRadarPoint(in);
- TransformRadarPointToScreenSpace(out, in);
- if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
- DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
- else
-#ifdef TRIANGULAR_BLIPS
- {
- CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
- CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
- uint8 mode = BLIP_MODE_TRIANGULAR_UP;
- if (blipPos.z - pos.z <= 2.0f) {
- if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
- else mode = BLIP_MODE_SQUARE;
- }
- ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
- }
-#else
- ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
-#endif
- }
- }
- break;
- default:
- break;
- }
- }
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive) {
- CVector2D in, out;
- TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift());
- TransformRadarPointToScreenSpace(out, in);
- DrawYouAreHereSprite(out.x, out.y);
- }
-#endif
- }
-}
-
-void CRadar::DrawMap()
-{
- if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
-#if 1 // from VC
- CalculateCachedSinCos();
-#endif
- if (FindPlayerVehicle()) {
- float speed = FindPlayerSpeed().Magnitude();
- if (speed < RADAR_MIN_SPEED)
- m_radarRange = RADAR_MIN_RANGE;
- else if (speed < RADAR_MAX_SPEED)
- m_radarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;
- else
- m_radarRange = RADAR_MAX_RANGE;
- }
- else
- m_radarRange = RADAR_MIN_RANGE;
-
- vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift());
- DrawRadarMap();
- }
-}
-
-void CRadar::DrawRadarMap()
-{
- // Game calculates an unused CRect here
-
- DrawRadarMask();
-
- // top left ist (0, 0)
- int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE);
- int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE);
- StreamRadarSections(x, y);
-
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
- RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE);
-
- DrawRadarSection(x - 1, y - 1);
- DrawRadarSection(x, y - 1);
- DrawRadarSection(x + 1, y - 1);
- DrawRadarSection(x - 1, y);
- DrawRadarSection(x, y);
- DrawRadarSection(x + 1, y);
- DrawRadarSection(x - 1, y + 1);
- DrawRadarSection(x, y + 1);
- DrawRadarSection(x + 1, y + 1);
-}
-
-void CRadar::DrawRadarMask()
-{
- CVector2D corners[4] = {
- CVector2D(1.0f, -1.0f),
- CVector2D(1.0f, 1.0f),
- CVector2D(-1.0f, 1.0f),
- CVector2D(-1.0, -1.0f)
- };
-
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONALWAYS);
-
- CVector2D out[8];
- CVector2D in;
-
- // Draw the shape we want to mask out from the radar in four segments
- for (int i = 0; i < 4; i++) {
- // First point is always the corner itself
- in.x = corners[i].x;
- in.y = corners[i].y;
- TransformRadarPointToScreenSpace(out[0], in);
-
- // Then generate a quarter of the circle
- for (int j = 0; j < 7; j++) {
- in.x = corners[i].x * Cos(j * (PI / 2.0f / 6.0f));
- in.y = corners[i].y * Sin(j * (PI / 2.0f / 6.0f));
- TransformRadarPointToScreenSpace(out[j + 1], in);
- };
-
- CSprite2d::SetMaskVertices(8, (float *)out);
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8);
- };
-
- RwD3D8SetRenderState(rwRENDERSTATESTENCILFUNCTION, rwSTENCILFUNCTIONGREATER);
-}
-
-void CRadar::DrawRadarSection(int32 x, int32 y)
-{
- int i;
- RwTexDictionary *txd;
- CVector2D worldPoly[8];
- CVector2D radarCorners[4];
- CVector2D radarPoly[8];
- CVector2D texCoords[8];
- CVector2D screenPoly[8];
- int numVertices;
- RwTexture *texture = nil;
-
- GetTextureCorners(x, y, worldPoly);
- ClipRadarTileCoords(x, y);
-
- assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y]));
- txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict;
- if (txd)
- texture = GetFirstTexture(txd);
- if (texture == nil)
- return;
-
- for (i = 0; i < 4; i++)
- TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]);
-
- numVertices = ClipRadarPoly(radarPoly, radarCorners);
-
- // FIX: can return earlier here
-// if(numVertices == 0)
- if (numVertices < 3)
- return;
-
- for (i = 0; i < numVertices; i++) {
- TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]);
- TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y);
- TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]);
- }
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture));
- CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255));
- // check done above now
-// if(numVertices > 2)
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices);
-}
-
-void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha)
-{
- RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha));
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive) {
- bool alreadyThere = false;
- for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
- if (MapLegendList[i] == sprite)
- alreadyThere = true;
- }
- if (!alreadyThere) {
- MapLegendList[MapLegendCounter] = sprite;
- MapLegendCounter++;
- }
- }
-#endif
-}
-
-void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha)
-{
- CVector curPosn[4];
- CVector oldPosn[4];
-
- curPosn[0].x = x - SCREEN_SCALE_X(5.6f);
- curPosn[0].y = y + SCREEN_SCALE_Y(5.6f);
-
- curPosn[1].x = x + SCREEN_SCALE_X(5.6f);
- curPosn[1].y = y + SCREEN_SCALE_Y(5.6f);
-
- curPosn[2].x = x - SCREEN_SCALE_X(5.6f);
- curPosn[2].y = y - SCREEN_SCALE_Y(5.6f);
-
- curPosn[3].x = x + SCREEN_SCALE_X(5.6f);
- curPosn[3].y = y - SCREEN_SCALE_Y(5.6f);
-
- for (uint32 i = 0; i < 4; i++) {
- oldPosn[i] = curPosn[i];
-
- curPosn[i].x = x + (oldPosn[i].x - x) * Cos(angle) + (oldPosn[i].y - y) * Sin(angle);
- curPosn[i].y = y - (oldPosn[i].x - x) * Sin(angle) + (oldPosn[i].y - y) * Cos(angle);
- }
-
- sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha));
-}
-
-int32 CRadar::GetActualBlipArrayIndex(int32 i)
-{
- if (i == -1)
- return -1;
- else if ((i & 0xFFFF0000) >> 16 != ms_RadarTrace[(uint16)i].m_BlipIndex)
- return -1;
- else
- return (uint16)i;
-}
-
-int32 CRadar::GetNewUniqueBlipIndex(int32 i)
-{
- if (ms_RadarTrace[i].m_BlipIndex >= UINT16_MAX - 1)
- ms_RadarTrace[i].m_BlipIndex = 1;
- else
- ms_RadarTrace[i].m_BlipIndex++;
- return i | (ms_RadarTrace[i].m_BlipIndex << 16);
-}
-
-uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)
-{
- int32 c;
- switch (color) {
- case 0:
- if (bright)
- c = 0x712B49FF;
- else
- c = 0x7F0000FF;
- break;
- case 1:
- if (bright)
- c = 0x5FA06AFF;
- else
- c = 0x007F00FF;
- break;
- case 2:
- if (bright)
- c = 0x80A7F3FF;
- else
- c = 0x00007FFF;
- break;
- case 3:
- if (bright)
- c = 0xE1E1E1FF;
- else
- c = 0x7F7F7FFF;
- break;
- case 4:
- if (bright)
- c = 0xFFFF00FF;
- else
- c = 0x7F7F00FF;
- break;
- case 5:
- if (bright)
- c = 0xFF00FFFF;
- else
- c = 0x7F007FFF;
- break;
- case 6:
- if (bright)
- c = 0x00FFFFFF;
- else
- c = 0x007F7FFF;
- break;
- default:
- c = color;
- break;
- };
- return c;
-}
-
-const char* gRadarTexNames[] = {
- "radar00", "radar01", "radar02", "radar03", "radar04", "radar05", "radar06", "radar07",
- "radar08", "radar09", "radar10", "radar11", "radar12", "radar13", "radar14", "radar15",
- "radar16", "radar17", "radar18", "radar19", "radar20", "radar21", "radar22", "radar23",
- "radar24", "radar25", "radar26", "radar27", "radar28", "radar29", "radar30", "radar31",
- "radar32", "radar33", "radar34", "radar35", "radar36", "radar37", "radar38", "radar39",
- "radar40", "radar41", "radar42", "radar43", "radar44", "radar45", "radar46", "radar47",
- "radar48", "radar49", "radar50", "radar51", "radar52", "radar53", "radar54", "radar55",
- "radar56", "radar57", "radar58", "radar59", "radar60", "radar61", "radar62", "radar63",
-};
-
-void
-CRadar::Initialise()
-{
- for (int i = 0; i < NUMRADARBLIPS; i++) {
- ms_RadarTrace[i].m_BlipIndex = 1;
- SetRadarMarkerState(i, false);
- ms_RadarTrace[i].m_bInUse = false;
- ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
- ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
- ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
- }
-
- m_radarRange = 350.0f;
- for (int i = 0; i < 64; i++)
- gRadarTxdIds[i] = CTxdStore::FindTxdSlot(gRadarTexNames[i]);
-}
-
-float CRadar::LimitRadarPoint(CVector2D &point)
-{
- float dist, invdist;
-
- dist = point.Magnitude();
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive)
- return dist;
-#endif
- if (dist > 1.0f) {
- invdist = 1.0f / dist;
- point.x *= invdist;
- point.y *= invdist;
- }
- return dist;
-}
-
-void CRadar::LoadAllRadarBlips(uint8 *buf, uint32 size)
-{
- Initialise();
-INITSAVEBUF
- CheckSaveHeader(buf, 'R', 'D', 'R', '\0', size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUMRADARBLIPS; i++)
- ms_RadarTrace[i] = ReadSaveBuf<CBlip>(buf);
-
-VALIDATESAVEBUF(size);
-}
-
-void
-CRadar::LoadTextures()
-{
- CTxdStore::PushCurrentTxd();
- CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud"));
- AsukaSprite.SetTexture("radar_asuka");
- BombSprite.SetTexture("radar_bomb");
- CatSprite.SetTexture("radar_cat");
- CentreSprite.SetTexture("radar_centre");
- CopcarSprite.SetTexture("radar_copcar");
- DonSprite.SetTexture("radar_don");
- EightSprite.SetTexture("radar_eight");
- ElSprite.SetTexture("radar_el");
- IceSprite.SetTexture("radar_ice");
- JoeySprite.SetTexture("radar_joey");
- KenjiSprite.SetTexture("radar_kenji");
- LizSprite.SetTexture("radar_liz");
- LuigiSprite.SetTexture("radar_luigi");
- NorthSprite.SetTexture("radar_north");
- RaySprite.SetTexture("radar_ray");
- SalSprite.SetTexture("radar_sal");
- SaveSprite.SetTexture("radar_save");
- SpraySprite.SetTexture("radar_spray");
- TonySprite.SetTexture("radar_tony");
- WeaponSprite.SetTexture("radar_weapon");
- CTxdStore::PopCurrentTxd();
-}
-
-void RemoveMapSection(int32 x, int32 y)
-{
- if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
- CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]);
-}
-
-void CRadar::RemoveRadarSections()
-{
- for (int i = 0; i < 8; i++)
- for (int j = 0; j < 8; j++)
- RemoveMapSection(i, j);
-}
-
-void CRadar::RequestMapSection(int32 x, int32 y)
-{
- ClipRadarTileCoords(x, y);
- CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
-}
-
-void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size)
-{
- *size = SAVE_HEADER_SIZE + sizeof(ms_RadarTrace);
-INITSAVEBUF
- WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUMRADARBLIPS; i++)
- WriteSaveBuf(buf, ms_RadarTrace[i]);
-
-VALIDATESAVEBUF(*size);
-}
-
-void CRadar::SetBlipSprite(int32 i, int32 icon)
-{
- int index = CRadar::GetActualBlipArrayIndex(i);
- if (index != -1) {
- ms_RadarTrace[index].m_eRadarSprite = icon;
- }
-}
-
-int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay display)
-{
- int nextBlip;
- for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
- if (!ms_RadarTrace[nextBlip].m_bInUse)
- break;
- }
- ms_RadarTrace[nextBlip].m_eBlipType = type;
- ms_RadarTrace[nextBlip].m_nColor = color;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
- ms_RadarTrace[nextBlip].m_Radius = 1.0f;
- ms_RadarTrace[nextBlip].m_vec2DPos = pos;
- ms_RadarTrace[nextBlip].m_vecPos = pos;
- ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
- ms_RadarTrace[nextBlip].m_wScale = 1;
- ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
- ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
- return CRadar::GetNewUniqueBlipIndex(nextBlip);
-}
-
-int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDisplay display)
-{
- int nextBlip;
- for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
- if (!ms_RadarTrace[nextBlip].m_bInUse)
- break;
- }
- ms_RadarTrace[nextBlip].m_eBlipType = type;
- ms_RadarTrace[nextBlip].m_nColor = color;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
- ms_RadarTrace[nextBlip].m_Radius = 1.0f;
- ms_RadarTrace[nextBlip].m_nEntityHandle = handle;
- ms_RadarTrace[nextBlip].m_wScale = 1;
- ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
- ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
- return GetNewUniqueBlipIndex(nextBlip);
-}
-
-void CRadar::SetRadarMarkerState(int32 counter, bool flag)
-{
- CEntity *e;
- switch (ms_RadarTrace[counter].m_eBlipType) {
- case BLIP_CAR:
- e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
- break;
- case BLIP_CHAR:
- e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
- break;
- case BLIP_OBJECT:
- e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
- break;
- default:
- return;
- }
-
- if (e)
- e->bHasBlip = flag;
-}
-
-void CRadar::ShowRadarMarker(CVector pos, uint32 color, float radius) {
- float f1 = radius * 1.4f;
- float f2 = radius * 0.5f;
- CVector p1, p2;
-
- p1 = pos + TheCamera.GetUp()*f1;
- p2 = pos + TheCamera.GetUp()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-
- p1 = pos - TheCamera.GetUp()*f1;
- p2 = pos - TheCamera.GetUp()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-
- p1 = pos + TheCamera.GetRight()*f1;
- p2 = pos + TheCamera.GetRight()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-
- p1 = pos - TheCamera.GetRight()*f1;
- p2 = pos - TheCamera.GetRight()*f2;
- CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
-}
-
-void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha)
-{
- if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
- return;
-
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
-}
-
-void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode)
-{
- if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
- return;
-
- switch (mode)
- {
- case BLIP_MODE_TRIANGULAR_UP:
- // size++; // VC does size + 1 for triangles
- CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 3.0f), y + SCREEN_SCALE_Y(size + 2.0f), x - (SCREEN_SCALE_X(size + 3.0f)), y + SCREEN_SCALE_Y(size + 2.0f), x, y - (SCREEN_SCALE_Y(size + 3.0f)), x, y - (SCREEN_SCALE_Y(size + 3.0f)), CRGBA(0, 0, 0, alpha));
- CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 1.0f), y + SCREEN_SCALE_Y(size + 1.0f), x - (SCREEN_SCALE_X(size + 1.0f)), y + SCREEN_SCALE_Y(size + 1.0f), x, y - (SCREEN_SCALE_Y(size + 1.0f)), x, y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
- break;
- case BLIP_MODE_TRIANGULAR_DOWN:
- // size++; // VC does size + 1 for triangles
- CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 2.0f), x, y + SCREEN_SCALE_Y(size + 3.0f), x + SCREEN_SCALE_X(size + 3.0f), y - (SCREEN_SCALE_Y(size + 2.0f)), x - (SCREEN_SCALE_X(size + 3.0f)), y - (SCREEN_SCALE_Y(size + 2.0f)), CRGBA(0, 0, 0, alpha));
- CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 1.0f), x, y + SCREEN_SCALE_Y(size + 1.0f), x + SCREEN_SCALE_X(size + 1.0f), y - (SCREEN_SCALE_Y(size + 1.0f)), x - (SCREEN_SCALE_X(size + 1.0f)), y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
- break;
- case BLIP_MODE_SQUARE:
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
- CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
- break;
- }
-#ifdef MENU_MAP
- // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips
- if (CMenuManager::bMenuMapActive) {
- bool alreadyThere = false;
- for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
- if (MapLegendList[i] == -1)
- alreadyThere = true;
- }
- if (!alreadyThere) {
- MapLegendList[MapLegendCounter] = -1;
- MapLegendCounter++;
- ArrowBlipColour1 = CRGBA(red, green, blue, alpha);
- }
- }
-#endif
-}
-
-void CRadar::Shutdown()
-{
- AsukaSprite.Delete();
- BombSprite.Delete();
- CatSprite.Delete();
- CentreSprite.Delete();
- CopcarSprite.Delete();
- DonSprite.Delete();
- EightSprite.Delete();
- ElSprite.Delete();
- IceSprite.Delete();
- JoeySprite.Delete();
- KenjiSprite.Delete();
- LizSprite.Delete();
- LuigiSprite.Delete();
- NorthSprite.Delete();
- RaySprite.Delete();
- SalSprite.Delete();
- SaveSprite.Delete();
- SpraySprite.Delete();
- TonySprite.Delete();
- WeaponSprite.Delete();
- RemoveRadarSections();
-}
-
-void CRadar::StreamRadarSections(const CVector &posn)
-{
- StreamRadarSections(floorf((2000.0f + posn.x) / 500.0f), ceilf(7.0f - (2000.0f + posn.y) / 500.0f));
-}
-
-void CRadar::StreamRadarSections(int32 x, int32 y)
-{
- for (int i = 0; i < RADAR_NUM_TILES; ++i) {
- for (int j = 0; j < RADAR_NUM_TILES; ++j) {
- if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1))
- RequestMapSection(i, j);
- else
- RemoveMapSection(i, j);
- };
- };
-}
-
-void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y)
-{
- out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X);
- out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y));
- out.x /= RADAR_TILE_SIZE;
- out.y /= RADAR_TILE_SIZE;
-}
-
-void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in)
-{
- float s, c;
-#if 1
- s = -cachedSin;
- c = cachedCos;
-#else
- // Original code
-
- s = -Sin(TheCamera.GetForward().Heading());
- c = Cos(TheCamera.GetForward().Heading());
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
- s = 0.0f;
- c = 1.0f;
- }
- else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) {
- CVector forward;
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
- forward.Normalise(); // a bit useless...
- }
- else
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
-
- s = -Sin(forward.Heading());
- c = Cos(forward.Heading());
- }
-#endif
-
- out.x = s * in.y + c * in.x;
- out.y = c * in.y - s * in.x;
-
- out = out * m_radarRange + vec2DRadarOrigin;
-}
-
-// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0)
-void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in)
+#include "config.h"
+#include "common.h"
+#include "patcher.h"
+#include "RwHelper.h"
+#include "Radar.h"
+#include "Camera.h"
+#include "Hud.h"
+#include "World.h"
+#include "Frontend.h"
+#include "General.h"
+#include "Vehicle.h"
+#include "Pools.h"
+#include "Script.h"
+#include "TxdStore.h"
+#include "World.h"
+#include "Streaming.h"
+#include "SpecialFX.h"
+
+float &CRadar::m_radarRange = *(float*)0x8E281C;
+CBlip (&CRadar::ms_RadarTrace)[NUMRADARBLIPS] = *(CBlip(*)[NUMRADARBLIPS]) * (uintptr*)0x6ED5E0;
+CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8;
+int32 gRadarTxdIds[64];// = (int*)0x6299C0;
+
+CSprite2d CRadar::AsukaSprite;// = *(CSprite2d*)0x8F1A40;
+CSprite2d CRadar::BombSprite;// = (CSprite2d*)0x8F5FB4;
+CSprite2d CRadar::CatSprite;// = (CSprite2d*)0x885B24;
+CSprite2d CRadar::CentreSprite;// = (CSprite2d*)0x8F6268;
+CSprite2d CRadar::CopcarSprite;// = (CSprite2d*)0x8F1A2C;
+CSprite2d CRadar::DonSprite;// = (CSprite2d*)0x8F2BE0;
+CSprite2d CRadar::EightSprite;// = (CSprite2d*)0x8F2BCC;
+CSprite2d CRadar::ElSprite;// = (CSprite2d*)0x8F1B80;
+CSprite2d CRadar::IceSprite;// = (CSprite2d*)0x9415FC;
+CSprite2d CRadar::JoeySprite;// = (CSprite2d*)0x8F2C00;
+CSprite2d CRadar::KenjiSprite;// = (CSprite2d*)0x8F2C68;
+CSprite2d CRadar::LizSprite;// = (CSprite2d*)0x8F5830;
+CSprite2d CRadar::LuigiSprite;// = (CSprite2d*)0x8F1A3C;
+CSprite2d CRadar::NorthSprite;// = (CSprite2d*)0x8F6274;
+CSprite2d CRadar::RaySprite;// = (CSprite2d*)0x8E2A7C;
+CSprite2d CRadar::SalSprite;// = (CSprite2d*)0x8F29EC;
+CSprite2d CRadar::SaveSprite;// = (CSprite2d*)0x8F5F74;
+CSprite2d CRadar::SpraySprite;// = (CSprite2d*)0x94307C;
+CSprite2d CRadar::TonySprite;// = (CSprite2d*)0x885B58;
+CSprite2d CRadar::WeaponSprite;// = (CSprite2d*)0x941534;
+
+CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = {
+ nil,
+ &AsukaSprite,
+ &BombSprite,
+ &CatSprite,
+ &CentreSprite,
+ &CopcarSprite,
+ &DonSprite,
+ &EightSprite,
+ &ElSprite,
+ &IceSprite,
+ &JoeySprite,
+ &KenjiSprite,
+ &LizSprite,
+ &LuigiSprite,
+ &NorthSprite,
+ &RaySprite,
+ &SalSprite,
+ &SaveSprite,
+ &SpraySprite,
+ &TonySprite,
+ &WeaponSprite
+};
+
+#define RADAR_NUM_TILES (8)
+#define RADAR_TILE_SIZE (WORLD_SIZE_X / RADAR_NUM_TILES)
+static_assert(RADAR_TILE_SIZE == (WORLD_SIZE_Y / RADAR_NUM_TILES), "CRadar: not a square");
+
+#define RADAR_MIN_RANGE (120.0f)
+#define RADAR_MAX_RANGE (350.0f)
+#define RADAR_MIN_SPEED (0.3f)
+#define RADAR_MAX_SPEED (0.9f)
+
+#ifdef MENU_MAP
+CRGBA CRadar::ArrowBlipColour1;
+CRGBA CRadar::ArrowBlipColour2;
+uint16 CRadar::MapLegendCounter;
+uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS];
+int CRadar::TargetMarkerId = -1;
+#endif
+
+// taken from VC
+float CRadar::cachedCos;
+float CRadar::cachedSin;
+
+uint8 CRadar::CalculateBlipAlpha(float dist)
{
-#ifdef MENU_MAP
- if (CMenuManager::bMenuMapActive) {
- // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0.
- out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f;
- out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f;
- } else
-#endif
- {
-#ifdef FIX_BUGS
- out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT);
-#else
- out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + RADAR_LEFT;
-#endif
- out.y = (1.0f - in.y) * 0.5f * SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT);
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive)
+ return 255;
+#endif
+ if (dist <= 1.0f)
+ return 255;
+
+ if (dist <= 5.0f)
+ return (128.0f * ((dist - 1.0f) / 4.0f)) + ((1.0f - (dist - 1.0f) / 4.0f) * 255.0f);
+
+ return 128;
+}
+
+void CRadar::ChangeBlipBrightness(int32 i, int32 bright)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_bDim = bright != 1;
+}
+
+void CRadar::ChangeBlipColour(int32 i, int32 color)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_nColor = color;
+}
+
+void CRadar::ChangeBlipDisplay(int32 i, eBlipDisplay display)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_eBlipDisplay = display;
+}
+
+void CRadar::ChangeBlipScale(int32 i, int32 scale)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1)
+ ms_RadarTrace[index].m_wScale = scale;
+}
+
+void CRadar::ClearBlip(int32 i)
+{
+ int index = GetActualBlipArrayIndex(i);
+ if (index != -1) {
+ SetRadarMarkerState(index, false);
+ ms_RadarTrace[index].m_bInUse = false;
+#ifndef MENU_MAP
+ // Ssshhh
+ ms_RadarTrace[index].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE;
+#endif
+ }
+}
+
+void CRadar::ClearBlipForEntity(eBlipType type, int32 id)
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ if (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) {
+ SetRadarMarkerState(i, false);
+ ms_RadarTrace[i].m_bInUse = false;
+ ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
+ }
+ };
+}
+
+// Why not a proper clipping algorithm?
+int CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect)
+{
+ CVector2D corners[4] = {
+ { 1.0f, -1.0f }, // top right
+ { 1.0f, 1.0f }, // bottom right
+ { -1.0f, 1.0f }, // bottom left
+ { -1.0f, -1.0f }, // top left
+ };
+ CVector2D tmp;
+ int i, j, n;
+ int laste, e, e1, e2;;
+ bool inside[4];
+
+ for (i = 0; i < 4; i++)
+ inside[i] = IsPointInsideRadar(rect[i]);
+
+ laste = -1;
+ n = 0;
+ for (i = 0; i < 4; i++)
+ if (inside[i]) {
+ // point is inside, just add
+ poly[n++] = rect[i];
+ }
+ else {
+ // point is outside but line to this point might be clipped
+ e1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]);
+ if (e1 != -1) {
+ laste = e1;
+ n++;
+ }
+ // and line from this point might be clipped as well
+ e2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]);
+ if (e2 != -1) {
+ if (e1 == -1) {
+ // if other line wasn't clipped, i.e. it was complete outside,
+ // we may have to insert another vertex if last clipped line
+ // was on a different edge
+
+ // find the last intersection if we haven't seen it yet
+ if (laste == -1)
+ for (j = 3; j >= i; j--) {
+ // game uses an if here for j == 0
+ e = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]);
+ if (e != -1) {
+ laste = e;
+ break;
+ }
+ }
+ assert(laste != -1);
+
+ // insert corners that were skipped
+ tmp = poly[n];
+ for (e = laste; e != e2; e = (e + 1) % 4)
+ poly[n++] = corners[e];
+ poly[n] = tmp;
+ }
+ n++;
+ }
+ }
+
+ if (n == 0) {
+ // If no points, either the rectangle is completely outside or completely surrounds the radar
+ // no idea what's going on here...
+ float m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x);
+ if ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
+ m = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x);
+ if ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) {
+ poly[0] = corners[0];
+ poly[1] = corners[1];
+ poly[2] = corners[2];
+ poly[3] = corners[3];
+ n = 4;
+ }
+ }
+ }
+
+ return n;
+}
+
+bool CRadar::DisplayThisBlip(int32 counter)
+{
+ switch (ms_RadarTrace[counter].m_eRadarSprite) {
+ case RADAR_SPRITE_BOMB:
+ case RADAR_SPRITE_SPRAY:
+ case RADAR_SPRITE_WEAPON:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void CRadar::Draw3dMarkers()
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ if (ms_RadarTrace[i].m_bInUse) {
+ switch (ms_RadarTrace[i].m_eBlipType) {
+ case BLIP_CAR:
+ {
+ CEntity *entity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ CVector pos = entity->GetPosition();
+ pos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f;
+ C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
+ }
+ break;
+ }
+ case BLIP_CHAR:
+ {
+ CEntity *entity = CPools::GetPedPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
+ if (entity != nil) {
+ if (((CPed*)entity)->InVehicle())
+ entity = ((CPed * )entity)->m_pMyVehicle;
+ }
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ CVector pos = entity->GetPosition();
+ pos.z += 3.0f;
+ C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5);
+ }
+ break;
+ }
+ case BLIP_OBJECT:
+ {
+ CEntity *entity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ CVector pos = entity->GetPosition();
+ pos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f;
+ C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5);
+ }
+ break;
+ }
+ case BLIP_COORD:
+ break;
+ case BLIP_CONTACT_POINT:
+ if (!CTheScripts::IsPlayerOnAMission()) {
+ if (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY)
+ C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0);
+ }
+ break;
+ }
+ }
+ }
+}
+
+void CRadar::DrawBlips()
+{
+ if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+
+ CVector2D out;
+ CVector2D in = CVector2D(0.0f, 0.0f);
+ TransformRadarPointToScreenSpace(out, in);
+
+#ifdef MENU_MAP
+ if (!CMenuManager::bMenuMapActive) {
+#endif
+ float angle;
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN)
+ angle = PI + FindPlayerHeading();
+#ifdef FIX_BUGS
+ else if (TheCamera.GetLookDirection() != LOOKING_FORWARD)
+ angle = FindPlayerHeading() - (PI + (TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind).Heading());
+#endif
+ else
+ angle = FindPlayerHeading() - (PI + TheCamera.GetForward().Heading());
+
+ DrawRotatingRadarSprite(&CentreSprite, out.x, out.y, angle, 255);
+
+ CVector2D vec2d;
+ vec2d.x = vec2DRadarOrigin.x;
+ vec2d.y = M_SQRT2 * m_radarRange + vec2DRadarOrigin.y;
+ TransformRealWorldPointToRadarSpace(in, vec2d);
+ LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255);
+#ifdef MENU_MAP
+ }
+#endif
+
+ CEntity *blipEntity = nil;
+ for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
+#ifdef MENU_MAP
+ // A little hack to reuse cleared blips in menu map. hehe
+ if (!CMenuManager::bMenuMapActive || ms_RadarTrace[blipId].m_eBlipType == BLIP_CAR ||
+ ms_RadarTrace[blipId].m_eBlipType == BLIP_CHAR || ms_RadarTrace[blipId].m_eBlipType == BLIP_OBJECT)
+#endif
+ if (!ms_RadarTrace[blipId].m_bInUse)
+ continue;
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ case BLIP_CHAR:
+ case BLIP_OBJECT:
+ if (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
+ || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON) {
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ case BLIP_CHAR:
+ blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ if (blipEntity != nil) {
+ if (((CPed*)blipEntity)->InVehicle())
+ blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
+ }
+ break;
+ case BLIP_OBJECT:
+ blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ default:
+ break;
+ }
+ if (blipEntity) {
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ } else {
+#ifdef TRIANGULAR_BLIPS
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = blipEntity->GetPosition();
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ }
+ }
+ break;
+ case BLIP_COORD:
+ case BLIP_CONTACT_POINT:
+ if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_BOMB || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE
+ || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_WEAPON)
+ && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
+
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ } else {
+#ifdef TRIANGULAR_BLIPS
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
+ if (!ms_RadarTrace[blipId].m_bInUse)
+ continue;
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ case BLIP_CHAR:
+ case BLIP_OBJECT:
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
+ && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON) {
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_CAR:
+ blipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ case BLIP_CHAR:
+ blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ if (blipEntity != nil) {
+ if (((CPed*)blipEntity)->InVehicle())
+ blipEntity = ((CPed*)blipEntity)->m_pMyVehicle;
+ }
+ break;
+ case BLIP_OBJECT:
+ blipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);
+ break;
+ default:
+ break;
+ }
+
+ if (blipEntity) {
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ else
+#ifdef TRIANGULAR_BLIPS
+ {
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = blipEntity->GetPosition();
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+ }
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ for (int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {
+ if (!ms_RadarTrace[blipId].m_bInUse)
+ continue;
+
+ switch (ms_RadarTrace[blipId].m_eBlipType) {
+ case BLIP_COORD:
+ case BLIP_CONTACT_POINT:
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_BOMB && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE
+ && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_WEAPON
+ && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) {
+
+ uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {
+ if (CTheScripts::IsDebugOn()) {
+ ShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);
+ ms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;
+ if (ms_RadarTrace[blipId].m_Radius < 1.0f)
+ ms_RadarTrace[blipId].m_Radius = 5.0f;
+ }
+ }
+ if (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {
+ TransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);
+ float dist = LimitRadarPoint(in);
+ TransformRadarPointToScreenSpace(out, in);
+ if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE)
+ DrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));
+ else
+#ifdef TRIANGULAR_BLIPS
+ {
+ CVector &pos = FindPlayerCentreOfWorld_NoSniperShift();
+ CVector &blipPos = ms_RadarTrace[blipId].m_vecPos;
+ uint8 mode = BLIP_MODE_TRIANGULAR_UP;
+ if (blipPos.z - pos.z <= 2.0f) {
+ if (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;
+ else mode = BLIP_MODE_SQUARE;
+ }
+ ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);
+ }
+#else
+ ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);
+#endif
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive) {
+ CVector2D in, out;
+ TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift());
+ TransformRadarPointToScreenSpace(out, in);
+ DrawYouAreHereSprite(out.x, out.y);
+ }
+#endif
+ }
+}
+
+void CRadar::DrawMap()
+{
+ if (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {
+#if 1 // from VC
+ CalculateCachedSinCos();
+#endif
+ if (FindPlayerVehicle()) {
+ float speed = FindPlayerSpeed().Magnitude();
+ if (speed < RADAR_MIN_SPEED)
+ m_radarRange = RADAR_MIN_RANGE;
+ else if (speed < RADAR_MAX_SPEED)
+ m_radarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;
+ else
+ m_radarRange = RADAR_MAX_RANGE;
+ }
+ else
+ m_radarRange = RADAR_MIN_RANGE;
+
+ vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift());
+ DrawRadarMap();
+ }
+}
+
+void CRadar::DrawRadarMap()
+{
+ // Game calculates an unused CRect here
+
+ DrawRadarMask();
+
+ // top left ist (0, 0)
+ int x = floorf((vec2DRadarOrigin.x - WORLD_MIN_X) / RADAR_TILE_SIZE);
+ int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - WORLD_MIN_Y) / RADAR_TILE_SIZE);
+ StreamRadarSections(x, y);
+
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
+ RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE);
+
+ DrawRadarSection(x - 1, y - 1);
+ DrawRadarSection(x, y - 1);
+ DrawRadarSection(x + 1, y - 1);
+ DrawRadarSection(x - 1, y);
+ DrawRadarSection(x, y);
+ DrawRadarSection(x + 1, y);
+ DrawRadarSection(x - 1, y + 1);
+ DrawRadarSection(x, y + 1);
+ DrawRadarSection(x + 1, y + 1);
+}
+
+void CRadar::DrawRadarMask()
+{
+ CVector2D corners[4] = {
+ CVector2D(1.0f, -1.0f),
+ CVector2D(1.0f, 1.0f),
+ CVector2D(-1.0f, 1.0f),
+ CVector2D(-1.0, -1.0f)
+ };
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+
+ CVector2D out[8];
+ CVector2D in;
+
+ // Draw the shape we want to mask out from the radar in four segments
+ for (int i = 0; i < 4; i++) {
+ // First point is always the corner itself
+ in.x = corners[i].x;
+ in.y = corners[i].y;
+ TransformRadarPointToScreenSpace(out[0], in);
+
+ // Then generate a quarter of the circle
+ for (int j = 0; j < 7; j++) {
+ in.x = corners[i].x * Cos(j * (PI / 2.0f / 6.0f));
+ in.y = corners[i].y * Sin(j * (PI / 2.0f / 6.0f));
+ TransformRadarPointToScreenSpace(out[j + 1], in);
+ };
+
+ CSprite2d::SetMaskVertices(8, (float *)out);
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8);
+ };
+}
+
+void CRadar::DrawRadarSection(int32 x, int32 y)
+{
+ int i;
+ RwTexDictionary *txd;
+ CVector2D worldPoly[8];
+ CVector2D radarCorners[4];
+ CVector2D radarPoly[8];
+ CVector2D texCoords[8];
+ CVector2D screenPoly[8];
+ int numVertices;
+ RwTexture *texture = nil;
+
+ GetTextureCorners(x, y, worldPoly);
+ ClipRadarTileCoords(x, y);
+
+ assert(CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y]));
+ txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict;
+ if (txd)
+ texture = GetFirstTexture(txd);
+ if (texture == nil)
+ return;
+
+ for (i = 0; i < 4; i++)
+ TransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]);
+
+ numVertices = ClipRadarPoly(radarPoly, radarCorners);
+
+ // FIX: can return earlier here
+// if(numVertices == 0)
+ if (numVertices < 3)
+ return;
+
+ for (i = 0; i < numVertices; i++) {
+ TransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]);
+ TransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y);
+ TransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]);
+ }
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture));
+ CSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255));
+ // check done above now
+// if(numVertices > 2)
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices);
+}
+
+void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha)
+{
+ RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha));
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive) {
+ bool alreadyThere = false;
+ for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
+ if (MapLegendList[i] == sprite)
+ alreadyThere = true;
+ }
+ if (!alreadyThere) {
+ MapLegendList[MapLegendCounter] = sprite;
+ MapLegendCounter++;
+ }
+ }
+#endif
+}
+
+void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha)
+{
+ CVector curPosn[4];
+ CVector oldPosn[4];
+
+ curPosn[0].x = x - SCREEN_SCALE_X(5.6f);
+ curPosn[0].y = y + SCREEN_SCALE_Y(5.6f);
+
+ curPosn[1].x = x + SCREEN_SCALE_X(5.6f);
+ curPosn[1].y = y + SCREEN_SCALE_Y(5.6f);
+
+ curPosn[2].x = x - SCREEN_SCALE_X(5.6f);
+ curPosn[2].y = y - SCREEN_SCALE_Y(5.6f);
+
+ curPosn[3].x = x + SCREEN_SCALE_X(5.6f);
+ curPosn[3].y = y - SCREEN_SCALE_Y(5.6f);
+
+ for (uint32 i = 0; i < 4; i++) {
+ oldPosn[i] = curPosn[i];
+
+ curPosn[i].x = x + (oldPosn[i].x - x) * Cos(angle) + (oldPosn[i].y - y) * Sin(angle);
+ curPosn[i].y = y - (oldPosn[i].x - x) * Sin(angle) + (oldPosn[i].y - y) * Cos(angle);
+ }
+
+ sprite->Draw(curPosn[2].x, curPosn[2].y, curPosn[3].x, curPosn[3].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha));
+}
+
+int32 CRadar::GetActualBlipArrayIndex(int32 i)
+{
+ if (i == -1)
+ return -1;
+ else if ((i & 0xFFFF0000) >> 16 != ms_RadarTrace[(uint16)i].m_BlipIndex)
+ return -1;
+ else
+ return (uint16)i;
+}
+
+int32 CRadar::GetNewUniqueBlipIndex(int32 i)
+{
+ if (ms_RadarTrace[i].m_BlipIndex >= UINT16_MAX - 1)
+ ms_RadarTrace[i].m_BlipIndex = 1;
+ else
+ ms_RadarTrace[i].m_BlipIndex++;
+ return i | (ms_RadarTrace[i].m_BlipIndex << 16);
+}
+
+uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)
+{
+ int32 c;
+ switch (color) {
+ case 0:
+ if (bright)
+ c = 0x712B49FF;
+ else
+ c = 0x7F0000FF;
+ break;
+ case 1:
+ if (bright)
+ c = 0x5FA06AFF;
+ else
+ c = 0x007F00FF;
+ break;
+ case 2:
+ if (bright)
+ c = 0x80A7F3FF;
+ else
+ c = 0x00007FFF;
+ break;
+ case 3:
+ if (bright)
+ c = 0xE1E1E1FF;
+ else
+ c = 0x7F7F7FFF;
+ break;
+ case 4:
+ if (bright)
+ c = 0xFFFF00FF;
+ else
+ c = 0x7F7F00FF;
+ break;
+ case 5:
+ if (bright)
+ c = 0xFF00FFFF;
+ else
+ c = 0x7F007FFF;
+ break;
+ case 6:
+ if (bright)
+ c = 0x00FFFFFF;
+ else
+ c = 0x007F7FFF;
+ break;
+ default:
+ c = color;
+ break;
+ };
+ return c;
+}
+
+const char* gRadarTexNames[] = {
+ "radar00", "radar01", "radar02", "radar03", "radar04", "radar05", "radar06", "radar07",
+ "radar08", "radar09", "radar10", "radar11", "radar12", "radar13", "radar14", "radar15",
+ "radar16", "radar17", "radar18", "radar19", "radar20", "radar21", "radar22", "radar23",
+ "radar24", "radar25", "radar26", "radar27", "radar28", "radar29", "radar30", "radar31",
+ "radar32", "radar33", "radar34", "radar35", "radar36", "radar37", "radar38", "radar39",
+ "radar40", "radar41", "radar42", "radar43", "radar44", "radar45", "radar46", "radar47",
+ "radar48", "radar49", "radar50", "radar51", "radar52", "radar53", "radar54", "radar55",
+ "radar56", "radar57", "radar58", "radar59", "radar60", "radar61", "radar62", "radar63",
+};
+
+void
+CRadar::Initialise()
+{
+ for (int i = 0; i < NUMRADARBLIPS; i++) {
+ ms_RadarTrace[i].m_BlipIndex = 1;
+ SetRadarMarkerState(i, false);
+ ms_RadarTrace[i].m_bInUse = false;
+ ms_RadarTrace[i].m_eBlipType = BLIP_NONE;
+ ms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;
+ ms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;
+ }
+
+ m_radarRange = 350.0f;
+ for (int i = 0; i < 64; i++)
+ gRadarTxdIds[i] = CTxdStore::FindTxdSlot(gRadarTexNames[i]);
+}
+
+float CRadar::LimitRadarPoint(CVector2D &point)
+{
+ float dist, invdist;
+
+ dist = point.Magnitude();
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive)
+ return dist;
+#endif
+ if (dist > 1.0f) {
+ invdist = 1.0f / dist;
+ point.x *= invdist;
+ point.y *= invdist;
+ }
+ return dist;
+}
+
+void CRadar::LoadAllRadarBlips(uint8 *buf, uint32 size)
+{
+ Initialise();
+INITSAVEBUF
+ CheckSaveHeader(buf, 'R', 'D', 'R', '\0', size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUMRADARBLIPS; i++)
+ ms_RadarTrace[i] = ReadSaveBuf<CBlip>(buf);
+
+VALIDATESAVEBUF(size);
+}
+
+void
+CRadar::LoadTextures()
+{
+ CTxdStore::PushCurrentTxd();
+ CTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot("hud"));
+ AsukaSprite.SetTexture("radar_asuka");
+ BombSprite.SetTexture("radar_bomb");
+ CatSprite.SetTexture("radar_cat");
+ CentreSprite.SetTexture("radar_centre");
+ CopcarSprite.SetTexture("radar_copcar");
+ DonSprite.SetTexture("radar_don");
+ EightSprite.SetTexture("radar_eight");
+ ElSprite.SetTexture("radar_el");
+ IceSprite.SetTexture("radar_ice");
+ JoeySprite.SetTexture("radar_joey");
+ KenjiSprite.SetTexture("radar_kenji");
+ LizSprite.SetTexture("radar_liz");
+ LuigiSprite.SetTexture("radar_luigi");
+ NorthSprite.SetTexture("radar_north");
+ RaySprite.SetTexture("radar_ray");
+ SalSprite.SetTexture("radar_sal");
+ SaveSprite.SetTexture("radar_save");
+ SpraySprite.SetTexture("radar_spray");
+ TonySprite.SetTexture("radar_tony");
+ WeaponSprite.SetTexture("radar_weapon");
+ CTxdStore::PopCurrentTxd();
+}
+
+void RemoveMapSection(int32 x, int32 y)
+{
+ if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
+ CStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]);
+}
+
+void CRadar::RemoveRadarSections()
+{
+ for (int i = 0; i < 8; i++)
+ for (int j = 0; j < 8; j++)
+ RemoveMapSection(i, j);
+}
+
+void CRadar::RequestMapSection(int32 x, int32 y)
+{
+ ClipRadarTileCoords(x, y);
+ CStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
+}
+
+void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size)
+{
+ *size = SAVE_HEADER_SIZE + sizeof(ms_RadarTrace);
+INITSAVEBUF
+ WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUMRADARBLIPS; i++)
+ WriteSaveBuf(buf, ms_RadarTrace[i]);
+
+VALIDATESAVEBUF(*size);
+}
+
+void CRadar::SetBlipSprite(int32 i, int32 icon)
+{
+ int index = CRadar::GetActualBlipArrayIndex(i);
+ if (index != -1) {
+ ms_RadarTrace[index].m_eRadarSprite = icon;
+ }
+}
+
+int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay display)
+{
+ int nextBlip;
+ for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+ if (!ms_RadarTrace[nextBlip].m_bInUse)
+ break;
+ }
+ ms_RadarTrace[nextBlip].m_eBlipType = type;
+ ms_RadarTrace[nextBlip].m_nColor = color;
+ ms_RadarTrace[nextBlip].m_bDim = 1;
+ ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_Radius = 1.0f;
+ ms_RadarTrace[nextBlip].m_vec2DPos = pos;
+ ms_RadarTrace[nextBlip].m_vecPos = pos;
+ ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
+ ms_RadarTrace[nextBlip].m_wScale = 1;
+ ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
+ ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
+ return CRadar::GetNewUniqueBlipIndex(nextBlip);
+}
+
+int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDisplay display)
+{
+ int nextBlip;
+ for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+ if (!ms_RadarTrace[nextBlip].m_bInUse)
+ break;
+ }
+ ms_RadarTrace[nextBlip].m_eBlipType = type;
+ ms_RadarTrace[nextBlip].m_nColor = color;
+ ms_RadarTrace[nextBlip].m_bDim = 1;
+ ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_Radius = 1.0f;
+ ms_RadarTrace[nextBlip].m_nEntityHandle = handle;
+ ms_RadarTrace[nextBlip].m_wScale = 1;
+ ms_RadarTrace[nextBlip].m_eBlipDisplay = display;
+ ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
+ return GetNewUniqueBlipIndex(nextBlip);
+}
+
+void CRadar::SetRadarMarkerState(int32 counter, bool flag)
+{
+ CEntity *e;
+ switch (ms_RadarTrace[counter].m_eBlipType) {
+ case BLIP_CAR:
+ e = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
+ break;
+ case BLIP_CHAR:
+ e = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
+ break;
+ case BLIP_OBJECT:
+ e = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);
+ break;
+ default:
+ return;
+ }
+
+ if (e)
+ e->bHasBlip = flag;
+}
+
+void CRadar::ShowRadarMarker(CVector pos, uint32 color, float radius) {
+ float f1 = radius * 1.4f;
+ float f2 = radius * 0.5f;
+ CVector p1, p2;
+
+ p1 = pos + TheCamera.GetUp()*f1;
+ p2 = pos + TheCamera.GetUp()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+
+ p1 = pos - TheCamera.GetUp()*f1;
+ p2 = pos - TheCamera.GetUp()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+
+ p1 = pos + TheCamera.GetRight()*f1;
+ p2 = pos + TheCamera.GetRight()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+
+ p1 = pos - TheCamera.GetRight()*f1;
+ p2 = pos - TheCamera.GetRight()*f2;
+ CTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);
+}
+
+void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha)
+{
+ if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
+ return;
+
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
+}
+
+void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode)
+{
+ if (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)
+ return;
+
+ switch (mode)
+ {
+ case BLIP_MODE_TRIANGULAR_UP:
+ // size++; // VC does size + 1 for triangles
+ CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 3.0f), y + SCREEN_SCALE_Y(size + 2.0f), x - (SCREEN_SCALE_X(size + 3.0f)), y + SCREEN_SCALE_Y(size + 2.0f), x, y - (SCREEN_SCALE_Y(size + 3.0f)), x, y - (SCREEN_SCALE_Y(size + 3.0f)), CRGBA(0, 0, 0, alpha));
+ CSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 1.0f), y + SCREEN_SCALE_Y(size + 1.0f), x - (SCREEN_SCALE_X(size + 1.0f)), y + SCREEN_SCALE_Y(size + 1.0f), x, y - (SCREEN_SCALE_Y(size + 1.0f)), x, y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
+ break;
+ case BLIP_MODE_TRIANGULAR_DOWN:
+ // size++; // VC does size + 1 for triangles
+ CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 2.0f), x, y + SCREEN_SCALE_Y(size + 3.0f), x + SCREEN_SCALE_X(size + 3.0f), y - (SCREEN_SCALE_Y(size + 2.0f)), x - (SCREEN_SCALE_X(size + 3.0f)), y - (SCREEN_SCALE_Y(size + 2.0f)), CRGBA(0, 0, 0, alpha));
+ CSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 1.0f), x, y + SCREEN_SCALE_Y(size + 1.0f), x + SCREEN_SCALE_X(size + 1.0f), y - (SCREEN_SCALE_Y(size + 1.0f)), x - (SCREEN_SCALE_X(size + 1.0f)), y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));
+ break;
+ case BLIP_MODE_SQUARE:
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));
+ CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));
+ break;
+ }
+#ifdef MENU_MAP
+ // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips
+ if (CMenuManager::bMenuMapActive) {
+ bool alreadyThere = false;
+ for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
+ if (MapLegendList[i] == -1)
+ alreadyThere = true;
+ }
+ if (!alreadyThere) {
+ MapLegendList[MapLegendCounter] = -1;
+ MapLegendCounter++;
+ ArrowBlipColour1 = CRGBA(red, green, blue, alpha);
+ }
+ }
+#endif
+}
+
+void CRadar::Shutdown()
+{
+ AsukaSprite.Delete();
+ BombSprite.Delete();
+ CatSprite.Delete();
+ CentreSprite.Delete();
+ CopcarSprite.Delete();
+ DonSprite.Delete();
+ EightSprite.Delete();
+ ElSprite.Delete();
+ IceSprite.Delete();
+ JoeySprite.Delete();
+ KenjiSprite.Delete();
+ LizSprite.Delete();
+ LuigiSprite.Delete();
+ NorthSprite.Delete();
+ RaySprite.Delete();
+ SalSprite.Delete();
+ SaveSprite.Delete();
+ SpraySprite.Delete();
+ TonySprite.Delete();
+ WeaponSprite.Delete();
+ RemoveRadarSections();
+}
+
+void CRadar::StreamRadarSections(const CVector &posn)
+{
+ StreamRadarSections(floorf((2000.0f + posn.x) / 500.0f), ceilf(7.0f - (2000.0f + posn.y) / 500.0f));
+}
+
+void CRadar::StreamRadarSections(int32 x, int32 y)
+{
+ for (int i = 0; i < RADAR_NUM_TILES; ++i) {
+ for (int j = 0; j < RADAR_NUM_TILES; ++j) {
+ if ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1))
+ RequestMapSection(i, j);
+ else
+ RemoveMapSection(i, j);
+ };
+ };
+}
+
+void CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y)
+{
+ out.x = in.x - (x * RADAR_TILE_SIZE + WORLD_MIN_X);
+ out.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + WORLD_MIN_Y));
+ out.x /= RADAR_TILE_SIZE;
+ out.y /= RADAR_TILE_SIZE;
+}
+
+void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in)
+{
+ float s, c;
+#if 1
+ s = -cachedSin;
+ c = cachedCos;
+#else
+ // Original code
+
+ s = -Sin(TheCamera.GetForward().Heading());
+ c = Cos(TheCamera.GetForward().Heading());
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
+ s = 0.0f;
+ c = 1.0f;
+ }
+ else if (TheCamera.GetLookDirection() != LOOKING_FORWARD) {
+ CVector forward;
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
+ forward.Normalise(); // a bit useless...
+ }
+ else
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
+
+ s = -Sin(forward.Heading());
+ c = Cos(forward.Heading());
+ }
+#endif
+
+ out.x = s * in.y + c * in.x;
+ out.y = c * in.y - s * in.x;
+
+ out = out * m_radarRange + vec2DRadarOrigin;
+}
+
+// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0)
+void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in)
+{
+#ifdef MENU_MAP
+ if (CMenuManager::bMenuMapActive) {
+ // fMapSize is actually half map size. Radar range is 1000, so if x is -2000, in.x + 2.0f is 0.
+ out.x = (CMenuManager::fMapCenterX - CMenuManager::fMapSize) + (in.x + 2.0f) * CMenuManager::fMapSize * 2.0f / 4.0f;
+ out.y = (CMenuManager::fMapCenterY - CMenuManager::fMapSize) + (2.0f - in.y) * CMenuManager::fMapSize * 2.0f / 4.0f;
+ } else
+#endif
+ {
+#ifdef FIX_BUGS
+ out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT);
+#else
+ out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + RADAR_LEFT;
+#endif
+ out.y = (1.0f - in.y) * 0.5f * SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT);
+ }
+}
+
+void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in)
+{
+ float s, c;
+#if 1
+ s = cachedSin;
+ c = cachedCos;
+#else
+ // Original code
+
+ float s, c;
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
+ s = 0.0f;
+ c = 1.0f;
+ }
+ else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
+ s = Sin(TheCamera.GetForward().Heading());
+ c = Cos(TheCamera.GetForward().Heading());
+ }
+ else {
+ CVector forward;
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
+ forward.Normalise(); // a bit useless...
+ }
+ else
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
+
+ s = Sin(forward.Heading());
+ c = Cos(forward.Heading());
+ }
+#endif
+
+ float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange);
+ float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange);
+
+ out.x = s * y + c * x;
+ out.y = c * y - s * x;
+}
+
+// Transform from section indices to world coordinates
+void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out)
+{
+ x = x - RADAR_NUM_TILES/2;
+ y = -(y - RADAR_NUM_TILES/2);
+
+ // bottom left
+ out[0].x = RADAR_TILE_SIZE * (x);
+ out[0].y = RADAR_TILE_SIZE * (y - 1);
+
+ // bottom right
+ out[1].x = RADAR_TILE_SIZE * (x + 1);
+ out[1].y = RADAR_TILE_SIZE * (y - 1);
+
+ // top right
+ out[2].x = RADAR_TILE_SIZE * (x + 1);
+ out[2].y = RADAR_TILE_SIZE * (y);
+
+ // top left
+ out[3].x = RADAR_TILE_SIZE * (x);
+ out[3].y = RADAR_TILE_SIZE * (y);
+}
+
+void CRadar::ClipRadarTileCoords(int32 &x, int32 &y)
+{
+ if (x < 0)
+ x = 0;
+ if (x > RADAR_NUM_TILES-1)
+ x = RADAR_NUM_TILES-1;
+ if (y < 0)
+ y = 0;
+ if (y > RADAR_NUM_TILES-1)
+ y = RADAR_NUM_TILES-1;
+}
+
+
+bool CRadar::IsPointInsideRadar(const CVector2D &point)
+{
+ if (point.x < -1.0f || point.x > 1.0f) return false;
+ if (point.y < -1.0f || point.y > 1.0f) return false;
+ return true;
+}
+
+// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1
+int CRadar::LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2)
+{
+ float d1, d2;
+ float t;
+ float x, y;
+ float shortest = 1.0f;
+ int edge = -1;
+
+ // clip against left edge, x = -1.0
+ d1 = -1.0f - p1.x;
+ d2 = -1.0f - p2.x;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ y = (p2.y - p1.y)*t + p1.y;
+ if (y >= -1.0f && y <= 1.0f && t <= shortest) {
+ out.x = -1.0f;
+ out.y = y;
+ edge = 3;
+ shortest = t;
+ }
+ }
+
+ // clip against right edge, x = 1.0
+ d1 = p1.x - 1.0f;
+ d2 = p2.x - 1.0f;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ y = (p2.y - p1.y)*t + p1.y;
+ if (y >= -1.0f && y <= 1.0f && t <= shortest) {
+ out.x = 1.0f;
+ out.y = y;
+ edge = 1;
+ shortest = t;
+ }
+ }
+
+ // clip against top edge, y = -1.0
+ d1 = -1.0f - p1.y;
+ d2 = -1.0f - p2.y;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ x = (p2.x - p1.x)*t + p1.x;
+ if (x >= -1.0f && x <= 1.0f && t <= shortest) {
+ out.y = -1.0f;
+ out.x = x;
+ edge = 0;
+ shortest = t;
+ }
+ }
+
+ // clip against bottom edge, y = 1.0
+ d1 = p1.y - 1.0f;
+ d2 = p2.y - 1.0f;
+ if (d1 * d2 < 0.0f) {
+ // they are on opposite sides, get point of intersection
+ t = d1 / (d1 - d2);
+ x = (p2.x - p1.x)*t + p1.x;
+ if (x >= -1.0f && x <= 1.0f && t <= shortest) {
+ out.y = 1.0f;
+ out.x = x;
+ edge = 2;
+ shortest = t;
+ }
+ }
+
+ return edge;
+}
+
+void
+CRadar::CalculateCachedSinCos()
+{
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED
+#ifdef MENU_MAP
+ || CMenuManager::bMenuMapActive
+#endif
+ ) {
+ cachedSin = 0.0f;
+ cachedCos = 1.0f;
+ } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
+ cachedSin = Sin(TheCamera.GetForward().Heading());
+ cachedCos = Cos(TheCamera.GetForward().Heading());
+ } else {
+ CVector forward;
+
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
+ forward.Normalise(); // a bit useless...
+ }
+ else
+ forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
+
+ cachedSin = Sin(forward.Heading());
+ cachedCos = Cos(forward.Heading());
+ }
+}
+
+#ifdef MENU_MAP
+void
+CRadar::InitFrontEndMap()
+{
+ CalculateCachedSinCos();
+ vec2DRadarOrigin.x = 0.0f;
+ vec2DRadarOrigin.y = 0.0f;
+ m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace
+ for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
+ MapLegendList[i] = RADAR_SPRITE_NONE;
+ }
+ MapLegendCounter = 0;
+ ArrowBlipColour1 = CRGBA(0, 0, 0, 0);
+ ArrowBlipColour2 = CRGBA(0, 0, 0, 0);
+}
+
+void
+CRadar::DrawYouAreHereSprite(float x, float y)
+{
+ static uint32 lastChange = 0;
+ static bool show = true;
+
+ if (show) {
+ if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 500) {
+ lastChange = CTimer::GetTimeInMillisecondsPauseMode();
+ show = !show;
+ }
+ } else {
+ if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 200) {
+ lastChange = CTimer::GetTimeInMillisecondsPauseMode();
+ show = !show;
+ }
+ }
+
+ if (show) {
+ float left = x - SCREEN_SCALE_X(12.0f);
+ float top = y - SCREEN_SCALE_Y(2.0f);
+ float right = SCREEN_SCALE_X(12.0) + x;
+ float bottom = y - SCREEN_SCALE_Y(26.0f);
+ CentreSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 217, 106, 255));
+ }
+ MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE;
+}
+
+void
+CRadar::ToggleTargetMarker(float x, float y)
+{
+ if (TargetMarkerId == -1) {
+ int nextBlip;
+ for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+ if (!ms_RadarTrace[nextBlip].m_bInUse)
+ break;
+ }
+ ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD;
+ ms_RadarTrace[nextBlip].m_nColor = 0x333333FF;
+ ms_RadarTrace[nextBlip].m_bDim = 1;
+ ms_RadarTrace[nextBlip].m_bInUse = 1;
+ ms_RadarTrace[nextBlip].m_Radius = 1.0f;
+ CVector pos(x, y, CWorld::FindGroundZForCoord(x,y));
+ ms_RadarTrace[nextBlip].m_vec2DPos = pos;
+ ms_RadarTrace[nextBlip].m_vecPos = pos;
+ ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
+ ms_RadarTrace[nextBlip].m_wScale = 5;
+ ms_RadarTrace[nextBlip].m_eBlipDisplay = BLIP_DISPLAY_BLIP_ONLY;
+ ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
+ TargetMarkerId = CRadar::GetNewUniqueBlipIndex(nextBlip);
+ } else {
+ ClearBlip(TargetMarkerId);
+ TargetMarkerId = -1;
}
-}
-
-void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in)
-{
- float s, c;
-#if 1
- s = cachedSin;
- c = cachedCos;
-#else
- // Original code
-
- float s, c;
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) {
- s = 0.0f;
- c = 1.0f;
- }
- else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
- s = Sin(TheCamera.GetForward().Heading());
- c = Cos(TheCamera.GetForward().Heading());
- }
- else {
- CVector forward;
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
- forward.Normalise(); // a bit useless...
- }
- else
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
-
- s = Sin(forward.Heading());
- c = Cos(forward.Heading());
- }
-#endif
-
- float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange);
- float y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange);
-
- out.x = s * y + c * x;
- out.y = c * y - s * x;
-}
-
-// Transform from section indices to world coordinates
-void CRadar::GetTextureCorners(int32 x, int32 y, CVector2D *out)
-{
- x = x - RADAR_NUM_TILES/2;
- y = -(y - RADAR_NUM_TILES/2);
-
- // bottom left
- out[0].x = RADAR_TILE_SIZE * (x);
- out[0].y = RADAR_TILE_SIZE * (y - 1);
-
- // bottom right
- out[1].x = RADAR_TILE_SIZE * (x + 1);
- out[1].y = RADAR_TILE_SIZE * (y - 1);
-
- // top right
- out[2].x = RADAR_TILE_SIZE * (x + 1);
- out[2].y = RADAR_TILE_SIZE * (y);
-
- // top left
- out[3].x = RADAR_TILE_SIZE * (x);
- out[3].y = RADAR_TILE_SIZE * (y);
-}
-
-void CRadar::ClipRadarTileCoords(int32 &x, int32 &y)
-{
- if (x < 0)
- x = 0;
- if (x > RADAR_NUM_TILES-1)
- x = RADAR_NUM_TILES-1;
- if (y < 0)
- y = 0;
- if (y > RADAR_NUM_TILES-1)
- y = RADAR_NUM_TILES-1;
-}
-
-
-bool CRadar::IsPointInsideRadar(const CVector2D &point)
-{
- if (point.x < -1.0f || point.x > 1.0f) return false;
- if (point.y < -1.0f || point.y > 1.0f) return false;
- return true;
-}
-
-// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1
-int CRadar::LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2)
-{
- float d1, d2;
- float t;
- float x, y;
- float shortest = 1.0f;
- int edge = -1;
-
- // clip against left edge, x = -1.0
- d1 = -1.0f - p1.x;
- d2 = -1.0f - p2.x;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- y = (p2.y - p1.y)*t + p1.y;
- if (y >= -1.0f && y <= 1.0f && t <= shortest) {
- out.x = -1.0f;
- out.y = y;
- edge = 3;
- shortest = t;
- }
- }
-
- // clip against right edge, x = 1.0
- d1 = p1.x - 1.0f;
- d2 = p2.x - 1.0f;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- y = (p2.y - p1.y)*t + p1.y;
- if (y >= -1.0f && y <= 1.0f && t <= shortest) {
- out.x = 1.0f;
- out.y = y;
- edge = 1;
- shortest = t;
- }
- }
-
- // clip against top edge, y = -1.0
- d1 = -1.0f - p1.y;
- d2 = -1.0f - p2.y;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- x = (p2.x - p1.x)*t + p1.x;
- if (x >= -1.0f && x <= 1.0f && t <= shortest) {
- out.y = -1.0f;
- out.x = x;
- edge = 0;
- shortest = t;
- }
- }
-
- // clip against bottom edge, y = 1.0
- d1 = p1.y - 1.0f;
- d2 = p2.y - 1.0f;
- if (d1 * d2 < 0.0f) {
- // they are on opposite sides, get point of intersection
- t = d1 / (d1 - d2);
- x = (p2.x - p1.x)*t + p1.x;
- if (x >= -1.0f && x <= 1.0f && t <= shortest) {
- out.y = 1.0f;
- out.x = x;
- edge = 2;
- shortest = t;
- }
- }
-
- return edge;
-}
-
-void
-CRadar::CalculateCachedSinCos()
-{
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED
-#ifdef MENU_MAP
- || CMenuManager::bMenuMapActive
-#endif
- ) {
- cachedSin = 0.0f;
- cachedCos = 1.0f;
- } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
- cachedSin = Sin(TheCamera.GetForward().Heading());
- cachedCos = Cos(TheCamera.GetForward().Heading());
- } else {
- CVector forward;
-
- if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();
- forward.Normalise(); // a bit useless...
- }
- else
- forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
-
- cachedSin = Sin(forward.Heading());
- cachedCos = Cos(forward.Heading());
- }
-}
-
-#ifdef MENU_MAP
-void
-CRadar::InitFrontEndMap()
-{
- CalculateCachedSinCos();
- vec2DRadarOrigin.x = 0.0f;
- vec2DRadarOrigin.y = 0.0f;
- m_radarRange = 1000.0f; // doesn't mean anything, just affects the calculation in TransformRadarPointToScreenSpace
- for (int i = 0; i < NUM_MAP_LEGENDS; i++) {
- MapLegendList[i] = RADAR_SPRITE_NONE;
- }
- MapLegendCounter = 0;
- ArrowBlipColour1 = CRGBA(0, 0, 0, 0);
- ArrowBlipColour2 = CRGBA(0, 0, 0, 0);
-}
-
-void
-CRadar::DrawYouAreHereSprite(float x, float y)
-{
- static uint32 lastChange = 0;
- static bool show = true;
-
- if (show) {
- if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 500) {
- lastChange = CTimer::GetTimeInMillisecondsPauseMode();
- show = !show;
- }
- } else {
- if (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 200) {
- lastChange = CTimer::GetTimeInMillisecondsPauseMode();
- show = !show;
- }
- }
-
- if (show) {
- float left = x - SCREEN_SCALE_X(12.0f);
- float top = y - SCREEN_SCALE_Y(2.0f);
- float right = SCREEN_SCALE_X(12.0) + x;
- float bottom = y - SCREEN_SCALE_Y(26.0f);
- CentreSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 217, 106, 255));
- }
- MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE;
-}
-
-void
-CRadar::ToggleTargetMarker(float x, float y)
-{
- if (TargetMarkerId == -1) {
- int nextBlip;
- for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
- if (!ms_RadarTrace[nextBlip].m_bInUse)
- break;
- }
- ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD;
- ms_RadarTrace[nextBlip].m_nColor = 0x333333FF;
- ms_RadarTrace[nextBlip].m_bDim = 1;
- ms_RadarTrace[nextBlip].m_bInUse = 1;
- ms_RadarTrace[nextBlip].m_Radius = 1.0f;
- CVector pos(x, y, CWorld::FindGroundZForCoord(x,y));
- ms_RadarTrace[nextBlip].m_vec2DPos = pos;
- ms_RadarTrace[nextBlip].m_vecPos = pos;
- ms_RadarTrace[nextBlip].m_nEntityHandle = 0;
- ms_RadarTrace[nextBlip].m_wScale = 5;
- ms_RadarTrace[nextBlip].m_eBlipDisplay = BLIP_DISPLAY_BLIP_ONLY;
- ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;
- TargetMarkerId = CRadar::GetNewUniqueBlipIndex(nextBlip);
- } else {
- ClearBlip(TargetMarkerId);
- TargetMarkerId = -1;
- }
-}
-#endif
-
-STARTPATCHES
- InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP);
- InjectHook(0x4A3F60, CRadar::Shutdown, PATCH_JUMP);
- InjectHook(0x4A4030, CRadar::LoadTextures, PATCH_JUMP);
- InjectHook(0x4A4180, CRadar::GetNewUniqueBlipIndex, PATCH_JUMP);
- InjectHook(0x4A41C0, CRadar::GetActualBlipArrayIndex, PATCH_JUMP);
- InjectHook(0x4A4200, CRadar::DrawMap, PATCH_JUMP);
- InjectHook(0x4A42F0, CRadar::DrawBlips, PATCH_JUMP);
- InjectHook(0x4A4C70, CRadar::Draw3dMarkers, PATCH_JUMP);
- InjectHook(0x4A4F30, CRadar::LimitRadarPoint, PATCH_JUMP);
- InjectHook(0x4A4F90, CRadar::CalculateBlipAlpha, PATCH_JUMP);
- InjectHook(0x4A5040, CRadar::TransformRadarPointToScreenSpace, PATCH_JUMP);
- InjectHook(0x4A50D0, CRadar::TransformRealWorldPointToRadarSpace, PATCH_JUMP);
- InjectHook(0x4A5300, CRadar::TransformRadarPointToRealWorldSpace, PATCH_JUMP);
- InjectHook(0x4A5530, CRadar::TransformRealWorldToTexCoordSpace, PATCH_JUMP);
- InjectHook(0x4A5590, CRadar::SetCoordBlip, PATCH_JUMP);
- InjectHook(0x4A5640, CRadar::SetEntityBlip, PATCH_JUMP);
- InjectHook(0x4A56C0, CRadar::ClearBlipForEntity, PATCH_JUMP);
- InjectHook(0x4A5720, CRadar::ClearBlip, PATCH_JUMP);
- InjectHook(0x4A5770, CRadar::ChangeBlipColour, PATCH_JUMP);
- InjectHook(0x4A57A0, CRadar::ChangeBlipBrightness, PATCH_JUMP);
- InjectHook(0x4A57E0, CRadar::ChangeBlipScale, PATCH_JUMP);
- InjectHook(0x4A5810, CRadar::ChangeBlipDisplay, PATCH_JUMP);
- InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP);
- InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP);
- InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP);
- InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP);
- InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP);
- InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP);
- InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP);
- InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP);
- InjectHook(0x4A6100, (void (*)(int32, int32))&CRadar::StreamRadarSections, PATCH_JUMP);
- InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP);
- InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP);
- InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP);
- InjectHook(0x4A6B60, (void (*)(const CVector&))&CRadar::StreamRadarSections, PATCH_JUMP);
- InjectHook(0x4A6C20, CRadar::DrawRadarMap, PATCH_JUMP);
- InjectHook(0x4A6E30, CRadar::SaveAllRadarBlips, PATCH_JUMP);
- InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP);
-
- InjectHook(0x4A61C0, CRadar::GetTextureCorners, PATCH_JUMP);
- InjectHook(0x4A6160, CRadar::IsPointInsideRadar, PATCH_JUMP);
- InjectHook(0x4A6250, CRadar::LineRadarBoxCollision, PATCH_JUMP);
-ENDPATCHES
+}
+#endif
+
+STARTPATCHES
+ InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP);
+ InjectHook(0x4A3F60, CRadar::Shutdown, PATCH_JUMP);
+ InjectHook(0x4A4030, CRadar::LoadTextures, PATCH_JUMP);
+ InjectHook(0x4A4180, CRadar::GetNewUniqueBlipIndex, PATCH_JUMP);
+ InjectHook(0x4A41C0, CRadar::GetActualBlipArrayIndex, PATCH_JUMP);
+ InjectHook(0x4A4200, CRadar::DrawMap, PATCH_JUMP);
+ InjectHook(0x4A42F0, CRadar::DrawBlips, PATCH_JUMP);
+ InjectHook(0x4A4C70, CRadar::Draw3dMarkers, PATCH_JUMP);
+ InjectHook(0x4A4F30, CRadar::LimitRadarPoint, PATCH_JUMP);
+ InjectHook(0x4A4F90, CRadar::CalculateBlipAlpha, PATCH_JUMP);
+ InjectHook(0x4A5040, CRadar::TransformRadarPointToScreenSpace, PATCH_JUMP);
+ InjectHook(0x4A50D0, CRadar::TransformRealWorldPointToRadarSpace, PATCH_JUMP);
+ InjectHook(0x4A5300, CRadar::TransformRadarPointToRealWorldSpace, PATCH_JUMP);
+ InjectHook(0x4A5530, CRadar::TransformRealWorldToTexCoordSpace, PATCH_JUMP);
+ InjectHook(0x4A5590, CRadar::SetCoordBlip, PATCH_JUMP);
+ InjectHook(0x4A5640, CRadar::SetEntityBlip, PATCH_JUMP);
+ InjectHook(0x4A56C0, CRadar::ClearBlipForEntity, PATCH_JUMP);
+ InjectHook(0x4A5720, CRadar::ClearBlip, PATCH_JUMP);
+ InjectHook(0x4A5770, CRadar::ChangeBlipColour, PATCH_JUMP);
+ InjectHook(0x4A57A0, CRadar::ChangeBlipBrightness, PATCH_JUMP);
+ InjectHook(0x4A57E0, CRadar::ChangeBlipScale, PATCH_JUMP);
+ InjectHook(0x4A5810, CRadar::ChangeBlipDisplay, PATCH_JUMP);
+ InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP);
+ InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP);
+ InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP);
+ InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP);
+ InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP);
+ InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP);
+ InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP);
+ InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP);
+ InjectHook(0x4A6100, (void (*)(int32, int32))&CRadar::StreamRadarSections, PATCH_JUMP);
+ InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP);
+ InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP);
+ InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP);
+ InjectHook(0x4A6B60, (void (*)(const CVector&))&CRadar::StreamRadarSections, PATCH_JUMP);
+ InjectHook(0x4A6C20, CRadar::DrawRadarMap, PATCH_JUMP);
+ InjectHook(0x4A6E30, CRadar::SaveAllRadarBlips, PATCH_JUMP);
+ InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP);
+
+ InjectHook(0x4A61C0, CRadar::GetTextureCorners, PATCH_JUMP);
+ InjectHook(0x4A6160, CRadar::IsPointInsideRadar, PATCH_JUMP);
+ InjectHook(0x4A6250, CRadar::LineRadarBoxCollision, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index aeb7afe5..02092a30 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -1,14 +1,14 @@
#include "common.h"
#include "patcher.h"
#include "Stats.h"
-
-WRAPPER void CStats::SaveStats(uint8 *buf, uint32 *size) { EAXJMP(0x4ab3e0); }
+#include "Text.h"
+#include "World.h"
int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
int32 &CStats::HeadsPopped = *(int32*)0x8F647C;
-bool& CStats::CommercialPassed = *(bool*)0x8F4334;
-bool& CStats::IndustrialPassed = *(bool*)0x8E2A68;
-bool& CStats::SuburbanPassed = *(bool*)0x8F2740;
+int32& CStats::CommercialPassed = *(int32*)0x8F4334;
+int32& CStats::IndustrialPassed = *(int32*)0x8E2A68;
+int32& CStats::SuburbanPassed = *(int32*)0x8F2740;
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64;
@@ -48,7 +48,7 @@ int32& CStats::LongestFlightInDodo = *(int32*)0x8F5FE4;
int32& CStats::TimeTakenDefuseMission = *(int32*)0x880E24;
int32& CStats::TotalNumberKillFrenzies = *(int32*)0x8E2884;
int32& CStats::TotalNumberMissions = *(int32*)0x8E2820;
-int32& CStats::ShotsMade = *(int32*)0x8E2BE8;
+int32& CStats::RoundsFiredByPlayer = *(int32*)0x8E2BE8;
int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510;
int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070;
int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C;
@@ -62,7 +62,7 @@ void CStats::Init()
{
PeopleKilledByOthers = 0;
PeopleKilledByPlayer = 0;
- ShotsMade = 0;
+ RoundsFiredByPlayer = 0;
CarsExploded = 0;
HelisDestroyed = 0;
ProgressMade = 0;
@@ -200,6 +200,229 @@ void CStats::SetTotalNumberMissions(int32 total)
TotalNumberMissions = total;
}
+wchar *CStats::FindCriminalRatingString()
+{
+ int rating = FindCriminalRatingNumber();
+
+ if (rating < 10) return TheText.Get("RATNG1");
+ if (rating < 25) return TheText.Get("RATNG2");
+ if (rating < 70) return TheText.Get("RATNG3");
+ if (rating < 150) return TheText.Get("RATNG4");
+ if (rating < 250) return TheText.Get("RATNG5");
+ if (rating < 450) return TheText.Get("RATNG6");
+ if (rating < 700) return TheText.Get("RATNG7");
+ if (rating < 1000) return TheText.Get("RATNG8");
+ if (rating < 1400) return TheText.Get("RATNG9");
+ if (rating < 1900) return TheText.Get("RATNG10");
+ if (rating < 2500) return TheText.Get("RATNG11");
+ if (rating < 3200) return TheText.Get("RATNG12");
+ if (rating < 4000) return TheText.Get("RATNG13");
+ if (rating < 5000) return TheText.Get("RATNG14");
+ return TheText.Get("RATNG15");
+}
+
+int32 CStats::FindCriminalRatingNumber()
+{
+ int32 rating;
+
+ rating = FiresExtinguished + 10 * HighestLevelAmbulanceMission + CriminalsCaught + LivesSavedWithAmbulance
+ + 30 * HelisDestroyed + TotalLegitimateKills - 3 * TimesArrested - 3 * TimesDied
+ + CWorld::Players[CWorld::PlayerInFocus].m_nMoney / 5000;
+ if (rating <= 0) rating = 0;
+
+ if (InstantHitsFiredByPlayer > 100)
+ rating += (float)CStats::InstantHitsHitByPlayer / (float)CStats::InstantHitsFiredByPlayer * 500.0f;
+ if (TotalProgressInGame)
+ rating += (float)CStats::ProgressMade / (float)CStats::TotalProgressInGame * 1000.0f;
+ if (!IndustrialPassed && rating >= 3521)
+ rating = 3521;
+ if (!CommercialPassed && rating >= 4552)
+ rating = 4552;
+ return rating;
+}
+
+void CStats::SaveStats(uint8 *buf, uint32 *size)
+{
+ CheckPointReachedSuccessfully();
+ uint8 *buf_start = buf;
+ *size = sizeof(PeopleKilledByPlayer) +
+ sizeof(PeopleKilledByOthers) +
+ sizeof(CarsExploded) +
+ sizeof(RoundsFiredByPlayer) +
+ sizeof(PedsKilledOfThisType) +
+ sizeof(HelisDestroyed) +
+ sizeof(ProgressMade) +
+ sizeof(TotalProgressInGame) +
+ sizeof(KgsOfExplosivesUsed) +
+ sizeof(InstantHitsFiredByPlayer) +
+ sizeof(InstantHitsHitByPlayer) +
+ sizeof(CarsCrushed) +
+ sizeof(HeadsPopped) +
+ sizeof(TimesArrested) +
+ sizeof(TimesDied) +
+ sizeof(DaysPassed) +
+ sizeof(mmRain) +
+ sizeof(MaximumJumpDistance) +
+ sizeof(MaximumJumpHeight) +
+ sizeof(MaximumJumpFlips) +
+ sizeof(MaximumJumpSpins) +
+ sizeof(BestStuntJump) +
+ sizeof(NumberOfUniqueJumpsFound) +
+ sizeof(TotalNumberOfUniqueJumps) +
+ sizeof(MissionsGiven) +
+ sizeof(MissionsPassed) +
+ sizeof(PassengersDroppedOffWithTaxi) +
+ sizeof(MoneyMadeWithTaxi) +
+ sizeof(IndustrialPassed) +
+ sizeof(CommercialPassed) +
+ sizeof(SuburbanPassed) +
+ sizeof(ElBurroTime) +
+ sizeof(DistanceTravelledOnFoot) +
+ sizeof(DistanceTravelledInVehicle) +
+ sizeof(Record4x4One) +
+ sizeof(Record4x4Two) +
+ sizeof(Record4x4Three) +
+ sizeof(Record4x4Mayhem) +
+ sizeof(LivesSavedWithAmbulance) +
+ sizeof(CriminalsCaught) +
+ sizeof(HighestLevelAmbulanceMission) +
+ sizeof(FiresExtinguished) +
+ sizeof(LongestFlightInDodo) +
+ sizeof(TimeTakenDefuseMission) +
+ sizeof(NumberKillFrenziesPassed) +
+ sizeof(TotalNumberKillFrenzies) +
+ sizeof(TotalNumberMissions) +
+ sizeof(FastestTimes) +
+ sizeof(HighestScores) +
+ sizeof(KillsSinceLastCheckpoint) +
+ sizeof(TotalLegitimateKills) +
+ sizeof(LastMissionPassedName);
+
+#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data);
+ CopyToBuf(buf, PeopleKilledByPlayer);
+ CopyToBuf(buf, PeopleKilledByOthers);
+ CopyToBuf(buf, CarsExploded);
+ CopyToBuf(buf, RoundsFiredByPlayer);
+ CopyToBuf(buf, PedsKilledOfThisType);
+ CopyToBuf(buf, HelisDestroyed);
+ CopyToBuf(buf, ProgressMade);
+ CopyToBuf(buf, TotalProgressInGame);
+ CopyToBuf(buf, KgsOfExplosivesUsed);
+ CopyToBuf(buf, InstantHitsFiredByPlayer);
+ CopyToBuf(buf, InstantHitsHitByPlayer);
+ CopyToBuf(buf, CarsCrushed);
+ CopyToBuf(buf, HeadsPopped);
+ CopyToBuf(buf, TimesArrested);
+ CopyToBuf(buf, TimesDied);
+ CopyToBuf(buf, DaysPassed);
+ CopyToBuf(buf, mmRain);
+ CopyToBuf(buf, MaximumJumpDistance);
+ CopyToBuf(buf, MaximumJumpHeight);
+ CopyToBuf(buf, MaximumJumpFlips);
+ CopyToBuf(buf, MaximumJumpSpins);
+ CopyToBuf(buf, BestStuntJump);
+ CopyToBuf(buf, NumberOfUniqueJumpsFound);
+ CopyToBuf(buf, TotalNumberOfUniqueJumps);
+ CopyToBuf(buf, MissionsGiven);
+ CopyToBuf(buf, MissionsPassed);
+ CopyToBuf(buf, PassengersDroppedOffWithTaxi);
+ CopyToBuf(buf, MoneyMadeWithTaxi);
+ CopyToBuf(buf, IndustrialPassed);
+ CopyToBuf(buf, CommercialPassed);
+ CopyToBuf(buf, SuburbanPassed);
+ CopyToBuf(buf, ElBurroTime);
+ CopyToBuf(buf, DistanceTravelledOnFoot);
+ CopyToBuf(buf, DistanceTravelledInVehicle);
+ CopyToBuf(buf, Record4x4One);
+ CopyToBuf(buf, Record4x4Two);
+ CopyToBuf(buf, Record4x4Three);
+ CopyToBuf(buf, Record4x4Mayhem);
+ CopyToBuf(buf, LivesSavedWithAmbulance);
+ CopyToBuf(buf, CriminalsCaught);
+ CopyToBuf(buf, HighestLevelAmbulanceMission);
+ CopyToBuf(buf, FiresExtinguished);
+ CopyToBuf(buf, LongestFlightInDodo);
+ CopyToBuf(buf, TimeTakenDefuseMission);
+ CopyToBuf(buf, NumberKillFrenziesPassed);
+ CopyToBuf(buf, TotalNumberKillFrenzies);
+ CopyToBuf(buf, TotalNumberMissions);
+ CopyToBuf(buf, FastestTimes);
+ CopyToBuf(buf, HighestScores);
+ CopyToBuf(buf, KillsSinceLastCheckpoint);
+ CopyToBuf(buf, TotalLegitimateKills);
+ CopyToBuf(buf, LastMissionPassedName);
+
+ assert(buf - buf_start == *size);
+#undef CopyToBuf
+}
+
+void CStats::LoadStats(uint8 *buf, uint32 size)
+{
+ uint8* buf_start = buf;
+
+#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data);
+
+ CopyFromBuf(buf, PeopleKilledByPlayer);
+ CopyFromBuf(buf, PeopleKilledByOthers);
+ CopyFromBuf(buf, CarsExploded);
+ CopyFromBuf(buf, RoundsFiredByPlayer);
+ CopyFromBuf(buf, PedsKilledOfThisType);
+ CopyFromBuf(buf, HelisDestroyed);
+ CopyFromBuf(buf, ProgressMade);
+ CopyFromBuf(buf, TotalProgressInGame);
+ CopyFromBuf(buf, KgsOfExplosivesUsed);
+ CopyFromBuf(buf, InstantHitsFiredByPlayer);
+ CopyFromBuf(buf, InstantHitsHitByPlayer);
+ CopyFromBuf(buf, CarsCrushed);
+ CopyFromBuf(buf, HeadsPopped);
+ CopyFromBuf(buf, TimesArrested);
+ CopyFromBuf(buf, TimesDied);
+ CopyFromBuf(buf, DaysPassed);
+ CopyFromBuf(buf, mmRain);
+ CopyFromBuf(buf, MaximumJumpDistance);
+ CopyFromBuf(buf, MaximumJumpHeight);
+ CopyFromBuf(buf, MaximumJumpFlips);
+ CopyFromBuf(buf, MaximumJumpSpins);
+ CopyFromBuf(buf, BestStuntJump);
+ CopyFromBuf(buf, NumberOfUniqueJumpsFound);
+ CopyFromBuf(buf, TotalNumberOfUniqueJumps);
+ CopyFromBuf(buf, MissionsGiven);
+ CopyFromBuf(buf, MissionsPassed);
+ CopyFromBuf(buf, PassengersDroppedOffWithTaxi);
+ CopyFromBuf(buf, MoneyMadeWithTaxi);
+ CopyFromBuf(buf, IndustrialPassed);
+ CopyFromBuf(buf, CommercialPassed);
+ CopyFromBuf(buf, SuburbanPassed);
+ CopyFromBuf(buf, ElBurroTime);
+ CopyFromBuf(buf, DistanceTravelledOnFoot);
+ CopyFromBuf(buf, DistanceTravelledInVehicle);
+ CopyFromBuf(buf, Record4x4One);
+ CopyFromBuf(buf, Record4x4Two);
+ CopyFromBuf(buf, Record4x4Three);
+ CopyFromBuf(buf, Record4x4Mayhem);
+ CopyFromBuf(buf, LivesSavedWithAmbulance);
+ CopyFromBuf(buf, CriminalsCaught);
+ CopyFromBuf(buf, HighestLevelAmbulanceMission);
+ CopyFromBuf(buf, FiresExtinguished);
+ CopyFromBuf(buf, LongestFlightInDodo);
+ CopyFromBuf(buf, TimeTakenDefuseMission);
+ CopyFromBuf(buf, NumberKillFrenziesPassed);
+ CopyFromBuf(buf, TotalNumberKillFrenzies);
+ CopyFromBuf(buf, TotalNumberMissions);
+ CopyFromBuf(buf, FastestTimes);
+ CopyFromBuf(buf, HighestScores);
+ CopyFromBuf(buf, KillsSinceLastCheckpoint);
+ CopyFromBuf(buf, TotalLegitimateKills);
+ CopyFromBuf(buf, LastMissionPassedName);
+
+ assert(buf - buf_start == size);
+#undef CopyFromBuf
+}
+
STARTPATCHES
InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables
+ InjectHook(0x4AB3E0, CStats::SaveStats, PATCH_JUMP);
+ InjectHook(0x4AB670, CStats::LoadStats, PATCH_JUMP);
+ InjectHook(0x4AB090, CStats::FindCriminalRatingString, PATCH_JUMP);
+ InjectHook(0x4AB2A0, CStats::FindCriminalRatingNumber, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 029b2307..ac3259f9 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -11,9 +11,9 @@ public:
};
static int32 &DaysPassed;
static int32 &HeadsPopped;
- static bool& CommercialPassed;
- static bool& IndustrialPassed;
- static bool& SuburbanPassed;
+ static int32& CommercialPassed;
+ static int32& IndustrialPassed;
+ static int32& SuburbanPassed;
static int32 &NumberKillFrenziesPassed;
static int32 &PeopleKilledByOthers;
static int32 &HelisDestroyed;
@@ -53,7 +53,7 @@ public:
static int32 &TimeTakenDefuseMission;
static int32 &TotalNumberKillFrenzies;
static int32 &TotalNumberMissions;
- static int32 &ShotsMade;
+ static int32 &RoundsFiredByPlayer;
static int32 &KgsOfExplosivesUsed;
static int32 &InstantHitsFiredByPlayer;
static int32 &InstantHitsHitByPlayer;
@@ -64,24 +64,27 @@ public:
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
public:
+ static void Init(void);
static void RegisterFastestTime(int32, int32);
static void RegisterHighestScore(int32, int32);
- static void AnotherKillFrenzyPassed();
- static void AnotherLifeSavedWithAmbulance();
- static void AnotherCriminalCaught();
- static void RegisterLevelAmbulanceMission(int32);
- static void AnotherFireExtinguished();
+ static void RegisterElBurroTime(int32);
static void Register4x4OneTime(int32);
static void Register4x4TwoTime(int32);
static void Register4x4ThreeTime(int32);
static void Register4x4MayhemTime(int32);
+ static void AnotherLifeSavedWithAmbulance();
+ static void AnotherCriminalCaught();
+ static void RegisterLevelAmbulanceMission(int32);
+ static void AnotherFireExtinguished();
+ static wchar *FindCriminalRatingString();
static void RegisterLongestFlightInDodo(int32);
static void RegisterTimeTakenDefuseMission(int32);
+ static void AnotherKillFrenzyPassed();
static void SetTotalNumberKillFrenzies(int32);
static void SetTotalNumberMissions(int32);
- static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };
static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };
- static void RegisterElBurroTime(int32);
+ static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };
+ static int32 FindCriminalRatingNumber();
static void SaveStats(uint8 *buf, uint32 *size);
- static void Init(void);
+ static void LoadStats(uint8 *buf, uint32 size);
};
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 4a0230ce..d64569b3 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -56,6 +56,8 @@ WRAPPER void CWorld::FindMissionEntitiesIntersectingCube(const CVector&, const C
WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); }
WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); }
WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); }
+WRAPPER void CWorld::TriggerExplosion(const CVector& a1, float a2, float a3, CEntity *a4, bool a5) { EAXJMP(0x4B1140); }
+WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); }
void
CWorld::Initialise()
diff --git a/src/core/World.h b/src/core/World.h
index c4103eb2..07e7889f 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -132,6 +132,7 @@ public:
static void SetAllCarsCanBeDamaged(bool);
static void ExtinguishAllCarFiresInArea(CVector, float);
static void SetCarsOnFire(float, float, float, float, CEntity*);
+ static void SetPedsOnFire(float, float, float, float, CEntity*);
static void Initialise();
static void AddParticles();
@@ -140,6 +141,7 @@ public:
static void RepositionCertainDynamicObjects();
static void RemoveStaticObjects();
static void Process();
+ static void TriggerExplosion(const CVector &, float, float, CEntity*, bool);
};
extern CColPoint *gaTempSphereColPoints;
diff --git a/src/core/config.h b/src/core/config.h
index f653f724..198ee946 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -79,6 +79,7 @@ enum Config {
NUMPICKUPMESSAGES = 16,
NUMBULLETTRACES = 16,
NUMMBLURSTREAKS = 4,
+ NUMSKIDMARKS = 32,
NUMONSCREENTIMERENTRIES = 1,
NUMRADARBLIPS = 32,
@@ -125,7 +126,9 @@ enum Config {
NUM_GARAGE_STORED_CARS = 6,
- NUM_CRANES = 8
+ NUM_CRANES = 8,
+
+ NUM_EXPLOSIONS = 48,
};
// We'll use this once we're ready to become independent of the game
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 6d4ff252..6eae8685 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -458,7 +458,7 @@ void re3_debug(const char *format, ...)
vsprintf_s(re3_buff, re3_buffsize, format, va);
va_end(va);
-// printf("%s", re3_buff);
+ printf("%s", re3_buff);
CDebug::DebugAddText(re3_buff);
}
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 7a050818..07d70394 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -275,9 +275,9 @@ CEntity::CreateRwObject(void)
if(IsBuilding())
gBuildings++;
if(RwObjectGetType(m_rwObject) == rpATOMIC)
- m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(m_rwObject)), false);
+ m_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
- m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame(m_rwObject)), false);
+ m_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
mi->AddRef();
}
}
@@ -290,7 +290,7 @@ CEntity::DeleteRwObject(void)
m_matrix.Detach();
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC){
- f = RpAtomicGetFrame(m_rwObject);
+ f = RpAtomicGetFrame((RpAtomic*)m_rwObject);
RpAtomicDestroy((RpAtomic*)m_rwObject);
RwFrameDestroy(f);
}else if(RwObjectGetType(m_rwObject) == rpCLUMP)
@@ -307,9 +307,9 @@ CEntity::UpdateRwFrame(void)
{
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC)
- RwFrameUpdateObjects(RpAtomicGetFrame(m_rwObject));
+ RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
- RwFrameUpdateObjects(RpClumpGetFrame(m_rwObject));
+ RwFrameUpdateObjects(RpClumpGetFrame((RpClump*)m_rwObject));
}
}
@@ -482,9 +482,9 @@ CEntity::AttachToRwObject(RwObject *obj)
m_rwObject = obj;
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC)
- m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame(m_rwObject)), false);
+ m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
- m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame(m_rwObject)), false);
+ m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
}
}
diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp
index 7b087fbd..015c6949 100644
--- a/src/modelinfo/PedModelInfo.cpp
+++ b/src/modelinfo/PedModelInfo.cpp
@@ -216,7 +216,7 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame)
RwMatrixCopy(mat, RwFrameGetMatrix(f));
for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) {
- RwMatrixTransform(mat, &f->modelling, rwCOMBINEPOSTCONCAT);
+ RwMatrixTransform(mat, RwFrameGetMatrix(f), rwCOMBINEPOSTCONCAT);
if (RwFrameGetParent(f) == frame)
break;
}
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index 42ad635b..432a9ea2 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -707,7 +707,7 @@ RpMaterial*
CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data)
{
static RwRGBA white = { 255, 255, 255, 255 };
- RwRGBA *col;
+ const RwRGBA *col;
editableMatCBData *cbdata;
cbdata = (editableMatCBData*)data;
@@ -758,8 +758,8 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
col = ms_vehicleColourTable[c1];
coltex = ms_colourTextureTable[c1];
for(matp = m_materials1; *matp; matp++){
- if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){
- colp = RpMaterialGetColor(*matp);
+ if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
+ colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
colp->red = col.red;
colp->green = col.green;
colp->blue = col.blue;
@@ -773,8 +773,8 @@ CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
col = ms_vehicleColourTable[c2];
coltex = ms_colourTextureTable[c2];
for(matp = m_materials2; *matp; matp++){
- if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){
- colp = RpMaterialGetColor(*matp);
+ if(RpMaterialGetTexture(*matp) && RwTextureGetName(RpMaterialGetTexture(*matp))[0] != '@'){
+ colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const
colp->red = col.red;
colp->green = col.green;
colp->blue = col.blue;
@@ -861,7 +861,7 @@ CreateCarColourTexture(uint8 r, uint8 g, uint8 b)
RwImageDestroy(img);
RwFree(pixels);
tex = RwTextureCreate(ras);
- tex->name[0] = '@';
+ RwTextureGetName(tex)[0] = '@';
return tex;
}
@@ -1058,7 +1058,7 @@ CVehicleModelInfo::LoadEnvironmentMaps(void)
}
if(gpWhiteTexture == nil){
gpWhiteTexture = RwTextureRead("white", nil);
- gpWhiteTexture->name[0] = '@';
+ RwTextureGetName(gpWhiteTexture)[0] = '@';
RwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR);
}
CTxdStore::PopCurrentTxd();
diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp
index 8c417973..a7722b8a 100644
--- a/src/objects/CutsceneHead.cpp
+++ b/src/objects/CutsceneHead.cpp
@@ -20,7 +20,7 @@ CCutsceneHead::CCutsceneHead(CObject *obj)
m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame;
atm = (RpAtomic*)GetFirstObject(m_pHeadNode);
if(atm){
- assert(RwObjectGetType(atm) == rpATOMIC);
+ assert(RwObjectGetType((RwObject*)atm) == rpATOMIC);
RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER);
}
}
diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp
index 881510e8..9f7bcda5 100644
--- a/src/objects/ParticleObject.cpp
+++ b/src/objects/ParticleObject.cpp
@@ -154,7 +154,7 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe
pobj->m_nRemoveTimer = 0;
if ( color.alpha != 0 )
- RwRGBAAssign(&pobj->m_Color, &color);
+ pobj->m_Color, color;
else
pobj->m_Color.alpha = 0;
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 54816b1c..2cd942f9 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -676,7 +676,7 @@ RemoveAllModelCB(RwObject *object, void *data)
{
RpAtomic *atomic = (RpAtomic*)object;
if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
- RpClumpRemoveAtomic(atomic->clump, atomic);
+ RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
RpAtomicDestroy(atomic);
}
return object;
@@ -902,7 +902,7 @@ static RwObject*
SetPedAtomicVisibilityCB(RwObject* object, void* data)
{
if (data == nil)
- RpAtomicSetFlags(object, 0);
+ RpAtomicSetFlags((RpAtomic*)object, 0);
return object;
}
diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp
index cc4b0dd0..8e450ee6 100644
--- a/src/peds/PedIK.cpp
+++ b/src/peds/PedIK.cpp
@@ -340,7 +340,7 @@ CPedIK::RestoreLookAt(void)
}
void
-CPedIK::ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch)
+CPedIK::ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch)
{
float f = clamp(DotProduct(mat->up, CVector(0.0f, 1.0f, 0.0f)), -1.0f, 1.0f);
*yaw = Acos(f);
@@ -352,7 +352,7 @@ CPedIK::ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch)
}
void
-CPedIK::ExtractYawAndPitchLocal(RwMatrixTag *mat, float *yaw, float *pitch)
+CPedIK::ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch)
{
float f = clamp(DotProduct(mat->at, CVector(0.0f, 0.0f, 1.0f)), -1.0f, 1.0f);
*yaw = Acos(f);
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index df9017f3..7b82d1ac 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -54,8 +54,8 @@ public:
void GetComponentPosition(RwV3d *pos, uint32 node);
static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination);
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
- void ExtractYawAndPitchLocal(RwMatrixTag *mat, float *yaw, float *pitch);
- void ExtractYawAndPitchWorld(RwMatrixTag *mat, float *yaw, float *pitch);
+ void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch);
+ void ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch);
LimbMoveStatus MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo);
bool RestoreGunPosn(void);
bool LookInDirection(float phi, float theta);
diff --git a/src/peds/PedType.h b/src/peds/PedType.h
index 1f3ecb59..3d927df5 100644
--- a/src/peds/PedType.h
+++ b/src/peds/PedType.h
@@ -85,6 +85,7 @@ public:
static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; }
static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; }
static uint32 GetThreats(int type) { return ms_apPedType[type]->m_threats; }
+ static void SetThreats(int type, uint32 threat) { ms_apPedType[type]->m_threats = threat; }
static void AddThreat(int type, int threat) { ms_apPedType[type]->m_threats |= threat; }
static void RemoveThreat(int type, int threat) { ms_apPedType[type]->m_threats &= ~threat; }
static bool IsThreat(int type, int threat) { return ms_apPedType[type]->m_threats & threat; }
diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp
index 2884894c..39866294 100644
--- a/src/render/Clouds.cpp
+++ b/src/render/Clouds.cpp
@@ -87,7 +87,7 @@ CClouds::Render(void)
RwV3d pos = { 0.0f, -100.0f, 15.0f };
RwV3dAdd(&worldpos, &campos, &pos);
if(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[2]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2]));
if(CCoronas::bSmallMoon){
szx *= 4.0f;
szy *= 4.0f;
@@ -116,7 +116,7 @@ CClouds::Render(void)
static float StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f };
static float StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f };
int brightness = (1.0f - coverage) * starintens;
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 11; i++){
RwV3d pos = { 100.0f, 0.0f, 10.0f };
if(i >= 9) pos.x = -pos.x;
@@ -132,7 +132,7 @@ CClouds::Render(void)
CSprite::FlushSpriteBuffer();
// *
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
RwV3d pos = { 100.0f, 0.0f, 10.0f };
RwV3dAdd(&worldpos, &campos, &pos);
worldpos.y -= 90.0f;
@@ -156,7 +156,7 @@ CClouds::Render(void)
int b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity;
for(int cloudtype = 0; cloudtype < 3; cloudtype++){
for(i = cloudtype; i < 12; i += 3){
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[cloudtype]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[cloudtype]));
RwV3d pos = { 800.0f*LowCloudsX[i], 800.0f*LowCloudsY[i], 60.0f*LowCloudsZ[i] };
worldpos.x = campos.x + pos.x;
worldpos.y = campos.y + pos.y;
@@ -202,7 +202,7 @@ CClouds::Render(void)
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[4]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[4]));
for(i = 0; i < 37; i++){
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
worldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x;
@@ -244,7 +244,7 @@ CClouds::Render(void)
// Highlights
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCloudTex[3]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[3]));
for(i = 0; i < 37; i++){
RwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };
@@ -269,7 +269,7 @@ CClouds::Render(void)
static uint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 };
static uint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 };
static uint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 };
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCoronaTexture[0]->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));
for(i = 0; i < 6; i++){
RwV3d pos = { i*1.5f, 100.0f, 5.0f };
RwV3dAdd(&worldpos, &campos, &pos);
diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp
index 8d7fad92..e2899532 100644
--- a/src/render/Fluff.cpp
+++ b/src/render/Fluff.cpp
@@ -755,14 +755,14 @@ void CTowerClock::Render()
&TempV[1],
m_Position.x + Sin(angleMinute) * m_fScale * m_Size.x,
m_Position.y + Sin(angleMinute) * m_fScale * m_Size.y,
- m_Position.z + Cos(angleMinute) * m_fScale;
+ m_Position.z + Cos(angleMinute) * m_fScale
);
RwIm3DVertexSetPos(&TempV[2], m_Position.x, m_Position.y, m_Position.z);
RwIm3DVertexSetPos(
&TempV[3],
m_Position.x + Sin(angleHour) * 0.75f * m_fScale * m_Size.x,
m_Position.y + Sin(angleHour) * 0.75f * m_fScale * m_Size.y,
- m_Position.z + Cos(angleHour) * 0.75f * m_fScale;
+ m_Position.z + Cos(angleHour) * 0.75f * m_fScale
);
LittleTest();
diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp
index 1cf27ee0..d28671fa 100644
--- a/src/render/MBlur.cpp
+++ b/src/render/MBlur.cpp
@@ -4,12 +4,13 @@
#include "Camera.h"
#include "MBlur.h"
+// Originally taken from RW example 'mblur'
+
RwRaster *&CMBlur::pFrontBuffer = *(RwRaster**)0x8E2C48;
bool &CMBlur::ms_bJustInitialised = *(bool*)0x95CDAB;
bool &CMBlur::BlurOn = *(bool*)0x95CDAD;
static RwIm2DVertex Vertex[4];
-//static RwIm2DVertex *Vertex = (RwIm2DVertex*)0x62F780;
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
void
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index c2725ed6..41ee5d1d 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -1,12 +1,247 @@
#include "common.h"
#include "patcher.h"
+#include "main.h"
+#include "TxdStore.h"
+#include "Timer.h"
+#include "Replay.h"
#include "Skidmarks.h"
-WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); }
-WRAPPER void CSkidmarks::Update() { EAXJMP(0x518200); }
+CSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];
-WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); }
-WRAPPER void CSkidmarks::RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy) { EAXJMP(0x5185C0); }
+RwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];
+RwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2];
+RwTexture *gpSkidTex;
+RwTexture *gpSkidBloodTex;
+RwTexture *gpSkidMudTex;
-WRAPPER void CSkidmarks::Init(void) { EAXJMP(0x517D70); }
-WRAPPER void CSkidmarks::Shutdown(void) { EAXJMP(0x518100); }
+void
+CSkidmarks::Init(void)
+{
+ int i, ix, slot;
+ CTxdStore::PushCurrentTxd();
+ slot = CTxdStore::FindTxdSlot("particle");
+ CTxdStore::SetCurrentTxd(slot);
+ gpSkidTex = RwTextureRead("particleskid", nil);
+ gpSkidBloodTex = RwTextureRead("particleskidblood", nil);
+ gpSkidMudTex = RwTextureRead("particleskidmud", nil);
+ CTxdStore::PopCurrentTxd();
+
+ for(i = 0; i < NUMSKIDMARKS; i++){
+ aSkidmarks[i].m_state = 0;
+ aSkidmarks[i].m_wasUpdated = false;
+ }
+
+ ix = 0;
+ for(i = 0; i < SKIDMARK_LENGTH; i++){
+ SkidmarkIndexList[i*6+0] = ix+0;
+ SkidmarkIndexList[i*6+1] = ix+2;
+ SkidmarkIndexList[i*6+2] = ix+1;
+ SkidmarkIndexList[i*6+3] = ix+1;
+ SkidmarkIndexList[i*6+4] = ix+2;
+ SkidmarkIndexList[i*6+5] = ix+3;
+ ix += 2;
+ }
+
+ for(i = 0; i < SKIDMARK_LENGTH; i++){
+ RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 0], 0.0f);
+ RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 0], i*5.01f);
+ RwIm3DVertexSetU(&SkidmarkVertices[i*2 + 1], 1.0f);
+ RwIm3DVertexSetV(&SkidmarkVertices[i*2 + 1], i*5.01f);
+ }
+}
+
+void
+CSkidmarks::Shutdown(void)
+{
+ RwTextureDestroy(gpSkidTex);
+ RwTextureDestroy(gpSkidBloodTex);
+ RwTextureDestroy(gpSkidMudTex);
+}
+
+void
+CSkidmarks::Clear(void)
+{
+ int i;
+ for(i = 0; i < NUMSKIDMARKS; i++){
+ aSkidmarks[i].m_state = 0;
+ aSkidmarks[i].m_wasUpdated = false;
+ }
+}
+
+void
+CSkidmarks::Update(void)
+{
+ int i;
+ uint32 t1 = CTimer::GetTimeInMilliseconds() + 2500;
+ uint32 t2 = CTimer::GetTimeInMilliseconds() + 5000;
+ uint32 t3 = CTimer::GetTimeInMilliseconds() + 10000;
+ uint32 t4 = CTimer::GetTimeInMilliseconds() + 20000;
+ for(i = 0; i < NUMSKIDMARKS; i++){
+ switch(aSkidmarks[i].m_state){
+ case 1:
+ if(!aSkidmarks[i].m_wasUpdated){
+ // Didn't continue this one last time, so finish it and set fade times
+ aSkidmarks[i].m_state = 2;
+ if(aSkidmarks[i].m_last < 4){
+ aSkidmarks[i].m_fadeStart = t1;
+ aSkidmarks[i].m_fadeEnd = t2;
+ }else if(aSkidmarks[i].m_last < 9){
+ aSkidmarks[i].m_fadeStart = t2;
+ aSkidmarks[i].m_fadeEnd = t3;
+ }else{
+ aSkidmarks[i].m_fadeStart = t3;
+ aSkidmarks[i].m_fadeEnd = t4;
+ }
+ }
+ break;
+ case 2:
+ if(CTimer::GetTimeInMilliseconds() > aSkidmarks[i].m_fadeEnd)
+ aSkidmarks[i].m_state = 0;
+ break;
+ }
+ aSkidmarks[i].m_wasUpdated = false;
+ }
+}
+
+void
+CSkidmarks::Render(void)
+{
+ int i, j;
+ RwTexture *lastTex = nil;
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ for(i = 0; i < NUMSKIDMARKS; i++){
+ if(aSkidmarks[i].m_state == 0 || aSkidmarks[i].m_last < 1)
+ continue;
+
+ if(aSkidmarks[i].m_isBloody){
+ if(lastTex != gpSkidBloodTex){
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidBloodTex));
+ lastTex = gpSkidBloodTex;
+ }
+ }else if(aSkidmarks[i].m_isMuddy){
+ if(lastTex != gpSkidMudTex){
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidMudTex));
+ lastTex = gpSkidMudTex;
+ }
+ }else{
+ if(lastTex != gpSkidTex){
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));
+ lastTex = gpSkidTex;
+ }
+ }
+
+ uint32 fade, alpha;
+ if(aSkidmarks[i].m_state == 1 || CTimer::GetTimeInMilliseconds() < aSkidmarks[i].m_fadeStart)
+ fade = 255;
+ else
+ fade = 255*(aSkidmarks[i].m_fadeEnd - CTimer::GetTimeInMilliseconds()) / (aSkidmarks[i].m_fadeEnd - aSkidmarks[i].m_fadeStart);
+
+ for(j = 0; j <= aSkidmarks[i].m_last; j++){
+ alpha = 128;
+ if(j == 0 || j == aSkidmarks[i].m_last && aSkidmarks[i].m_state == 2)
+ alpha = 0;
+ alpha = alpha*fade/256;
+
+ CVector p1 = aSkidmarks[i].m_pos[j] + aSkidmarks[i].m_side[j];
+ CVector p2 = aSkidmarks[i].m_pos[j] - aSkidmarks[i].m_side[j];
+ RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], 255, 255, 255, alpha);
+ RwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f);
+ RwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], 255, 255, 255, alpha);
+ RwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f);
+ }
+
+ LittleTest();
+ if(RwIm3DTransform(SkidmarkVertices, 2*(aSkidmarks[i].m_last+1), nil, rwIM3D_VERTEXUV)){
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, SkidmarkIndexList, 6*aSkidmarks[i].m_last);
+ RwIm3DEnd();
+ }
+ }
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+}
+
+void
+CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody)
+{
+ int i;
+ CVector2D fwd(fwdX, fwdY);
+
+ if(CReplay::IsPlayingBack())
+ return;
+
+ // Find a skidmark to continue
+ for(i = 0; i < NUMSKIDMARKS; i++)
+ if(aSkidmarks[i].m_state == 1 && aSkidmarks[i].m_id == id)
+ break;
+
+ if(i < NUMSKIDMARKS){
+ // Continue this one
+
+ if(aSkidmarks[i].m_isBloody != *isBloody){
+ // Blood-status changed, end this one
+ aSkidmarks[i].m_state = 2;
+ aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;
+ aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;
+ return;
+ }
+
+ aSkidmarks[i].m_wasUpdated = true;
+
+ if(CTimer::GetTimeInMilliseconds() - aSkidmarks[i].m_lastUpdate <= 100){
+ // Last update was recently, just change last coords
+ aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
+ return;
+ }
+ aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds();
+
+ if(aSkidmarks[i].m_last >= SKIDMARK_LENGTH-1){
+ // No space to continue, end it
+ aSkidmarks[i].m_state = 2;
+ aSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;
+ aSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;
+ *isBloody = false; // stpo blood marks at end
+ return;
+ }
+ aSkidmarks[i].m_last++;
+
+ aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
+
+ CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1];
+ dist.Normalise();
+ CVector2D right(dist.y, -dist.x);
+ float turn = DotProduct2D(fwd, right);
+ turn = Abs(turn) + 1.0f;
+ aSkidmarks[i].m_side[aSkidmarks[i].m_last] = CVector(right.x, right.y, 0.0f) * turn * 0.125f;
+ if(aSkidmarks[i].m_last == 1)
+ aSkidmarks[i].m_side[0] = aSkidmarks[i].m_side[1];
+
+ if(aSkidmarks[i].m_last > 8)
+ *isBloody = false; // stop blood marks after 8
+ return;
+ }
+
+ // Start a new one
+ for(i = 0; i < NUMSKIDMARKS; i++)
+ if(aSkidmarks[i].m_state == 0)
+ break;
+ if(i < NUMSKIDMARKS){
+ // Found a free slot
+ aSkidmarks[i].m_state = 1;
+ aSkidmarks[i].m_id = id;
+ aSkidmarks[i].m_pos[0] = pos;
+ aSkidmarks[i].m_side[0] = CVector(0.0f, 0.0f, 0.0f);
+ aSkidmarks[i].m_wasUpdated = true;
+ aSkidmarks[i].m_last = 0;
+ aSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds() - 1000;
+ aSkidmarks[i].m_isBloody = *isBloody;
+ aSkidmarks[i].m_isMuddy = *isMuddy;
+ }else
+ *isBloody = false; // stop blood marks if no space
+}
diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h
index bf2da7e4..085b4c6d 100644
--- a/src/render/Skidmarks.h
+++ b/src/render/Skidmarks.h
@@ -1,12 +1,32 @@
#pragma once
+enum { SKIDMARK_LENGTH = 16 };
+
+class CSkidmark
+{
+public:
+ uint8 m_state;
+ bool m_wasUpdated;
+ bool m_isBloody;
+ bool m_isMuddy;
+ uintptr m_id;
+ int16 m_last;
+ uint32 m_lastUpdate;;
+ uint32 m_fadeStart;
+ uint32 m_fadeEnd;
+ CVector m_pos[SKIDMARK_LENGTH];
+ CVector m_side[SKIDMARK_LENGTH];
+};
+
class CSkidmarks
{
+ static CSkidmark aSkidmarks[NUMSKIDMARKS];
public:
+
+ static void Init(void);
+ static void Shutdown(void);
static void Clear(void);
static void Update(void);
static void Render(void);
- static void RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy);
- static void Init(void);
- static void Shutdown(void);
+ static void RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody);
};
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 0d856d9c..9189a7c2 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -22,10 +22,10 @@
#include "Shadows.h"
#include "main.h"
-RxObjSpace3DVertex StreakVertices[4];
+RwIm3DVertex StreakVertices[4];
RwImVertexIndex StreakIndexList[12];
-RxObjSpace3DVertex TraceVertices[6];
+RwIm3DVertex TraceVertices[6];
RwImVertexIndex TraceIndexList[12];
@@ -34,60 +34,60 @@ CSpecialFX::Init(void)
{
CBulletTraces::Init();
- RwIm3DVertexSetU(&StreakVertices[0], 0.0f);
- RwIm3DVertexSetV(&StreakVertices[0], 0.0f);
- RwIm3DVertexSetU(&StreakVertices[1], 1.0f);
- RwIm3DVertexSetV(&StreakVertices[1], 0.0f);
- RwIm3DVertexSetU(&StreakVertices[2], 0.0f);
- RwIm3DVertexSetV(&StreakVertices[2], 0.0f);
- RwIm3DVertexSetU(&StreakVertices[3], 1.0f);
- RwIm3DVertexSetV(&StreakVertices[3], 0.0f);
-
- StreakIndexList[0] = 0;
- StreakIndexList[1] = 1;
- StreakIndexList[2] = 2;
- StreakIndexList[3] = 1;
- StreakIndexList[4] = 3;
- StreakIndexList[5] = 2;
- StreakIndexList[6] = 0;
- StreakIndexList[7] = 2;
- StreakIndexList[8] = 1;
- StreakIndexList[9] = 1;
- StreakIndexList[10] = 2;
- StreakIndexList[11] = 3;
-
- RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255);
- RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255);
- RwIm3DVertexSetU(&TraceVertices[0], 0.0);
- RwIm3DVertexSetV(&TraceVertices[0], 0.0);
- RwIm3DVertexSetU(&TraceVertices[1], 1.0);
- RwIm3DVertexSetV(&TraceVertices[1], 0.0);
- RwIm3DVertexSetU(&TraceVertices[2], 0.0);
- RwIm3DVertexSetV(&TraceVertices[2], 0.5);
- RwIm3DVertexSetU(&TraceVertices[3], 1.0);
- RwIm3DVertexSetV(&TraceVertices[3], 0.5);
- RwIm3DVertexSetU(&TraceVertices[4], 0.0);
- RwIm3DVertexSetV(&TraceVertices[4], 1.0);
- RwIm3DVertexSetU(&TraceVertices[5], 1.0);
- RwIm3DVertexSetV(&TraceVertices[5], 1.0);
-
- TraceIndexList[0] = 0;
- TraceIndexList[1] = 2;
- TraceIndexList[2] = 1;
- TraceIndexList[3] = 1;
- TraceIndexList[4] = 2;
- TraceIndexList[5] = 3;
- TraceIndexList[6] = 2;
- TraceIndexList[7] = 4;
- TraceIndexList[8] = 3;
- TraceIndexList[9] = 3;
- TraceIndexList[10] = 4;
- TraceIndexList[11] = 5;
-
+ RwIm3DVertexSetU(&StreakVertices[0], 0.0f);
+ RwIm3DVertexSetV(&StreakVertices[0], 0.0f);
+ RwIm3DVertexSetU(&StreakVertices[1], 1.0f);
+ RwIm3DVertexSetV(&StreakVertices[1], 0.0f);
+ RwIm3DVertexSetU(&StreakVertices[2], 0.0f);
+ RwIm3DVertexSetV(&StreakVertices[2], 0.0f);
+ RwIm3DVertexSetU(&StreakVertices[3], 1.0f);
+ RwIm3DVertexSetV(&StreakVertices[3], 0.0f);
+
+ StreakIndexList[0] = 0;
+ StreakIndexList[1] = 1;
+ StreakIndexList[2] = 2;
+ StreakIndexList[3] = 1;
+ StreakIndexList[4] = 3;
+ StreakIndexList[5] = 2;
+ StreakIndexList[6] = 0;
+ StreakIndexList[7] = 2;
+ StreakIndexList[8] = 1;
+ StreakIndexList[9] = 1;
+ StreakIndexList[10] = 2;
+ StreakIndexList[11] = 3;
+
+ RwIm3DVertexSetRGBA(&TraceVertices[0], 20, 20, 20, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[1], 20, 20, 20, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[2], 70, 70, 70, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[3], 70, 70, 70, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[4], 10, 10, 10, 255);
+ RwIm3DVertexSetRGBA(&TraceVertices[5], 10, 10, 10, 255);
+ RwIm3DVertexSetU(&TraceVertices[0], 0.0);
+ RwIm3DVertexSetV(&TraceVertices[0], 0.0);
+ RwIm3DVertexSetU(&TraceVertices[1], 1.0);
+ RwIm3DVertexSetV(&TraceVertices[1], 0.0);
+ RwIm3DVertexSetU(&TraceVertices[2], 0.0);
+ RwIm3DVertexSetV(&TraceVertices[2], 0.5);
+ RwIm3DVertexSetU(&TraceVertices[3], 1.0);
+ RwIm3DVertexSetV(&TraceVertices[3], 0.5);
+ RwIm3DVertexSetU(&TraceVertices[4], 0.0);
+ RwIm3DVertexSetV(&TraceVertices[4], 1.0);
+ RwIm3DVertexSetU(&TraceVertices[5], 1.0);
+ RwIm3DVertexSetV(&TraceVertices[5], 1.0);
+
+ TraceIndexList[0] = 0;
+ TraceIndexList[1] = 2;
+ TraceIndexList[2] = 1;
+ TraceIndexList[3] = 1;
+ TraceIndexList[4] = 2;
+ TraceIndexList[5] = 3;
+ TraceIndexList[6] = 2;
+ TraceIndexList[7] = 4;
+ TraceIndexList[8] = 3;
+ TraceIndexList[9] = 3;
+ TraceIndexList[10] = 4;
+ TraceIndexList[11] = 5;
+
CMotionBlurStreaks::Init();
CBrightLights::Init();
CShinyTexts::Init();
@@ -112,13 +112,13 @@ LookForBatCB(RwObject *object, void *data)
void
CSpecialFX::Update(void)
{
- CMotionBlurStreaks::Update();
- CBulletTraces::Update();
-
- if(FindPlayerPed() &&
- FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&
- FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING)
- RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT));
+ CMotionBlurStreaks::Update();
+ CBulletTraces::Update();
+
+ if(FindPlayerPed() &&
+ FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&
+ FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING)
+ RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT));
}
void
@@ -130,78 +130,78 @@ CSpecialFX::Shutdown(void)
void
CSpecialFX::Render(void)
{
- CMotionBlurStreaks::Render();
- CBulletTraces::Render();
- CBrightLights::Render();
- CShinyTexts::Render();
- CMoneyMessages::Render();
- C3dMarkers::Render();
+ CMotionBlurStreaks::Render();
+ CBulletTraces::Render();
+ CBrightLights::Render();
+ CShinyTexts::Render();
+ CMoneyMessages::Render();
+ C3dMarkers::Render();
}
CRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS];
-void
-CRegisteredMotionBlurStreak::Update(void)
-{
- int i;
- bool wasUpdated;
- bool lastWasUpdated = false;
- for(i = 2; i > 0; i--){
- m_pos1[i] = m_pos1[i-1];
- m_pos2[i] = m_pos2[i-1];
- m_isValid[i] = m_isValid[i-1];
- wasUpdated = true;
- if(!lastWasUpdated && !m_isValid[i])
- wasUpdated = false;
- lastWasUpdated = wasUpdated;
- }
- m_isValid[0] = false;
- if(!wasUpdated)
- m_id = 0;
-}
-
-void
-CRegisteredMotionBlurStreak::Render(void)
-{
- int i;
- int a1, a2;
- for(i = 0; i < 2; i++)
- if(m_isValid[i] && m_isValid[i+1]){
- a1 = (255/3)*(3-i)/3;
- RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1);
- RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1);
- a2 = (255/3)*(3-(i+1))/3;
- RwIm3DVertexSetRGBA(&StreakVertices[2], m_red, m_green, m_blue, a2);
- RwIm3DVertexSetRGBA(&StreakVertices[3], m_red, m_green, m_blue, a2);
- RwIm3DVertexSetPos(&StreakVertices[0], m_pos1[i].x, m_pos1[i].y, m_pos1[i].z);
- RwIm3DVertexSetPos(&StreakVertices[1], m_pos2[i].x, m_pos2[i].y, m_pos2[i].z);
- RwIm3DVertexSetPos(&StreakVertices[2], m_pos1[i+1].x, m_pos1[i+1].y, m_pos1[i+1].z);
- RwIm3DVertexSetPos(&StreakVertices[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z);
+void
+CRegisteredMotionBlurStreak::Update(void)
+{
+ int i;
+ bool wasUpdated;
+ bool lastWasUpdated = false;
+ for(i = 2; i > 0; i--){
+ m_pos1[i] = m_pos1[i-1];
+ m_pos2[i] = m_pos2[i-1];
+ m_isValid[i] = m_isValid[i-1];
+ wasUpdated = true;
+ if(!lastWasUpdated && !m_isValid[i])
+ wasUpdated = false;
+ lastWasUpdated = wasUpdated;
+ }
+ m_isValid[0] = false;
+ if(!wasUpdated)
+ m_id = 0;
+}
+
+void
+CRegisteredMotionBlurStreak::Render(void)
+{
+ int i;
+ int a1, a2;
+ for(i = 0; i < 2; i++)
+ if(m_isValid[i] && m_isValid[i+1]){
+ a1 = (255/3)*(3-i)/3;
+ RwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1);
+ RwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1);
+ a2 = (255/3)*(3-(i+1))/3;
+ RwIm3DVertexSetRGBA(&StreakVertices[2], m_red, m_green, m_blue, a2);
+ RwIm3DVertexSetRGBA(&StreakVertices[3], m_red, m_green, m_blue, a2);
+ RwIm3DVertexSetPos(&StreakVertices[0], m_pos1[i].x, m_pos1[i].y, m_pos1[i].z);
+ RwIm3DVertexSetPos(&StreakVertices[1], m_pos2[i].x, m_pos2[i].y, m_pos2[i].z);
+ RwIm3DVertexSetPos(&StreakVertices[2], m_pos1[i+1].x, m_pos1[i+1].y, m_pos1[i+1].z);
+ RwIm3DVertexSetPos(&StreakVertices[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z);
LittleTest();
if(RwIm3DTransform(StreakVertices, 4, nil, rwIM3D_VERTEXUV)){
RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, StreakIndexList, 12);
RwIm3DEnd();
- }
- }
-}
-
-void
-CMotionBlurStreaks::Init(void)
-{
- int i;
- for(i = 0; i < NUMMBLURSTREAKS; i++)
- aStreaks[i].m_id = 0;
-}
-
-void
-CMotionBlurStreaks::Update(void)
-{
- int i;
- for(i = 0; i < NUMMBLURSTREAKS; i++)
- if(aStreaks[i].m_id)
- aStreaks[i].Update();
-}
-
+ }
+ }
+}
+
+void
+CMotionBlurStreaks::Init(void)
+{
+ int i;
+ for(i = 0; i < NUMMBLURSTREAKS; i++)
+ aStreaks[i].m_id = 0;
+}
+
+void
+CMotionBlurStreaks::Update(void)
+{
+ int i;
+ for(i = 0; i < NUMMBLURSTREAKS; i++)
+ if(aStreaks[i].m_id)
+ aStreaks[i].Update();
+}
+
void
CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2)
{
@@ -234,32 +234,32 @@ CMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVecto
aStreaks[i].m_isValid[2] = false;
}
-void
-CMotionBlurStreaks::Render(void)
-{
+void
+CMotionBlurStreaks::Render(void)
+{
bool setRenderStates = false;
int i;
- for(i = 0; i < NUMMBLURSTREAKS; i++)
- if(aStreaks[i].m_id){
- if(!setRenderStates){
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ for(i = 0; i < NUMMBLURSTREAKS; i++)
+ if(aStreaks[i].m_id){
+ if(!setRenderStates){
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATEFOGCOLOR,
(void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
- setRenderStates = true;
- }
- aStreaks[i].Render();
- }
- if(setRenderStates){
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
- }
-}
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
+ setRenderStates = true;
+ }
+ aStreaks[i].Render();
+ }
+ if(setRenderStates){
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
+ }
+}
CBulletTrace CBulletTraces::aTraces[NUMBULLETTRACES];
@@ -291,10 +291,10 @@ void CBulletTraces::Render(void)
for (int i = 0; i < NUMBULLETTRACES; i++) {
if (!aTraces[i].m_bInUse)
continue;
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)2);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpShadowExplosionTex->raster);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpShadowExplosionTex));
CVector inf = aTraces[i].m_vecCurrentPos;
CVector sup = aTraces[i].m_vecTargetPos;
CVector center = (inf + sup) / 2;
@@ -316,9 +316,9 @@ void CBulletTraces::Render(void)
RwIm3DEnd();
}
}
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}
void CBulletTraces::Update(void)
@@ -414,8 +414,7 @@ C3dMarker::Render()
{
if (m_pAtomic == nil) return;
- RwRGBA *color = RpMaterialGetColor(m_pMaterial);
- *color = m_Color;
+ RpMaterialSetColor(m_pMaterial, &m_Color);
m_Matrix.UpdateRW();
@@ -643,13 +642,13 @@ C3dMarkers::Update()
int CBrightLights::NumBrightLights;
CBrightLight CBrightLights::aBrightLights[NUMBRIGHTLIGHTS];
-
-void
-CBrightLights::Init(void)
-{
- NumBrightLights = 0;
-}
-
+
+void
+CBrightLights::Init(void)
+{
+ NumBrightLights = 0;
+}
+
void
CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front,
uint8 type, uint8 red, uint8 green, uint8 blue)
@@ -661,13 +660,13 @@ CBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front,
if(aBrightLights[NumBrightLights].m_camDist > BRIGHTLIGHTS_MAX_DIST)
return;
- aBrightLights[NumBrightLights].m_pos = pos;
- aBrightLights[NumBrightLights].m_up = up;
- aBrightLights[NumBrightLights].m_side = side;
- aBrightLights[NumBrightLights].m_front = front;
- aBrightLights[NumBrightLights].m_type = type;
- aBrightLights[NumBrightLights].m_red = red;
- aBrightLights[NumBrightLights].m_green = green;
+ aBrightLights[NumBrightLights].m_pos = pos;
+ aBrightLights[NumBrightLights].m_up = up;
+ aBrightLights[NumBrightLights].m_side = side;
+ aBrightLights[NumBrightLights].m_front = front;
+ aBrightLights[NumBrightLights].m_type = type;
+ aBrightLights[NumBrightLights].m_red = red;
+ aBrightLights[NumBrightLights].m_green = green;
aBrightLights[NumBrightLights].m_blue = blue;
NumBrightLights++;
@@ -696,22 +695,22 @@ static RwImVertexIndex CubeIndices[12*3] = {
6, 0, 4, 6, 2, 0, 6, 5, 7, 6, 4, 5
};
-void
-CBrightLights::Render(void)
-{
+void
+CBrightLights::Render(void)
+{
int i, j;
CVector pos;
- if(NumBrightLights == 0)
- return;
-
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
-
- for(i = 0; i < NumBrightLights; i++){
+ if(NumBrightLights == 0)
+ return;
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+
+ for(i = 0; i < NumBrightLights; i++){
if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40)
RenderOutGeometryBuffer();
@@ -753,14 +752,14 @@ CBrightLights::Render(void)
a = 255;
else
a = 255*(1.0f - (aBrightLights[i].m_camDist-BRIGHTLIGHTS_FADE_DIST)/(BRIGHTLIGHTS_MAX_DIST-BRIGHTLIGHTS_FADE_DIST));
- // fade car lights down to 31 as they come near
- if(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){
+ // fade car lights down to 31 as they come near
+ if(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){
if(aBrightLights[i].m_camDist < CARLIGHTS_FADE_DIST)
a = 31;
else if(aBrightLights[i].m_camDist < CARLIGHTS_MAX_DIST)
a = 31 + (255-31)*((aBrightLights[i].m_camDist-CARLIGHTS_FADE_DIST)/(CARLIGHTS_MAX_DIST-CARLIGHTS_FADE_DIST));
- }
-
+ }
+
switch(aBrightLights[i].m_type){
case BRIGHTLIGHT_TRAFFIC_GREEN:
case BRIGHTLIGHT_TRAFFIC_YELLOW:
@@ -793,7 +792,7 @@ CBrightLights::Render(void)
TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12*3;
break;
-
+
case BRIGHTLIGHT_FRONT_SMALL:
case BRIGHTLIGHT_REAR_SMALL:
for(j = 0; j < 8; j++){
@@ -809,7 +808,7 @@ CBrightLights::Render(void)
TempBufferVerticesStored += 8;
TempBufferIndicesStored += 12*3;
break;
-
+
case BRIGHTLIGHT_FRONT_TALL:
case BRIGHTLIGHT_REAR_TALL:
for(j = 0; j < 8; j++){
@@ -840,17 +839,17 @@ CBrightLights::Render(void)
TempBufferIndicesStored += 4*3;
break;
- }
- }
-
- RenderOutGeometryBuffer();
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- NumBrightLights = 0;
-}
-
-void
-CBrightLights::RenderOutGeometryBuffer(void)
-{
+ }
+ }
+
+ RenderOutGeometryBuffer();
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ NumBrightLights = 0;
+}
+
+void
+CBrightLights::RenderOutGeometryBuffer(void)
+{
if(TempBufferIndicesStored != 0){
LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
@@ -864,13 +863,13 @@ CBrightLights::RenderOutGeometryBuffer(void)
int CShinyTexts::NumShinyTexts;
CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS];
-
-void
-CShinyTexts::Init(void)
-{
- NumShinyTexts = 0;
-}
-
+
+void
+CShinyTexts::Init(void)
+{
+ NumShinyTexts = 0;
+}
+
void
CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
@@ -910,20 +909,20 @@ CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
NumShinyTexts++;
}
-void
-CShinyTexts::Render(void)
-{
- int i, ix, v;
- RwTexture *lastTex = nil;
-
- if(NumShinyTexts == 0)
- return;
-
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
-
+void
+CShinyTexts::Render(void)
+{
+ int i, ix, v;
+ RwTexture *lastTex = nil;
+
+ if(NumShinyTexts == 0)
+ return;
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
@@ -984,15 +983,15 @@ CShinyTexts::Render(void)
RenderOutGeometryBuffer();
NumShinyTexts = 0;
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
-}
-
-void
-CShinyTexts::RenderOutGeometryBuffer(void)
-{
+}
+
+void
+CShinyTexts::RenderOutGeometryBuffer(void)
+{
if(TempBufferIndicesStored != 0){
LittleTest();
if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
@@ -1002,8 +1001,8 @@ CShinyTexts::RenderOutGeometryBuffer(void)
TempBufferVerticesStored = 0;
TempBufferIndicesStored = 0;
}
-}
-
+}
+
#define MONEY_MESSAGE_LIFETIME_MS 2000
diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp
index 24577f41..fec50c7e 100644
--- a/src/render/Sprite.cpp
+++ b/src/render/Sprite.cpp
@@ -432,6 +432,7 @@ void
CSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
float screenz, recipz;
+ float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane;
@@ -496,6 +497,7 @@ CSprite::Set6Vertices2D(RwIm2DVertex *verts, float x1, float y1, float x2, float
const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
float screenz, recipz;
+ float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = m_f2DNearScreenZ;
recipz = m_fRecipNearClipPlane;
diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp
index c4dbcdaa..3f21516a 100644
--- a/src/render/Sprite2d.cpp
+++ b/src/render/Sprite2d.cpp
@@ -267,6 +267,7 @@ CSprite2d::SetVertices(float x1, float y1, float x2, float y2, float x3, float y
const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
float screenz, recipz;
+ float z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
@@ -312,10 +313,11 @@ void
CSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col)
{
int i;
- float screenz, recipz;
+ float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
+ z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){
@@ -334,10 +336,11 @@ void
CSprite2d::SetMaskVertices(int n, float *positions)
{
int i;
- float screenz, recipz;
+ float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
+ z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
for(i = 0; i < n; i++){
RwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);
@@ -345,7 +348,7 @@ CSprite2d::SetMaskVertices(int n, float *positions)
RwIm2DVertexSetScreenZ(&maVertices[i], screenz);
RwIm2DVertexSetCameraZ(&maVertices[i], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[i], recipz);
- RwIm2DVertexSetIntRGBA(&maVertices[i], 0, 0, 0, 0);
+ RwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255); // 0, 0, 0, 0 on PC
}
}
@@ -353,10 +356,11 @@ void
CSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
{
- float screenz, recipz;
+ float screenz, recipz, z;
screenz = RwIm2DGetNearScreenZ();
recipz = RecipNearClip;
+ z = RwCameraGetNearClipPlane(Scene.camera); // not done by game
RwIm2DVertexSetScreenX(&verts[0], r.left);
RwIm2DVertexSetScreenY(&verts[0], r.top);
@@ -459,15 +463,15 @@ CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const C
void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color)
{
- SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
- RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
- RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ SetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
+ RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));
+ RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
}
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index 235d559c..f126dca6 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -136,6 +136,7 @@ public:
static int GetFogRed(void) { return m_nCurrentFogColourRed; }
static int GetFogGreen(void) { return m_nCurrentFogColourGreen; }
static int GetFogBlue(void) { return m_nCurrentFogColourBlue; }
+ static int GetFogReduction(void) { return m_FogReduction; }
static void Initialise(void);
static void Update(void);
diff --git a/src/render/VisibilityPlugins.cpp b/src/render/VisibilityPlugins.cpp
index 74cd2590..f8b1f6b2 100644
--- a/src/render/VisibilityPlugins.cpp
+++ b/src/render/VisibilityPlugins.cpp
@@ -117,7 +117,7 @@ CVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)
RpMaterial*
SetAlphaCB(RpMaterial *material, void *data)
{
- material->color.alpha = (uint8)(uint32)data;
+ ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uint32)data;
return material;
}
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index c1988ab4..d132ffdb 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -2,6 +2,22 @@
#include "patcher.h"
#include "Weather.h"
+#include "Camera.h"
+#include "Clock.h"
+#include "CutsceneMgr.h"
+#include "DMAudio.h"
+#include "General.h"
+#include "Pad.h"
+#include "Particle.h"
+#include "RenderBuffer.h"
+#include "Stats.h"
+#include "Shadows.h"
+#include "Timecycle.h"
+#include "Timer.h"
+#include "Vehicle.h"
+#include "World.h"
+#include "ZoneCull.h"
+
int32 &CWeather::SoundHandle = *(int32*)0x5FFBC4;
int32 &CWeather::WeatherTypeInList = *(int32*)0x8F626C;
@@ -32,13 +48,203 @@ int16 &CWeather::Stored_OldWeatherType = *(int16*)0x95CC68;
int16 &CWeather::Stored_NewWeatherType = *(int16*)0x95CCAE;
float &CWeather::Stored_Rain = *(float*)0x885B4C;
-WRAPPER void CWeather::RenderRainStreaks(void) { EAXJMP(0x524550); }
-WRAPPER void CWeather::Update(void) { EAXJMP(0x522C10); }
-WRAPPER void CWeather::Init(void) { EAXJMP(0x522BA0); }
+tRainStreak Streaks[NUM_RAIN_STREAKS];
-void CWeather::ReleaseWeather()
+const int16 WeatherTypesList[] = {
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
+ WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_CLOUDY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_CLOUDY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, WEATHER_CLOUDY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
+ WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_SUNNY,
+ WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_RAINY, WEATHER_CLOUDY,
+};
+
+const float Windiness[] = {
+ 0.0f, // WEATHER_SUNNY
+ 0.7f, // WEATHER_RAINY
+ 1.0f, // WEATHER_CLOUDY
+ 0.5f // WEATHER_FOGGY
+};
+
+#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50)
+
+#define RAIN_CHANGE_SPEED (0.003f)
+
+#define DROPLETS_LEFT_OFFSET (10.0f)
+#define DROPLETS_RIGHT_OFFSET (10.0f)
+#define DROPLETS_TOP_OFFSET (10.0f)
+#define DROPLETS_BOTTOM_OFFSET (10.0f)
+
+#define STREAK_U (10.0f)
+#define STREAK_V (18.0f)
+#define LARGE_STREAK_COEFFICIENT (1.23f)
+#define STREAK_MIN_DISTANCE (8.0f)
+#define STREAK_MAX_DISTANCE (16.0f)
+
+#define SPLASH_CHECK_RADIUS (7.0f)
+#define SPLASH_OFFSET_RADIUS (2.0f)
+
+#define STREAK_LIFETIME (4.0f)
+#define STREAK_INTEROLATION_TIME (0.3f)
+
+#define RAIN_COLOUR_R (200)
+#define RAIN_COLOUR_G (200)
+#define RAIN_COLOUR_B (256)
+#define RAIN_ALPHA (255)
+
+void CWeather::Init(void)
{
- ForcedWeatherType = -1;
+ NewWeatherType = WEATHER_SUNNY;
+ bScriptsForceRain = false;
+ OldWeatherType = WEATHER_RAINY;
+ Stored_StateStored = false;
+ InterpolationValue = 0.0f;
+ WhenToPlayLightningSound = 0;
+ WeatherTypeInList = 0;
+ ForcedWeatherType = WEATHER_RANDOM;
+ SoundHandle = DMAudio.CreateEntity(AUDIOTYPE_WEATHER, (void*)1);
+ if (SoundHandle >= 0)
+ DMAudio.SetEntityStatus(SoundHandle, 1);
+}
+
+void CWeather::Update(void)
+{
+ float fNewInterpolation = CClock::GetMinutes() * 1.0f / 60;
+ if (fNewInterpolation < InterpolationValue) {
+ // new hour
+ OldWeatherType = NewWeatherType;
+ if (ForcedWeatherType >= 0)
+ NewWeatherType = ForcedWeatherType;
+ else {
+ WeatherTypeInList = (WeatherTypeInList + 1) % ARRAYSIZE(WeatherTypesList);
+ NewWeatherType = WeatherTypesList[WeatherTypeInList];
+#ifdef FIX_BUGS
+ }
+ if (NewWeatherType == WEATHER_RAINY)
+ CStats::mmRain += CGeneral::GetRandomNumber() & 7;
+#else
+ if (NewWeatherType == WEATHER_RAINY)
+ CStats::mmRain += CGeneral::GetRandomNumber() & 7;
+ }
+#endif
+ }
+ InterpolationValue = fNewInterpolation;
+ if (CPad::GetPad(1)->GetRightShockJustDown()) {
+ NewWeatherType = (NewWeatherType + 1) % WEATHER_TOTAL;
+ OldWeatherType = NewWeatherType;
+ }
+
+ // Lightning
+ if (NewWeatherType != WEATHER_RAINY || OldWeatherType != WEATHER_RAINY) {
+ LightningFlash = false;
+ LightningBurst = false;
+ }
+ else{
+ if (LightningBurst) {
+ if ((CGeneral::GetRandomNumber() & 255) >= 32) {
+ // 0.875 probability
+ if (CTimer::GetTimeInMilliseconds() - LightningFlashLastChange > MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES) {
+ bool bOldLightningFlash = LightningFlash;
+ LightningFlash = CGeneral::GetRandomTrueFalse();
+ if (LightningFlash != bOldLightningFlash)
+ LightningFlashLastChange = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ else {
+ // 0.125 probability
+ LightningBurst = false;
+ LightningDuration = min(CTimer::GetFrameCounter() - LightningStart, 20);
+ LightningFlash = false;
+ WhenToPlayLightningSound = CTimer::GetTimeInMilliseconds() + 150 * (20 - LightningDuration);
+ }
+ }
+ else {
+ if (CGeneral::GetRandomNumber() >= 200) {
+ // lower probability on PC due to randomness bug
+ LightningFlash = false;
+ }
+ else {
+ LightningBurst = true;
+ LightningStart = CTimer::GetFrameCounter();
+ LightningFlashLastChange = CTimer::GetTimeInMilliseconds();
+ LightningFlash = true;
+ }
+ }
+ }
+ if (WhenToPlayLightningSound && CTimer::GetTimeInMilliseconds() > WhenToPlayLightningSound) {
+ DMAudio.PlayOneShot(SoundHandle, SOUND_LIGHTNING, LightningDuration);
+ CPad::GetPad(0)->StartShake(40 * LightningDuration + 100, 2 * LightningDuration + 80);
+ WhenToPlayLightningSound = 0;
+ }
+
+ // Wet roads
+ if (OldWeatherType == WEATHER_RAINY) {
+ if (NewWeatherType == WEATHER_RAINY)
+ WetRoads = 1.0f;
+ else
+ WetRoads = 1.0f - InterpolationValue;
+ }
+ else {
+ if (NewWeatherType == WEATHER_RAINY)
+ WetRoads = InterpolationValue;
+ else
+ WetRoads = 0.0f;
+ }
+
+ // Rain
+ float fNewRain;
+ if (NewWeatherType == WEATHER_RAINY) {
+ // if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
+ fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
+ if (OldWeatherType != WEATHER_RAINY) {
+ if (InterpolationValue < 0.4f)
+ // if rain has just started (<24 minutes), always 0.5
+ fNewRain = 0.5f;
+ else
+ // if rain is ongoing for >24 minutes, values: 0.25, 0.5, 0.75, 1.0, switching every ~16.5s
+ fNewRain = 0.25f + ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.25f;
+ }
+ }
+ else
+ fNewRain = 0.0f;
+ if (Rain != fNewRain) { // ok to use comparasion
+ if (Rain < fNewRain)
+ Rain = min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
+ else
+ Rain = max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
+ }
+
+ // Clouds
+ if (OldWeatherType != WEATHER_SUNNY)
+ CloudCoverage = 1.0f - InterpolationValue;
+ else
+ CloudCoverage = 0.0f;
+ if (NewWeatherType != WEATHER_SUNNY)
+ CloudCoverage += InterpolationValue;
+
+ // Fog
+ if (OldWeatherType == WEATHER_FOGGY)
+ Foggyness = 1.0f - InterpolationValue;
+ else
+ Foggyness = 0.0f;
+ if (NewWeatherType == WEATHER_FOGGY)
+ Foggyness += InterpolationValue;
+ if (OldWeatherType == WEATHER_RAINY && NewWeatherType == WEATHER_SUNNY && InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21)
+ Rainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f;
+ else
+ Rainbow = 0.0f;
+ Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType];
+ AddRain();
}
void CWeather::ForceWeather(int16 weather)
@@ -53,6 +259,258 @@ void CWeather::ForceWeatherNow(int16 weather)
ForcedWeatherType = weather;
}
+void CWeather::ReleaseWeather()
+{
+ ForcedWeatherType = -1;
+}
+
+void CWeather::AddRain()
+{
+ if (CCullZones::CamNoRain() || CCullZones::PlayerNoRain())
+ return;
+ if (TheCamera.GetLookingLRBFirstPerson()) {
+ CVehicle* pVehicle = FindPlayerVehicle();
+ if (pVehicle && pVehicle->CarHasRoof()) {
+ CParticle::RemovePSystem(PARTICLE_RAINDROP_2D);
+ return;
+ }
+ }
+ if (Rain <= 0.1f)
+ return;
+ static RwRGBA colour;
+ float screen_width = RsGlobal.width;
+ float screen_height = RsGlobal.height;
+ int cur_frame = (int)(3 * Rain) & 3;
+ int num_drops = (int)(2 * Rain) + 2;
+ static int STATIC_RAIN_ANGLE = -45;
+ static int count = 1500;
+ static int add_angle = 1;
+ if (--count == 0) {
+ count = 1;
+ if (add_angle) {
+ STATIC_RAIN_ANGLE += 12;
+ if (STATIC_RAIN_ANGLE > 45) {
+ count = 1500;
+ add_angle = !add_angle;
+ }
+ }
+ else {
+ STATIC_RAIN_ANGLE -= 12;
+ if (STATIC_RAIN_ANGLE < -45) {
+ count = 1500;
+ add_angle = !add_angle;
+ }
+ }
+ }
+ float rain_angle = DEGTORAD(STATIC_RAIN_ANGLE + ((STATIC_RAIN_ANGLE < 0) ? 360 : 0));
+ float sin_angle = Sin(rain_angle);
+ float cos_angle = Cos(rain_angle);
+ float base_x = 0.0f * cos_angle - 1.0f * sin_angle;
+ float base_y = 1.0f * cos_angle + 0.0f * sin_angle;
+ CVector xpos(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < 2 * num_drops; i++) {
+ CVector dir;
+ dir.x = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_x) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f);
+ dir.y = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_y) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f);
+ dir.z = 0;
+ CParticle::AddParticle(PARTICLE_RAINDROP_2D, xpos, dir, nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f),
+ colour, 0, rain_angle + CGeneral::GetRandomNumberInRange(-10, 10), cur_frame);
+ xpos.x += screen_width / (2 * num_drops);
+ xpos.x += CGeneral::GetRandomNumberInRange(-25.0f, 25.0f);
+ }
+ CVector ypos(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < num_drops; i++) {
+ CVector dir;
+ dir.x = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_x) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f);
+ dir.y = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_y) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f);
+ dir.z = 0;
+ CParticle::AddParticle(PARTICLE_RAINDROP_2D, ypos, dir, nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f),
+ colour, 0, rain_angle + CGeneral::GetRandomNumberInRange(-10, 10), cur_frame);
+ ypos.y += screen_width / num_drops;
+ ypos.y += CGeneral::GetRandomNumberInRange(-25.0f, 25.0f);
+ }
+ CVector ypos2(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < num_drops; i++) {
+ CVector dir;
+ dir.x = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_x) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f);
+ dir.y = (CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) + base_y) * CGeneral::GetRandomNumberInRange(10.0f, 25.0f);
+ dir.z = 0;
+ CParticle::AddParticle(PARTICLE_RAINDROP_2D, ypos2, dir, nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f),
+ colour, 0, rain_angle + CGeneral::GetRandomNumberInRange(-10, 10), cur_frame);
+ ypos2.y += screen_width / num_drops;
+ ypos2.y += CGeneral::GetRandomNumberInRange(-25.0f, 25.0f);
+ }
+ for (int i = 0; i < num_drops; i++) {
+ CVector pos;
+ pos.x = CGeneral::GetRandomNumberInRange(DROPLETS_LEFT_OFFSET, screen_width - DROPLETS_RIGHT_OFFSET);
+ pos.y = CGeneral::GetRandomNumberInRange(DROPLETS_TOP_OFFSET, screen_height - DROPLETS_TOP_OFFSET);
+ pos.z = 0.0f;
+ CParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.9f),
+ colour, CGeneral::GetRandomNumberInRange(-10, 10), 360 - rain_angle + CGeneral::GetRandomNumberInRange(-30, 30), cur_frame, 0);
+ }
+ int num_splash_attempts = (int)(3 * Rain) + 1;
+ int num_splashes = (int)(3 * Rain) + 4;
+ CVector splash_points[4];
+ splash_points[0] = CVector(-RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) *
+ RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude();
+ splash_points[1] = CVector(RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) *
+ RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude();
+ splash_points[2] = 4.0f * CVector(-RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) *
+ RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude();
+ splash_points[3] = 4.0f * CVector(RwCameraGetViewWindow(TheCamera.m_pRwCamera)->x, RwCameraGetViewWindow(TheCamera.m_pRwCamera)->y, 1.0f) *
+ RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) / (RwCameraGetFarClipPlane(TheCamera.m_pRwCamera) * *(CVector2D*)RwCameraGetViewWindow(TheCamera.m_pRwCamera)).Magnitude();
+ RwV3dTransformPoints((RwV3d*)splash_points, (RwV3d*)splash_points, 4, RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)));
+ CVector fp = (splash_points[0] + splash_points[1] + splash_points[2] + splash_points[3]) / 4;
+ for (int i = 0; i < num_splash_attempts; i++) {
+ CColPoint point;
+ CEntity* entity;
+ CVector np = fp + CVector(CGeneral::GetRandomNumberInRange(-SPLASH_CHECK_RADIUS, SPLASH_CHECK_RADIUS), CGeneral::GetRandomNumberInRange(-SPLASH_CHECK_RADIUS, SPLASH_CHECK_RADIUS), 0.0f);
+ if (CWorld::ProcessVerticalLine(np + CVector(0.0f, 0.0f, 40.0f), -40.0f, point, entity, true, false, false, false, true, false, nil)) {
+ for (int j = 0; j < num_splashes; j++)
+ CParticle::AddParticle((CGeneral::GetRandomTrueFalse() ? PARTICLE_RAIN_SPLASH : PARTICLE_RAIN_SPLASHUP),
+ CVector(
+ np.x + CGeneral::GetRandomNumberInRange(-SPLASH_OFFSET_RADIUS, SPLASH_OFFSET_RADIUS),
+ np.y + CGeneral::GetRandomNumberInRange(-SPLASH_OFFSET_RADIUS, SPLASH_OFFSET_RADIUS),
+ point.point.z + 0.1f),
+ CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour);
+ }
+ }
+}
+
+void RenderOneRainStreak(CVector pos, CVector unused, int intensity, bool scale, float distance)
+{
+ static float RandomTex;
+ static float RandomTexX;
+ static float RandomTexY;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored + 0;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 6] = TempBufferVerticesStored + 1;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 7] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 8] = TempBufferVerticesStored + 4;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 9] = TempBufferVerticesStored + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 10] = TempBufferVerticesStored + 3;
+ TempBufferRenderIndexList[TempBufferIndicesStored + 11] = TempBufferVerticesStored + 4;
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0, 0, 0, 0);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 0], pos.x + 11.0f * TheCamera.GetUp().x, pos.y + 11.0f * TheCamera.GetUp().y, pos.z + 11.0f * TheCamera.GetUp().z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 1], 0, 0, 0, 0);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 1], pos.x - 9.0f * TheCamera.GetRight().x, pos.y - 9.0f * TheCamera.GetRight().y, pos.z - 9.0f * TheCamera.GetUp().z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RAIN_COLOUR_R * intensity / 256, RAIN_COLOUR_G * intensity / 256, RAIN_COLOUR_B * intensity / 256, RAIN_ALPHA);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 2], pos.x, pos.y, pos.z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 3], 0, 0, 0, 0);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 3], pos.x + 9.0f * TheCamera.GetRight().x, pos.y + 9.0f * TheCamera.GetRight().y, pos.z + 9.0f * TheCamera.GetUp().z);
+ RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0, 0, 0, 0);
+ RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 4], pos.x - 11.0f * TheCamera.GetUp().x, pos.y - 11.0f * TheCamera.GetUp().y, pos.z - 11.0f * TheCamera.GetUp().z);
+ float u = STREAK_U;
+ float v = STREAK_V;
+ if (scale) {
+ u *= LARGE_STREAK_COEFFICIENT;
+ v *= LARGE_STREAK_COEFFICIENT;
+ }
+ float distance_coefficient;
+ if (distance < STREAK_MIN_DISTANCE)
+ distance_coefficient = 1.0f;
+ else if (distance > STREAK_MAX_DISTANCE)
+ distance_coefficient = 0.5f;
+ else
+ distance_coefficient = 1.0f - 0.5f * (distance - STREAK_MIN_DISTANCE) / (STREAK_MAX_DISTANCE - STREAK_MIN_DISTANCE);
+ u *= distance_coefficient;
+ v *= distance_coefficient;
+ if (!CTimer::GetIsPaused()) {
+ RandomTex = ((CGeneral::GetRandomNumber() & 255) - 128) * 0.01f;
+ RandomTexX = (CGeneral::GetRandomNumber() & 127) * 0.01f;
+ RandomTexY = (CGeneral::GetRandomNumber() & 127) * 0.01f;
+ }
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0.5f * u - RandomTex + RandomTexX);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 0], -v * 0.5f + RandomTexY);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexX);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexY);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 2], 0.5f * u + RandomTexX);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RandomTexY);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 3], u + RandomTexX);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 3], RandomTexY);
+ RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0.5f * u + RandomTex + RandomTexX);
+ RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 5], 0.5f * v + RandomTexY);
+ TempBufferIndicesStored += 12;
+ TempBufferVerticesStored += 5;
+}
+
+void CWeather::RenderRainStreaks(void)
+{
+ if (CTimer::GetIsCodePaused())
+ return;
+ int base_intensity = (64.0f - CTimeCycle::GetFogReduction()) / 64.0f * int(255 * Rain);
+ if (base_intensity == 0)
+ return;
+ TempBufferIndicesStored = 0;
+ TempBufferVerticesStored = 0;
+ for (int i = 0; i < NUM_RAIN_STREAKS; i++) {
+ if (Streaks[i].timer) {
+ float secondsElapsed = (CTimer::GetTimeInMilliseconds() - Streaks[i].timer) / 1024.0f;
+ if (secondsElapsed > STREAK_LIFETIME)
+ Streaks[i].timer = 0;
+ else{
+ int intensity;
+ if (secondsElapsed < STREAK_INTEROLATION_TIME)
+ intensity = base_intensity * 0.5f * secondsElapsed / STREAK_INTEROLATION_TIME;
+ else if (secondsElapsed > (STREAK_LIFETIME - STREAK_INTEROLATION_TIME))
+ intensity = (STREAK_LIFETIME - secondsElapsed) * 0.5f * base_intensity / STREAK_INTEROLATION_TIME;
+ else
+ intensity = base_intensity * 0.5f;
+ CVector dir = Streaks[i].direction;
+ dir.Normalise();
+ CVector pos = Streaks[i].position + secondsElapsed * Streaks[i].direction;
+ RenderOneRainStreak(pos, dir, intensity, false, (pos - TheCamera.GetPosition()).Magnitude());
+#ifndef FIX_BUGS // remove useless code
+ if (secondsElapsed > 1.0f && secondsElapsed < STREAK_LIFETIME - 1.0f) {
+ CGeneral::GetRandomNumber(), CGeneral::GetRandomNumber();
+ }
+#endif
+ }
+ }
+ else if ((CGeneral::GetRandomNumber() & 0xF00) == 0){
+ // 1/16 probability
+ Streaks[i].direction = CVector(4.0f, 4.0f, -4.0f);
+ Streaks[i].position = 6.0f * TheCamera.GetForward() + TheCamera.GetPosition() + CVector(-1.8f * Streaks[i].direction.x, -1.8f * Streaks[i].direction.y, 8.0f);
+ if (!CCutsceneMgr::IsCutsceneProcessing()) {
+ Streaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f;
+ Streaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f;
+ }
+ else
+ Streaks[i].position += (TheCamera.GetPosition() - TheCamera.m_RealPreviousCameraPosition) * 20.0f;
+ Streaks[i].position.x += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.08f;
+ Streaks[i].position.y += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.08f;
+ Streaks[i].timer = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ if (TempBufferIndicesStored){
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex[3]));
+ if (RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 1))
+ {
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
+ RwIm3DEnd();
+ }
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ }
+ TempBufferVerticesStored = 0;
+ TempBufferIndicesStored = 0;
+}
+
void CWeather::StoreWeatherState()
{
Stored_StateStored = true;
@@ -71,4 +529,4 @@ void CWeather::RestoreWeatherState()
Rain = Stored_Rain;
NewWeatherType = Stored_NewWeatherType;
OldWeatherType = Stored_OldWeatherType;
-} \ No newline at end of file
+}
diff --git a/src/render/Weather.h b/src/render/Weather.h
index 63def9b9..9e4ea378 100644
--- a/src/render/Weather.h
+++ b/src/render/Weather.h
@@ -8,6 +8,14 @@ enum {
class CWeather
{
public:
+ enum {
+ WEATHER_RANDOM = -1,
+ WEATHER_SUNNY = 0,
+ WEATHER_CLOUDY = 1,
+ WEATHER_RAINY = 2,
+ WEATHER_FOGGY = 3,
+ WEATHER_TOTAL = 4
+ };
static int32 &SoundHandle;
static int32 &WeatherTypeInList;
@@ -46,4 +54,18 @@ public:
static void ForceWeatherNow(int16);
static void StoreWeatherState();
static void RestoreWeatherState();
+ static void AddRain();
};
+
+enum {
+ NUM_RAIN_STREAKS = 35
+};
+
+struct tRainStreak
+{
+ CVector position;
+ CVector direction;
+ uint32 timer;
+};
+
+extern RwTexture* (&gpRainDropTex)[4]; \ No newline at end of file
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 0c8f0dd4..1c0d673e 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -182,17 +182,17 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_weaponDoorTimerRight = m_weaponDoorTimerLeft;
if(GetModelIndex() == MI_DODO){
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
CMatrix mat1;
mat1.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
CMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
mat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z);
mat1.UpdateRW();
}else if(GetModelIndex() == MI_MIAMI_SPARROW || GetModelIndex() == MI_MIAMI_RCRAIDER){
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
}else if(GetModelIndex() == MI_RHINO){
bExplosionProof = true;
bBulletProof = true;
diff --git a/src/vehicles/Bike.h b/src/vehicles/Bike.h
new file mode 100644
index 00000000..00aa259c
--- /dev/null
+++ b/src/vehicles/Bike.h
@@ -0,0 +1,15 @@
+#pragma once
+
+// some miami bike leftovers
+
+enum eBikeNodes {
+ BIKE_NODE_NONE,
+ BIKE_CHASSIS,
+ BIKE_FORKS_FRONT,
+ BIKE_FORKS_REAR,
+ BIKE_WHEEL_FRONT,
+ BIKE_WHEEL_REAR,
+ BIKE_MUDGUARD,
+ BIKE_HANDLEBARS,
+ BIKE_NUM_NODES
+}; \ No newline at end of file
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 6d584017..9c7cbb4f 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -94,7 +94,7 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos)
pos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component]));
}
-RxObjSpace3DVertex KeepWaterOutVertices[4];
+RwIm3DVertex KeepWaterOutVertices[4];
RwImVertexIndex KeepWaterOutIndices[6];
void
@@ -103,7 +103,7 @@ CBoat::Render()
CMatrix matrix;
if (m_aBoatNodes[1] != nil) {
- matrix.Attach(&m_aBoatNodes[1]->modelling);
+ matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[1]));
CVector pos = matrix.GetPosition();
matrix.SetRotateZ(m_fMovingHiRotation);
@@ -111,7 +111,7 @@ CBoat::Render()
matrix.UpdateRW();
if (CVehicle::bWheelsOnlyCheat) {
- RpAtomicRenderMacro((RpAtomic*)GetFirstObject(m_aBoatNodes[1]));
+ RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[1]));
}
}
m_fMovingHiRotation += 0.05f;
@@ -130,47 +130,23 @@ CBoat::Render()
KeepWaterOutIndices[5] = 3;
switch (GetModelIndex()) {
case MI_SPEEDER:
- KeepWaterOutVertices[0].objVertex.x = -1.15f;
- KeepWaterOutVertices[0].objVertex.y = 3.61f;
- KeepWaterOutVertices[0].objVertex.z = 1.03f;
- KeepWaterOutVertices[1].objVertex.x = 1.15f;
- KeepWaterOutVertices[1].objVertex.y = 3.61f;
- KeepWaterOutVertices[1].objVertex.z = 1.03f;
- KeepWaterOutVertices[2].objVertex.x = -1.15f;
- KeepWaterOutVertices[2].objVertex.y = 0.06f;
- KeepWaterOutVertices[2].objVertex.z = 1.03f;
- KeepWaterOutVertices[3].objVertex.x = 1.15f;
- KeepWaterOutVertices[3].objVertex.y = 0.06f;
- KeepWaterOutVertices[3].objVertex.z = 1.03f;
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.15f, 3.61f, 1.03f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.15f, 3.61f, 1.03f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.15f, 0.06f, 1.03f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.15f, 0.06f, 1.03f);
break;
case MI_REEFER:
- KeepWaterOutVertices[2].objVertex.x = -1.9f;
- KeepWaterOutVertices[2].objVertex.y = 2.83f;
- KeepWaterOutVertices[2].objVertex.z = 1.0f;
- KeepWaterOutVertices[3].objVertex.x = 1.9f;
- KeepWaterOutVertices[3].objVertex.y = 2.83f;
- KeepWaterOutVertices[3].objVertex.z = 1.0f;
- KeepWaterOutVertices[0].objVertex.x = -1.66f;
- KeepWaterOutVertices[0].objVertex.y = -4.48f;
- KeepWaterOutVertices[0].objVertex.z = 0.83f;
- KeepWaterOutVertices[1].objVertex.x = 1.66f;
- KeepWaterOutVertices[1].objVertex.y = -4.48f;
- KeepWaterOutVertices[1].objVertex.z = 0.83f;
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.9f, 2.83f, 1.0f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.9f, 2.83f, 1.0f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.66f, -4.48f, 0.83f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.66f, -4.48f, 0.83f);
break;
case MI_PREDATOR:
default:
- KeepWaterOutVertices[0].objVertex.x = -1.45f;
- KeepWaterOutVertices[0].objVertex.y = 1.9f;
- KeepWaterOutVertices[0].objVertex.z = 0.96f;
- KeepWaterOutVertices[1].objVertex.x = 1.45f;
- KeepWaterOutVertices[1].objVertex.y = 1.9f;
- KeepWaterOutVertices[1].objVertex.z = 0.96f;
- KeepWaterOutVertices[2].objVertex.x = -1.45f;
- KeepWaterOutVertices[2].objVertex.y = -3.75f;
- KeepWaterOutVertices[2].objVertex.z = 0.96f;
- KeepWaterOutVertices[3].objVertex.x = 1.45f;
- KeepWaterOutVertices[3].objVertex.y = -3.75f;
- KeepWaterOutVertices[3].objVertex.z = 0.96f;
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.45f, 1.9f, 0.96f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.45f, 1.9f, 0.96f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.45f, -3.75f, 0.96f);
+ RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.45f, -3.75f, 0.96f);
break;
}
KeepWaterOutVertices[0].u = 0.0f;
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 4639f3e1..c7be3674 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -238,6 +238,7 @@ public:
bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }
bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; }
bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; }
+ bool IsBike(void) { return m_vehType == VEHICLE_TYPE_BIKE; }
void FlyingControl(eFlightModel flightModel);
void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
diff --git a/src/weapons/Explosion.cpp b/src/weapons/Explosion.cpp
index e99dc918..3d00052a 100644
--- a/src/weapons/Explosion.cpp
+++ b/src/weapons/Explosion.cpp
@@ -1,11 +1,29 @@
#include "common.h"
#include "patcher.h"
+#include "Automobile.h"
+#include "Bike.h"
+#include "Camera.h"
+#include "Coronas.h"
#include "DMAudio.h"
+#include "Entity.h"
+#include "EventList.h"
#include "Explosion.h"
+#include "General.h"
+#include "Fire.h"
+#include "Pad.h"
+#include "Particle.h"
+#include "PointLights.h"
+#include "Shadows.h"
+#include "Timer.h"
+#include "Vehicle.h"
+#include "WaterLevel.h"
+#include "World.h"
-CExplosion(&gaExplosion)[48] = *(CExplosion(*)[48])*(uintptr*)0x64E208;
+CExplosion(&gaExplosion)[NUM_EXPLOSIONS] = *(CExplosion(*)[NUM_EXPLOSIONS])*(uintptr*)0x64E208;
-WRAPPER void CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32) { EAXJMP(0x5591C0); }
+// these two were not initialised in original code, I'm really not sure what were they meant to be
+RwRGBA colMedExpl = { 0, 0, 0, 0 };
+RwRGBA colUpdate = { 0, 0, 0, 0 };
int AudioHandle = AEHANDLE_NONE;
@@ -15,26 +33,25 @@ CExplosion::Initialise()
debug("Initialising CExplosion...\n");
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
gaExplosion[i].m_ExplosionType = EXPLOSION_GRENADE;
- gaExplosion[i].m_vecPosition.x = 0.0f;
- gaExplosion[i].m_vecPosition.y = 0.0f;
- gaExplosion[i].m_vecPosition.z = 0.0f;
+ gaExplosion[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
gaExplosion[i].m_fRadius = 1.0f;
gaExplosion[i].m_fPropagationRate = 0.0f;
- gaExplosion[i].field_38 = 0;
+ gaExplosion[i].m_fZshift = 0.0f;
gaExplosion[i].m_pCreatorEntity = nil;
gaExplosion[i].m_pVictimEntity = nil;
gaExplosion[i].m_fStopTime = 0.0f;
- gaExplosion[i].m_bActive = false;
- gaExplosion[i].m_nStartTime = 0;
- gaExplosion[i].field_34 = 0;
+ gaExplosion[i].m_nIteration = 0;
+ gaExplosion[i].m_fStartTime = 0.0f;
+ gaExplosion[i].m_bIsBoat = false;
}
AudioHandle = DMAudio.CreateEntity(AUDIOTYPE_EXPLOSION, (void*)1);
if (AudioHandle >= 0)
- DMAudio.SetEntityStatus(AudioHandle, 1);
+ DMAudio.SetEntityStatus(AudioHandle, true);
debug("CExplosion ready\n");
}
-void CExplosion::Shutdown()
+void
+CExplosion::Shutdown()
{
debug("Shutting down CExplosion...\n");
if (AudioHandle >= 0) {
@@ -44,21 +61,22 @@ void CExplosion::Shutdown()
debug("CExplosion shut down\n");
}
+int8
+CExplosion::GetExplosionActiveCounter(uint8 id)
+{
+ return gaExplosion[id].m_nActiveCounter;
+}
+
void
-CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)
+CExplosion::ResetExplosionActiveCounter(uint8 id)
{
- for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
- if (gaExplosion[i].m_bActive) {
- if ((pos - gaExplosion[i].m_vecPosition).MagnitudeSqr() < SQR(radius))
- gaExplosion[i].m_bActive = false;
- }
- }
+ gaExplosion[id].m_nActiveCounter = 0;
}
-int8
-CExplosion::GetExplosionActiveCounter(uint8 id)
+uint8
+CExplosion::GetExplosionType(uint8 id)
{
- return gaExplosion[id].m_bActiveCounter;
+ return gaExplosion[id].m_ExplosionType;
}
CVector *
@@ -67,24 +85,357 @@ CExplosion::GetExplosionPosition(uint8 id)
return &gaExplosion[id].m_vecPosition;
}
-uint8
-CExplosion::GetExplosionType(uint8 id)
+bool
+CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime)
{
- return gaExplosion[id].m_ExplosionType;
+ CVector pPosn;
+ CVector posGround;
+
+ RwRGBA colorMedium = colMedExpl;
+ bool bDontExplode = false;
+ const RwRGBA color = { 160, 160, 160, 255 };
+ pPosn = pos;
+ pPosn.z += 5.0f;
+#ifdef FIX_BUGS
+ CShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 30000, 1.0f);
+#else
+ // last two arguments are swapped resulting in no shadow
+ CShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 1, 30000.0f);
+#endif
+
+ int n = 0;
+ while (gaExplosion[n].m_nIteration != 0 && n < ARRAY_SIZE(gaExplosion))
+ n++;
+ if (n == ARRAY_SIZE(gaExplosion))
+ return false;
+
+ CExplosion &explosion = gaExplosion[n];
+ explosion.m_ExplosionType = type;
+ explosion.m_vecPosition = pos;
+ explosion.m_fRadius = 1.0f;
+ explosion.m_fZshift = 0.0f;
+ explosion.m_pCreatorEntity = culprit;
+ if (culprit != nil)
+ culprit->RegisterReference(&explosion.m_pCreatorEntity);
+ explosion.m_pVictimEntity = explodingEntity;
+ if (explodingEntity != nil)
+ explodingEntity->RegisterReference(&explosion.m_pVictimEntity);
+ explosion.m_nIteration = 1;
+ explosion.m_nActiveCounter = 1;
+ explosion.m_bIsBoat = false;
+ explosion.m_nParticlesExpireTime = lifetime != 0 ? CTimer::GetTimeInMilliseconds() + lifetime : 0;
+ switch (type)
+ {
+ case EXPLOSION_GRENADE:
+ explosion.m_fRadius = 9.0f;
+ explosion.m_fPower = 300.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ posGround = pos;
+ posGround.z = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, nil);
+ CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
+ if (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f)
+ CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
+ break;
+ case EXPLOSION_MOLOTOV:
+ {
+ explosion.m_fRadius = 6.0f;
+ explosion.m_fPower = 0.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 3000;
+ explosion.m_fPropagationRate = 0.5f;
+ posGround = pos;
+ bool found;
+ posGround.z = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, &found);
+ if (found) {
+ float waterLevel;
+ if (CWaterLevel::GetWaterLevelNoWaves(posGround.x, posGround.y, posGround.z, &waterLevel)
+ && posGround.z < waterLevel
+ && waterLevel - 6.0f < posGround.z) // some subway/tunnels check?
+ bDontExplode = true;
+ else
+ gFireManager.StartFire(posGround, 1.8f, false);
+ }
+ else
+ bDontExplode = true;
+ break;
+ }
+ case EXPLOSION_ROCKET:
+ explosion.m_fRadius = 10.0f;
+ explosion.m_fPower = 300.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 250);
+ if (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f)
+ CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
+ break;
+ case EXPLOSION_CAR:
+ case EXPLOSION_CAR_QUICK:
+ explosion.m_fRadius = 9.0f;
+ explosion.m_fPower = 300.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 4250;
+ explosion.m_fPropagationRate = 0.5f;
+ explosion.m_fStartTime = CTimer::GetTimeInMilliseconds();
+ if (explosion.m_pVictimEntity != nil) {
+ if (explosion.m_pVictimEntity->IsVehicle() && ((CVehicle*)explosion.m_pVictimEntity)->IsBoat())
+ explosion.m_bIsBoat = true;
+ CEventList::RegisterEvent(EVENT_EXPLOSION, EVENT_ENTITY_VEHICLE, explosion.m_pVictimEntity, nil, 1000);
+ } else
+ CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);
+
+ if (explosion.m_pVictimEntity != nil && !explosion.m_bIsBoat) {
+ int rn = (CGeneral::GetRandomNumber() & 1) + 2;
+ for (int i = 0; i < rn; i++) {
+ CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, 3.5f, colMedExpl);
+ CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
+ }
+ CVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;
+ int32 component = CAR_WING_LR;
+
+ // miami leftover
+ if (veh->IsBike())
+ component = BIKE_FORKS_REAR;
+
+ if (veh->IsComponentPresent(component)) {
+ CVector componentPos;
+ veh->GetComponentWorldPosition(component, componentPos);
+ rn = (CGeneral::GetRandomNumber() & 1) + 1;
+ for (int i = 0; i < rn; i++)
+ CParticle::AddJetExplosion(componentPos, 1.4f, 0.0f);
+ }
+ }
+ break;
+ case EXPLOSION_HELI:
+ explosion.m_fRadius = 6.0f;
+ explosion.m_fPower = 300.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ explosion.m_fStartTime = CTimer::GetTimeInMilliseconds();
+ for (int i = 0; i < 10; i++) {
+ CVector randpos;
+ uint8 x, y, z;
+
+ x = CGeneral::GetRandomNumber();
+ y = CGeneral::GetRandomNumber();
+ z = CGeneral::GetRandomNumber();
+ randpos = pos + CVector(x - 128, y - 128, z - 128) / 20.0f;
+
+ CParticle::AddParticle(PARTICLE_EXPLOSION_MFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 2.5f, color);
+
+ x = CGeneral::GetRandomNumber();
+ y = CGeneral::GetRandomNumber();
+ z = CGeneral::GetRandomNumber();
+ randpos = pos + CVector(x - 128, y - 128, z - 128) / 20.0f;
+
+ CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 5.0f, color);
+
+ x = CGeneral::GetRandomNumber();
+ y = CGeneral::GetRandomNumber();
+ z = CGeneral::GetRandomNumber();
+ randpos = pos + CVector(x - 128, y - 128, z - 128) / 20.0f;
+
+ CParticle::AddJetExplosion(randpos, 1.4f, 3.0f);
+ }
+ CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);
+ break;
+ case EXPLOSION_MINE:
+ explosion.m_fRadius = 10.0f;
+ explosion.m_fPower = 150.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ posGround = pos;
+ //posGround.z =
+ CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
+ CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
+ break;
+ case EXPLOSION_BARREL:
+ explosion.m_fRadius = 7.0f;
+ explosion.m_fPower = 150.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ for (int i = 0; i < 6; i++) {
+ CVector randpos;
+ uint8 x, y, z;
+
+ x = CGeneral::GetRandomNumber();
+ y = CGeneral::GetRandomNumber();
+ z = CGeneral::GetRandomNumber();
+ randpos = CVector(x - 128, y - 128, z - 128);
+
+ randpos.x /= 50.0f;
+ randpos.y /= 50.0f;
+ randpos.z /= 25.0f;
+ randpos += pos;
+ CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colorMedium);
+ }
+ posGround = pos;
+ //posGround.z =
+ CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
+ CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
+ break;
+ case EXPLOSION_TANK_GRENADE:
+ explosion.m_fRadius = 10.0f;
+ explosion.m_fPower = 150.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ posGround = pos;
+ //posGround.z =
+ CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
+ CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
+ break;
+ case EXPLOSION_HELI_BOMB:
+ explosion.m_fRadius = 8.0f;
+ explosion.m_fPower = 50.0f;
+ explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
+ explosion.m_fPropagationRate = 0.5f;
+ posGround = pos;
+ //posGround.z =
+ CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
+ CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
+ break;
+ }
+ if (bDontExplode) {
+ explosion.m_nIteration = 0;
+ return false;
+ }
+
+ if (explosion.m_fPower != 0.0f && explosion.m_nParticlesExpireTime == 0)
+ CWorld::TriggerExplosion(pos, explosion.m_fRadius, explosion.m_fPower, culprit, (type == EXPLOSION_ROCKET || type == EXPLOSION_CAR_QUICK || type == EXPLOSION_MINE || type == EXPLOSION_BARREL || type == EXPLOSION_TANK_GRENADE || type == EXPLOSION_HELI_BOMB));
+
+ TheCamera.CamShake(0.6f, pos.x, pos.y, pos.z);
+ CPad::GetPad(0)->StartShake_Distance(300, 128, pos.x, pos.y, pos.z);
+ return true;
}
void
-CExplosion::ResetExplosionActiveCounter(uint8 id)
+CExplosion::Update()
{
- gaExplosion[id].m_bActiveCounter = 0;
+ RwRGBA color = colUpdate;
+ for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
+ CExplosion &explosion = gaExplosion[i];
+ if (explosion.m_nIteration == 0) continue;
+
+ if (explosion.m_nParticlesExpireTime != 0) {
+ if (CTimer::GetTimeInMilliseconds() > explosion.m_nParticlesExpireTime) {
+ explosion.m_nParticlesExpireTime = 0;
+ if (explosion.m_fPower != 0.0f)
+ CWorld::TriggerExplosion(explosion.m_vecPosition, explosion.m_fRadius, explosion.m_fPower, explosion.m_pCreatorEntity, (explosion.m_ExplosionType == EXPLOSION_ROCKET || explosion.m_ExplosionType == EXPLOSION_CAR_QUICK || explosion.m_ExplosionType == EXPLOSION_MINE || explosion.m_ExplosionType == EXPLOSION_BARREL || explosion.m_ExplosionType == EXPLOSION_TANK_GRENADE || explosion.m_ExplosionType == EXPLOSION_HELI_BOMB));
+ }
+ } else {
+ explosion.m_fRadius += explosion.m_fPropagationRate * CTimer::GetTimeStep();
+ int32 someTime = explosion.m_fStopTime - CTimer::GetTimeInMilliseconds();
+ switch (explosion.m_ExplosionType)
+ {
+ case EXPLOSION_GRENADE:
+ case EXPLOSION_ROCKET:
+ case EXPLOSION_HELI:
+ case EXPLOSION_MINE:
+ case EXPLOSION_BARREL:
+ if (CTimer::GetFrameCounter() & 1) {
+ CPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 20.0f, 1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true);
+ CCoronas::RegisterCorona((uintptr)&explosion, 255, 255, 200, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ } else
+ CCoronas::RegisterCorona((uintptr)&explosion, 128, 128, 100, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ CCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 30, 25, 255, explosion.m_vecPosition, explosion.m_fRadius, 120.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ break;
+ case EXPLOSION_MOLOTOV:
+ CWorld::SetPedsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);
+ CWorld::SetCarsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);
+ if (explosion.m_nIteration < 10) {
+ if (explosion.m_nIteration == 1) {
+ CVector point1 = explosion.m_vecPosition;
+ point1.z += 5.0f;
+ CColPoint colPoint;
+ CEntity *pEntity;
+ CWorld::ProcessVerticalLine(point1, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil);
+ explosion.m_fZshift = colPoint.point.z;
+ }
+ float ff = ((float)explosion.m_nIteration * 0.55f);
+ for (int i = 0; i < 5 * ff; i++) {
+ float angle = CGeneral::GetRandomNumber() / 256.0f * 6.28f;
+
+ CVector pos = explosion.m_vecPosition;
+ pos.x += ff * Sin(angle);
+ pos.y += ff * Cos(angle);
+ pos.z += 5.0f; // what is the point of this?
+
+ pos.z = explosion.m_fZshift + 0.5f;
+ CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));
+ }
+ }
+ break;
+ case EXPLOSION_CAR:
+ case EXPLOSION_CAR_QUICK:
+ if (someTime >= 3500) {
+ if (explosion.m_pVictimEntity != nil && !explosion.m_bIsBoat) {
+ if ((CGeneral::GetRandomNumber() & 0xF) == 0) {
+ CVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;
+ uint8 component = CAR_WING_LR;
+
+ // miami leftover
+ if (veh->IsBike())
+ component = BIKE_FORKS_REAR;
+
+ if (veh->IsComponentPresent(component)) {
+ CVector componentPos;
+ veh->GetComponentWorldPosition(component, componentPos);
+ CParticle::AddJetExplosion(componentPos, 1.5f, 0.0f);
+ }
+ }
+ if (CTimer::GetTimeInMilliseconds() > explosion.m_fStartTime) {
+ explosion.m_fStartTime = CTimer::GetTimeInMilliseconds() + 125 + (CGeneral::GetRandomNumber() & 0x7F);
+ CVector pos = explosion.m_pVictimEntity->GetPosition();
+ for (int i = 0; i < (CGeneral::GetRandomNumber() & 1) + 1; i++) {
+ CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 3.5f, color);
+ CParticle::AddParticle(PARTICLE_EXPLOSION_LARGE, pos, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
+ }
+ }
+ }
+ if (CTimer::GetFrameCounter() & 1) {
+ CPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 15.0f, 1.0f, 0.0f, 0.0f, CPointLights::FOG_NONE, true);
+ CCoronas::RegisterCorona((uintptr)&explosion, 200, 100, 0, 255, explosion.m_vecPosition, 6.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ } else
+ CCoronas::RegisterCorona((uintptr)&explosion, 128, 0, 0, 255, explosion.m_vecPosition, 8.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+
+ CCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 15, 0, 255, explosion.m_vecPosition, explosion.m_fRadius, 80.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ } else if (explosion.m_nIteration & 1) {
+ if (explosion.m_pVictimEntity != nil)
+ CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.8f), color);
+ CVector pos = explosion.m_vecPosition;
+ pos.z += 1.0f;
+ CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, pos, CVector(0.0f, 0.0f, 0.11f), nil, CGeneral::GetRandomNumberInRange(0.5f, 2.0f), color);
+ }
+ break;
+ case EXPLOSION_TANK_GRENADE:
+ case EXPLOSION_HELI_BOMB:
+ if (explosion.m_nIteration < 5) {
+ float ff = ((float)explosion.m_nIteration * 0.65f);
+ for (int i = 0; i < 10 * ff; i++) {
+ uint8 x = CGeneral::GetRandomNumber(), y = CGeneral::GetRandomNumber(), z = CGeneral::GetRandomNumber();
+ CVector pos(x - 128, y - 128, (z % 128) + 1);
+
+ pos.Normalise();
+ pos *= ff / 5.0f;
+ pos += explosion.m_vecPosition;
+ pos.z += 0.5f;
+ CParticle::AddParticle(PARTICLE_EXPLOSION_LARGE, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));
+ }
+ }
+ break;
+ }
+ if (someTime > 0)
+ explosion.m_nIteration++;
+ else
+ explosion.m_nIteration = 0;
+ }
+ }
}
bool
-CExplosion::TestForExplosionInArea(eExplosionType a1, float x1, float x2, float y1, float y2, float z1, float z2)
+CExplosion::TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2)
{
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
- if (gaExplosion[i].m_bActive) {
- if (a1 == gaExplosion[i].m_ExplosionType) {
+ if (gaExplosion[i].m_nIteration != 0) {
+ if (type == gaExplosion[i].m_ExplosionType) {
if (gaExplosion[i].m_vecPosition.x >= x1 && gaExplosion[i].m_vecPosition.x <= x2) {
if (gaExplosion[i].m_vecPosition.y >= y1 && gaExplosion[i].m_vecPosition.y <= y2) {
if (gaExplosion[i].m_vecPosition.z >= z1 && gaExplosion[i].m_vecPosition.z <= z2)
@@ -97,13 +448,26 @@ CExplosion::TestForExplosionInArea(eExplosionType a1, float x1, float x2, float
return false;
}
+void
+CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)
+{
+ for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
+ if (gaExplosion[i].m_nIteration != 0) {
+ if ((pos - gaExplosion[i].m_vecPosition).MagnitudeSqr() < SQR(radius))
+ gaExplosion[i].m_nIteration = 0;
+ }
+ }
+}
+
STARTPATCHES
InjectHook(0x559030, &CExplosion::Initialise, PATCH_JUMP);
InjectHook(0x559100, &CExplosion::Shutdown, PATCH_JUMP);
- InjectHook(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, PATCH_JUMP);
InjectHook(0x559140, &CExplosion::GetExplosionActiveCounter, PATCH_JUMP);
- InjectHook(0x5591A0, &CExplosion::GetExplosionPosition, PATCH_JUMP);
- InjectHook(0x559180, &CExplosion::GetExplosionType, PATCH_JUMP);
InjectHook(0x559160, &CExplosion::ResetExplosionActiveCounter, PATCH_JUMP);
+ InjectHook(0x559180, &CExplosion::GetExplosionType, PATCH_JUMP);
+ InjectHook(0x5591A0, &CExplosion::GetExplosionPosition, PATCH_JUMP);
+ InjectHook(0x5591C0, &CExplosion::AddExplosion, PATCH_JUMP);
+ InjectHook(0x55A0C0, &CExplosion::Update, PATCH_JUMP);
InjectHook(0x55AC80, &CExplosion::TestForExplosionInArea, PATCH_JUMP);
+ InjectHook(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/weapons/Explosion.h b/src/weapons/Explosion.h
index e6ef9496..45e2d5bb 100644
--- a/src/weapons/Explosion.h
+++ b/src/weapons/Explosion.h
@@ -26,25 +26,24 @@ class CExplosion
CEntity *m_pCreatorEntity;
CEntity *m_pVictimEntity;
float m_fStopTime;
- bool m_bActive;
- int8 m_bActiveCounter;
- int32 m_nStartTime;
+ uint8 m_nIteration;
+ uint8 m_nActiveCounter;
+ float m_fStartTime;
uint32 m_nParticlesExpireTime;
float m_fPower;
- int32 field_34;
- int32 field_38;
+ bool m_bIsBoat;
+ float m_fZshift;
public:
static void Initialise();
static void Shutdown();
- static void AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type,
- const CVector &pos, uint32);
-
static int8 GetExplosionActiveCounter(uint8 id);
- static CVector *GetExplosionPosition(uint8 id);
- static uint8 GetExplosionType(uint8 id);
static void ResetExplosionActiveCounter(uint8 id);
- static void RemoveAllExplosionsInArea(CVector, float);
- static bool TestForExplosionInArea(eExplosionType, float, float, float, float, float, float);
+ static uint8 GetExplosionType(uint8 id);
+ static CVector *GetExplosionPosition(uint8 id);
+ static bool AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime);
+ static void Update();
+ static bool TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2);
+ static void RemoveAllExplosionsInArea(CVector pos, float radius);
};
-extern CExplosion (&gaExplosion)[48]; \ No newline at end of file
+extern CExplosion (&gaExplosion)[NUM_EXPLOSIONS]; \ No newline at end of file