From 0544beb00d5eaf6c974bb7ebcf1f871e3ce94cfb Mon Sep 17 00:00:00 2001
From: Sergeanur <s.anureev@yandex.ua>
Date: Wed, 11 Aug 2021 08:15:30 +0300
Subject: [PATCH] Add sprite to the waypoint marker

---
 src/core/Radar.cpp  | 62 +++++++++++++++++++++++++++++++++++++++++----
 src/core/Radar.h    |  4 +++
 src/fakerw/fake.cpp |  4 +--
 src/fakerw/rwcore.h |  8 ++++++
 4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp
index ff9231c6..faf11387 100644
--- a/src/core/Radar.cpp
+++ b/src/core/Radar.cpp
@@ -66,6 +66,9 @@ CSprite2d CRadar::RadioVCPRSprite;
 CSprite2d CRadar::RadioEspantosoSprite;
 CSprite2d CRadar::RadioEmotionSprite;
 CSprite2d CRadar::RadioWaveSprite;
+#ifdef MAP_ENHANCEMENTS
+CSprite2d CRadar::WaypointSprite;
+#endif
 
 CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { 
 	nil,
@@ -107,7 +110,10 @@ CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = {
 	&RadioVCPRSprite,
 	&RadioEspantosoSprite,
 	&RadioEmotionSprite,
-	&RadioWaveSprite
+	&RadioWaveSprite,
+#ifdef MAP_ENHANCEMENTS
+	&WaypointSprite,
+#endif
 };
 
 // Why this doesn't coincide with world coordinates i don't know
@@ -819,6 +825,9 @@ void CRadar::DrawRadarSection(int32 x, int32 y)
 
 void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha)
 {
+#ifdef MAP_ENHANCEMENTS
+	if(sprite == RADAR_SPRITE_WAYPOINT) alpha = 255;
+#endif
 	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));
 
 	if (FrontEndMenuManager.m_bMenuMapActive) {
@@ -936,6 +945,9 @@ const char* gRadarTexNames[] = {
 void
 CRadar::Initialise()
 {
+#ifdef MAP_ENHANCEMENTS
+	TargetMarkerId = -1;
+#endif
 	for (int i = 0; i < NUMRADARBLIPS; i++) {
 		ms_RadarTrace[i].m_BlipIndex = 1;
 		SetRadarMarkerState(i, false);
@@ -1084,6 +1096,43 @@ CRadar::LoadTextures()
 	RadioEspantosoSprite.SetTexture("REspantoso");
 	RadioEmotionSprite.SetTexture("REmotion");
 	RadioWaveSprite.SetTexture("RWave");
+#ifdef MAP_ENHANCEMENTS
+	WaypointSprite.SetTexture("radar_waypoint");
+	if(!WaypointSprite.m_pTexture) {
+		// create the texture if it's missing in TXD
+#define WAYPOINT_R (255)
+#define WAYPOINT_G (72)
+#define WAYPOINT_B (77)
+
+		RwRaster *raster = RwRasterCreate(16, 16, 0, rwRASTERTYPETEXTURE | rwRASTERFORMAT8888);
+
+		RwUInt32 *pixels = (RwUInt32 *)RwRasterLock(raster, 0, rwRASTERLOCKWRITE);
+		for(int x = 0; x < 16; x++)
+			for(int y = 0; y < 16; y++)
+			{
+				int x2 = x < 8 ? x : 7 - (x & 7);
+				int y2 = y < 8 ? y : 7 - (y & 7);
+				if ((y2 >= 4 && x2 >= 4) // square in the center is transparent
+					|| (x2 < 2 && y2 == 0) // two pixels on each side of first/last line are transparent
+					|| (x2 < 1 && y2 == 1)) // one pixel on each side of second to first/last line is transparent
+					pixels[x + y * 16] = 0;
+				else if((x2 == 2 && y2 >= 2)|| (y2 == 2 && x2 >= 2) )// colored square inside
+#ifdef RW_GL3
+					pixels[x + y * 16] = WAYPOINT_R | (WAYPOINT_G << 8) | (WAYPOINT_B << 16) | (255 << 24);
+#else
+					pixels[x + y * 16] = WAYPOINT_B | (WAYPOINT_G << 8) | (WAYPOINT_R << 16) | (255 << 24);
+#endif
+				else
+					pixels[x + y * 16] = 0xFF000000; // black
+			}
+		RwRasterUnlock(raster);
+		WaypointSprite.m_pTexture = RwTextureCreate(raster);
+		RwTextureSetFilterMode(WaypointSprite.m_pTexture, rwFILTERLINEAR);
+#undef WAYPOINT_R
+#undef WAYPOINT_G
+#undef WAYPOINT_B
+	}
+#endif
 	CTxdStore::PopCurrentTxd();
 }
 
@@ -1278,6 +1327,9 @@ void CRadar::Shutdown()
 	RadioEspantosoSprite.Delete();
 	RadioEmotionSprite.Delete();
 	RadioWaveSprite.Delete();
+#ifdef MAP_ENHANCEMENTS
+	WaypointSprite.Delete();
+#endif
 	RemoveRadarSections();
 }
 
@@ -1439,12 +1491,12 @@ CRadar::ToggleTargetMarker(float x, float y)
 {
 	if (TargetMarkerId == -1) {
 		int nextBlip;
-		for (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {
+		for (nextBlip = NUMRADARBLIPS-1; nextBlip >= 0; nextBlip--) {
 			if (!ms_RadarTrace[nextBlip].m_bInUse)
 				break;
 		}
 		
-		if (nextBlip == NUMRADARBLIPS)
+		if (nextBlip == 0)
 			return;
 			
 		ms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD;
@@ -1452,14 +1504,14 @@ CRadar::ToggleTargetMarker(float x, float y)
 		ms_RadarTrace[nextBlip].m_bDim = 0;
 		ms_RadarTrace[nextBlip].m_bInUse = 1;
 		ms_RadarTrace[nextBlip].m_Radius = 1.0f;
-		CVector pos(x, y, CWorld::FindGroundZForCoord(x,y));
+		CVector pos(x, y, 0.0f/*CWorld::FindGroundZForCoord(x,y)*/);
 		TargetMarkerPos = pos;
 		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;
+		ms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_WAYPOINT;
 		TargetMarkerId = CRadar::GetNewUniqueBlipIndex(nextBlip);
 	} else {
 		ClearBlip(TargetMarkerId);
diff --git a/src/core/Radar.h b/src/core/Radar.h
index b01a5d04..afb37fe4 100644
--- a/src/core/Radar.h
+++ b/src/core/Radar.h
@@ -93,6 +93,9 @@ enum eRadarSprite
 	RADAR_SPRITE_RADIO_ESPANTOSO,
 	RADAR_SPRITE_RADIO_EMOTION,
 	RADAR_SPRITE_RADIO_WAVE,
+#ifdef MAP_ENHANCEMENTS
+	RADAR_SPRITE_WAYPOINT,
+#endif
 
 	RADAR_SPRITE_COUNT
 };
@@ -233,6 +236,7 @@ public:
 	static int16 MapLegendCounter;
 
 #ifdef MAP_ENHANCEMENTS
+	static CSprite2d WaypointSprite;
 	static int TargetMarkerId;
 	static CVector TargetMarkerPos;
 #endif
diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp
index e51a0821..ee779788 100644
--- a/src/fakerw/fake.cpp
+++ b/src/fakerw/fake.cpp
@@ -235,8 +235,8 @@ RwRaster    *RwRasterGetCurrentContext(void) { return Raster::getCurrentContext(
 RwBool       RwRasterClear(RwInt32 pixelValue);
 RwBool       RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue);
 RwRaster    *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags);
-RwUInt8     *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode);
-RwRaster    *RwRasterUnlock(RwRaster * raster);
+RwUInt8     *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode) { return raster->lock(level, lockMode); }
+RwRaster    *RwRasterUnlock(RwRaster * raster) { raster->unlock(0); return raster; }
 RwUInt8     *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode);
 RwRaster    *RwRasterUnlockPalette(RwRaster * raster);
 RwInt32      RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
diff --git a/src/fakerw/rwcore.h b/src/fakerw/rwcore.h
index e5d21865..ab0a719f 100644
--- a/src/fakerw/rwcore.h
+++ b/src/fakerw/rwcore.h
@@ -104,6 +104,14 @@ enum RwRasterFormat
 	rwRASTERFORMATMASK = 0xff00
 };
 
+enum RwRasterLockMode
+{
+    rwRASTERLOCKWRITE = rw::Raster::LOCKWRITE,
+    rwRASTERLOCKREAD = rw::Raster::LOCKREAD,
+    rwRASTERLOCKNOFETCH = rw::Raster::LOCKNOFETCH,
+    rwRASTERLOCKRAW = rw::Raster::LOCKRAW,
+};
+
 enum RwRasterFlipMode
 {
 	rwRASTERFLIPDONTWAIT = 0,