├── .gitattributes ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── Android.mk ├── Application.mk ├── LICENSE └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: AML Mod Compiler 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Checkout repository... 15 | uses: actions/checkout@v3 16 | with: 17 | submodules: recursive 18 | 19 | - name: Setup SSH keys... 20 | uses: webfactory/ssh-agent@v0.8.0 21 | with: 22 | ssh-private-key: | 23 | ${{ secrets.SSH }} 24 | 25 | - name: Download AndroidModLoader`s mod template... 26 | uses: wei/wget@v1 27 | with: 28 | args: -O ./AML_src.zip https://github.com/RusJJ/AndroidModLoader/archive/refs/heads/main.zip 29 | 30 | - name: Install AndroidModLoader`s mod template... 31 | run: | 32 | unzip ./AML_src.zip 33 | mv ./AndroidModLoader-main/mod ./mod 34 | 35 | - name: Get GTA:SA structures file (private)... 36 | run: | 37 | git clone ssh://git@github.com/RusJJ/GTASAAndroid_Structs.git ./structs 38 | mv ./structs/* ./ 39 | 40 | - name: Install Android NDK (r25c)... 41 | uses: nttld/setup-ndk@v1.2.0 42 | with: 43 | ndk-version: r25c 44 | local-cache: true 45 | 46 | - name: Build the code... 47 | run: ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk NDK_DEBUG=0 -j12 48 | 49 | - name: Upload the mod! 50 | uses: actions/upload-artifact@v3 51 | with: 52 | name: compiled-mod.zip 53 | path: ./libs 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | 400 | # Own 401 | mod/ 402 | libs/ 403 | *.bak 404 | build.ps1 405 | ndkpath.txt 406 | GTASA_ENUMS.h 407 | GTASA_STRUCTS.h 408 | RW_STRUCTS.h 409 | .vscode/settings.json 410 | GTASA_STRUCTS_210.h 411 | RW_STRUCTS_210.h 412 | GTASA_DECLS.h 413 | GTA_SHARED.h 414 | GTASADE_STRUCTS.h 415 | GTAVC_ENUMS.h 416 | GTAVC_STRUCTS.h 417 | GTAVC_STRUCTS_112.h 418 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "AArch64_ModHelper"] 2 | path = AArch64_ModHelper 3 | url = https://github.com/RusJJ/AArch64_ModHelper 4 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_CPP_EXTENSION := .cpp .cc 5 | ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) 6 | LOCAL_MODULE := GPS 7 | else 8 | LOCAL_MODULE := GPS64 9 | endif 10 | LOCAL_SRC_FILES := main.cpp mod/logger.cpp mod/config.cpp 11 | LOCAL_CFLAGS += -O2 -mfloat-abi=softfp -DNDEBUG 12 | LOCAL_C_INCLUDES += ./include 13 | LOCAL_LDLIBS += -llog 14 | include $(BUILD_SHARED_LIBRARY) -------------------------------------------------------------------------------- /Application.mk: -------------------------------------------------------------------------------- 1 | APP_STL := c++_static 2 | APP_ABI := armeabi-v7a arm64-v8a 3 | APP_OPTIM := release -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014 Dmitry K. <> 2 | Copyright (c) 2013-2014 fastman92 <> 3 | Copyright (c) 2014 LINK/2012 4 | Copyright (c) 2022 RusJJ <> 5 | 6 | This software is provided 'as-is', without any express or implied 7 | warranty. In no event will the authors be held liable for any damages 8 | arising from the use of this software. 9 | 10 | Permission is granted to anyone to use this software for any purpose, 11 | including commercial applications, and to alter it and redistribute it 12 | freely, subject to the following restrictions: 13 | 14 | 1. The origin of this software must not be misrepresented; you must not 15 | claim that you wrote the original software. If you use this software 16 | in a product, an acknowledgment in the product documentation would be 17 | appreciated but is not required. 18 | 19 | 2. Altered source versions must be plainly marked as such, and must not be 20 | misrepresented as being the original software. 21 | 22 | 3. This notice may not be removed or altered from any source 23 | distribution. 24 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef AML32 6 | #include "GTASA_STRUCTS.h" 7 | #include "AArch64_ModHelper/Thumbv7_ASMHelper.h" 8 | using namespace ThumbV7; 9 | #else 10 | #include "GTASA_STRUCTS_210.h" 11 | #include "AArch64_ModHelper/ARMv8_ASMHelper.h" 12 | using namespace ARMv8; 13 | #endif 14 | 15 | #define MAX_NODE_POINTS 50000 16 | 17 | #define GPS_LINE_R 235 18 | #define GPS_LINE_G 212 19 | #define GPS_LINE_B 0 20 | #define GPS_LINE_A 255 21 | 22 | MYMODCFG(net.dk22pac.rusjj.gps, GTA:SA GPS, 1.4.1, DK22Pac & JuniorDjjr & juicermv & RusJJ) 23 | NEEDGAME(com.rockstargames.gtasa) 24 | 25 | CVector2D g_vecUnderRadar(0.0, -1.05); // 0 26 | CVector2D g_vecAboveRadar(0.0, 1.05); // 1 27 | CVector2D g_vecLeftRadar(-1.05, 0.0); // 2 28 | CVector2D g_vecRightRadar(1.05, 0.0); // 3 29 | eFontAlignment g_nTextAlignment; 30 | 31 | // Patched 32 | CNodeAddress aNodesToBeCleared_NEW[MAX_NODE_POINTS]; 33 | 34 | // Savings 35 | uintptr_t pGTASA; 36 | void* hGTASA; 37 | CNodeAddress resultNodes[MAX_NODE_POINTS]; 38 | CVector2D nodePoints[MAX_NODE_POINTS]; 39 | RwOpenGLVertex lineVerts[MAX_NODE_POINTS * 4] {0}; 40 | float gpsDistance; 41 | CVector2D gpsDistanceTextPos; 42 | CRect emptyRect, radarRect; 43 | unsigned int gpsLineColor = RWRGBALONG(GPS_LINE_R, GPS_LINE_G, GPS_LINE_B, GPS_LINE_A); 44 | unsigned int maxLoadedPathNodes; 45 | float lineWidth = 3.5f, textOffset, textScale, flMenuMapScaling; 46 | CVector2D vecTextOffset; 47 | tRadarTrace* pTrace; 48 | bool *ExtraPathsNeeded; 49 | CVector *ExtraPathPos; 50 | uint8_t *ToBeStreamed; 51 | 52 | // Config 53 | ConfigEntry* pCfgClosestMaxGPSDistance; 54 | ConfigEntry* pCfgGPSMaxPathNodesLoaded; 55 | ConfigEntry* pCfgGPSLineColorRGB; 56 | ConfigEntry* pCfgGPSDrawDistance; 57 | ConfigEntry* pCfgGPSDrawDistancePosition; 58 | ConfigEntry* pCfgGPSDrawDistanceTextScale; 59 | ConfigEntry* pCfgGPSDrawDistanceTextOffset; 60 | bool bAllowBMX, bAllowBoat, bAllowMission, bImperialUnits, bRespectLanesDirection; 61 | 62 | // Game Vars 63 | RsGlobalType* RsGlobal; 64 | tRadarTrace* pRadarTrace; 65 | MobileMenu* gMobileMenu; 66 | CPathFind* ThePaths; 67 | ScriptHandle TargetBlip {0}; 68 | float* NearScreenZ; 69 | float* RecipNearClip; 70 | bool *m_UserPause, *m_CodePause; 71 | CWidget** aWidgets; 72 | CPickup* aPickUps; 73 | uint32_t *m_snTimeInMilliseconds, *m_snPreviousTimeInMilliseconds; 74 | 75 | // Game Funcs 76 | CPlayerPed* (*FindPlayerPed)(int); 77 | CVector& (*FindPlayerCoors)(CVector*, int); 78 | float (*FindGroundZForCoord)(float, float); 79 | int (*DoPathSearch)(CPathFind*, unsigned char, CVector, CNodeAddress, CVector, CNodeAddress*, short*, int, float*, float, CNodeAddress*, float, bool, CNodeAddress, bool, bool); 80 | void (*TransformRadarPointToRealWorldSpace)(CVector2D& out, CVector2D const& in); 81 | void (*TransformRealWorldPointToRadarSpace)(CVector2D& out, CVector2D const& in); 82 | void (*TransformRadarPointToScreenSpace)(CVector2D& out, CVector2D const& in); 83 | void (*LimitRadarPoint)(CVector2D& in); 84 | void (*LimitToMap)(float*, float*); 85 | void (*RwRenderStateSet)(RwRenderState, void*); 86 | void (*RwIm2DRenderPrimitive)(RwPrimitiveType, RwOpenGLVertex*, int); 87 | void (*SetScissorRect)(CRect&); 88 | void (*ClearRadarBlip)(uint32_t); 89 | bool (*IsOnAMission)(); 90 | CPed* (*GetPoolPed)(int); 91 | CVehicle* (*GetPoolVeh)(int); 92 | CObject* (*GetPoolObj)(int); 93 | void (*RequestModel)(int, int); 94 | void (*RemoveModel)(int); 95 | void (*LoadAllRequestedModels)(bool); 96 | void (*MarkRegionsForCoors)(CPathFind*, CVector, float); 97 | void (*RequestCollision)(CVector*, int); 98 | 99 | void (*FontSetOrientation)(unsigned char); 100 | void (*FontSetColor)(CRGBA*); 101 | void (*FontSetBackground)(unsigned char, unsigned char); 102 | void (*FontSetWrapx)(float); 103 | void (*FontSetStyle)(unsigned char); 104 | void (*FontSetScale)(float); 105 | void (*FontSetProportional)(unsigned char); 106 | void (*FontSetDropShadowPosition)(char); 107 | void (*FontSetEdge)(char); 108 | void (*FontSetDropColor)(CRGBA*); 109 | void (*FontPrintString)(float, float, unsigned short*); 110 | void (*AsciiToGxtChar)(const char* txt, unsigned short* ret); 111 | void (*RenderFontBuffer)(void); 112 | 113 | 114 | 115 | inline bool IsRadarVisible() 116 | { 117 | CWidget* radar = aWidgets[161]; 118 | return (radar != NULL && radar->enabled); 119 | } 120 | inline uint8_t GetRadarVisibility() 121 | { 122 | CWidget* radar = aWidgets[161]; 123 | return (radar) ? radar->color.a : 0; 124 | } 125 | inline bool IsGamePaused() { return *m_CodePause || *m_UserPause; }; 126 | inline bool IsRGBValue(int value) { return value >= 0 && value <= 255; } 127 | void InitializeConfigValues() 128 | { 129 | textOffset = (8.0f * (float)RsGlobal->maximumHeight) / 448.0f; 130 | textScale = (0.4f * ((float)RsGlobal->maximumWidth) / 640.0f) * pCfgGPSDrawDistanceTextScale->GetFloat(); 131 | flMenuMapScaling = (float)RsGlobal->maximumHeight / 448.0f; 132 | 133 | if(sscanf(pCfgGPSDrawDistanceTextOffset->GetString(), "%f %f", &vecTextOffset.x, &vecTextOffset.y) != 2) 134 | { 135 | vecTextOffset.x = vecTextOffset.y = 0; 136 | } 137 | } 138 | 139 | RwUInt32 GetTraceColor(eBlipColour clr, bool friendly = false) 140 | { 141 | switch(clr) 142 | { 143 | case BLIP_COLOUR_RED: 144 | return RWRGBALONG(127, 0, 0, 255); 145 | case BLIP_COLOUR_GREEN: 146 | return RWRGBALONG( 0, 127, 0, 255); 147 | case BLIP_COLOUR_BLUE: 148 | return RWRGBALONG( 0, 0, 127, 255); 149 | case BLIP_COLOUR_WHITE: 150 | return RWRGBALONG(127, 127, 127, 255); 151 | case BLIP_COLOUR_YELLOW: 152 | return RWRGBALONG(200, 200, 0, 255); 153 | case BLIP_COLOUR_PURPLE: 154 | return RWRGBALONG(127, 0, 127, 255); 155 | case BLIP_COLOUR_CYAN: 156 | return RWRGBALONG( 0, 127, 127, 255); 157 | case BLIP_COLOUR_THREAT: 158 | return friendly ? RWRGBALONG(0, 0, 127, 255) : RWRGBALONG(127, 0, 0, 255); 159 | case BLIP_COLOUR_DESTINATION: 160 | return RWRGBALONG(200, 200, 0, 255); 161 | 162 | default: 163 | CRGBA a((int)clr); 164 | return RWRGBALONG(a.r, a.g, a.b, 255); 165 | } 166 | } 167 | 168 | CRGBA rgbclr; 169 | CRGBA& GetTraceTextColor(eBlipColour clr, bool friendly = false) 170 | { 171 | switch(clr) 172 | { 173 | case BLIP_COLOUR_RED: 174 | return rgbclr = CRGBA(127,0,0,255); 175 | case BLIP_COLOUR_GREEN: 176 | return rgbclr = CRGBA(0,127,0,255); 177 | case BLIP_COLOUR_BLUE: 178 | return rgbclr = CRGBA(0,0,127,255); 179 | case BLIP_COLOUR_WHITE: 180 | return rgbclr = CRGBA(127,127,127,255); 181 | case BLIP_COLOUR_YELLOW: 182 | return rgbclr = CRGBA(200,200,0,255); 183 | case BLIP_COLOUR_PURPLE: 184 | return rgbclr = CRGBA(127,0,127,255); 185 | case BLIP_COLOUR_CYAN: 186 | return rgbclr = CRGBA(0,127,127,255); 187 | case BLIP_COLOUR_THREAT: 188 | return friendly ? rgbclr = CRGBA(0,0,127,255) : rgbclr = CRGBA(127,0,0,255); 189 | case BLIP_COLOUR_DESTINATION: 190 | return rgbclr = CRGBA(200,200,0,255); 191 | 192 | default: 193 | rgbclr = CRGBA((int)clr); 194 | rgbclr.a = 255; 195 | return rgbclr; 196 | } 197 | } 198 | 199 | void SetDistanceTextValues() 200 | { 201 | CVector2D posn; 202 | TransformRadarPointToScreenSpace(posn, CVector2D(-1.0f, -1.0f)); 203 | radarRect.left = posn.x + 2.0f; 204 | radarRect.bottom = posn.y - 2.0f; 205 | TransformRadarPointToScreenSpace(posn, CVector2D(1.0f, 1.0f)); 206 | radarRect.right = posn.x - 2.0f; 207 | radarRect.top = posn.y + 2.0f; 208 | 209 | switch(pCfgGPSDrawDistancePosition->GetInt()) 210 | { 211 | default: 212 | case 0: // Under 213 | g_nTextAlignment = ALIGN_CENTER; 214 | TransformRadarPointToScreenSpace(gpsDistanceTextPos, g_vecUnderRadar); 215 | gpsDistanceTextPos += vecTextOffset; 216 | gpsDistanceTextPos.y += textOffset; 217 | break; 218 | 219 | case 1: // Above 220 | g_nTextAlignment = ALIGN_CENTER; 221 | TransformRadarPointToScreenSpace(gpsDistanceTextPos, g_vecAboveRadar); 222 | gpsDistanceTextPos += vecTextOffset; 223 | gpsDistanceTextPos.y -= textOffset; 224 | break; 225 | 226 | case 2: // Left 227 | g_nTextAlignment = ALIGN_RIGHT; 228 | TransformRadarPointToScreenSpace(gpsDistanceTextPos, g_vecLeftRadar); 229 | gpsDistanceTextPos += vecTextOffset; 230 | gpsDistanceTextPos.x -= textOffset; 231 | break; 232 | 233 | case 3: // Right 234 | g_nTextAlignment = ALIGN_LEFT; 235 | TransformRadarPointToScreenSpace(gpsDistanceTextPos, g_vecRightRadar); 236 | gpsDistanceTextPos += vecTextOffset; 237 | gpsDistanceTextPos.x += textOffset; 238 | break; 239 | 240 | case 4: // Custom 241 | gpsDistanceTextPos = vecTextOffset; 242 | break; 243 | } 244 | } 245 | 246 | inline void Setup2DVertex(RwOpenGLVertex &vertex, float x, float y, RwUInt32 color) 247 | { 248 | vertex.pos.x = x; 249 | vertex.pos.y = y; 250 | vertex.pos.z = *NearScreenZ + 0.0001f; 251 | vertex.rhw = *RecipNearClip; 252 | vertex.color = color; 253 | } 254 | 255 | inline bool IsBMXNaviAllowed(CPlayerPed* player) 256 | { 257 | return bAllowBMX || 258 | (!bAllowBMX && player->m_pVehicle->m_nVehicleSubType != VEHICLE_TYPE_BMX); 259 | } 260 | 261 | inline bool IsInSupportedVehicle(CPlayerPed* player) 262 | { 263 | return (player && 264 | player->m_pVehicle && 265 | player->m_PedFlags.bInVehicle && 266 | player->m_pVehicle->m_nVehicleSubType != VEHICLE_TYPE_PLANE && 267 | player->m_pVehicle->m_nVehicleSubType != VEHICLE_TYPE_HELI && 268 | IsBMXNaviAllowed(player)); 269 | } 270 | 271 | inline bool LaneDirectionRespected() 272 | { 273 | return bRespectLanesDirection; 274 | } 275 | 276 | inline bool IsBoatNaviAllowed() 277 | { 278 | return bAllowBoat; 279 | } 280 | 281 | char text[24]; 282 | unsigned short* textGxt = new unsigned short[0xFF]; 283 | DECL_HOOK(void, PreRenderEnd, void* self) 284 | { 285 | PreRenderEnd(self); 286 | if(gpsDistance > 0.0f && !IsGamePaused() && IsRadarVisible()) 287 | { 288 | static bool bInit = false; 289 | if(!bInit) 290 | { 291 | bInit = true; 292 | SetDistanceTextValues(); 293 | } 294 | 295 | if(pCfgGPSDrawDistance->GetBool()) 296 | { 297 | if(!bImperialUnits) 298 | { 299 | if(gpsDistance == 100000.0f) sprintf(text, "Far from the road!"); 300 | else if (gpsDistance >= 1000.0f) sprintf(text, "%.2fkm", 0.001f * gpsDistance); 301 | else sprintf(text, "%dm", (int)gpsDistance); 302 | } 303 | else 304 | { 305 | if(gpsDistance == 100000.0f) sprintf(text, "Far from the road!"); 306 | else if (gpsDistance > 1609.344f) sprintf(text, "%.2fmil", (float)(0.000621371192237334 * (double)gpsDistance)); 307 | else sprintf(text, "%dyrd", (int)(gpsDistance * 1.094f)); 308 | } 309 | AsciiToGxtChar(text, textGxt); 310 | 311 | static CRGBA drawingColor; 312 | drawingColor = (!TargetBlip.m_nHandleIndex && pTrace) ? GetTraceTextColor(pTrace->m_nColour, pTrace->m_bFriendly) : rgbaWhite; 313 | //drawingColor.a = GetRadarVisibility(); 314 | 315 | FontSetOrientation(g_nTextAlignment); 316 | FontSetColor(&drawingColor); 317 | FontSetBackground(false, false); 318 | FontSetWrapx(500.0f); 319 | FontSetScale(textScale); 320 | FontSetStyle(FONT_SUBTITLES); 321 | FontSetProportional(true); 322 | FontSetDropShadowPosition(1); 323 | FontPrintString(gpsDistanceTextPos.x, gpsDistanceTextPos.y, textGxt); 324 | RenderFontBuffer(); 325 | } 326 | } 327 | gpsDistance = 0; 328 | } 329 | 330 | DECL_HOOKv(InitRenderWare) 331 | { 332 | InitRenderWare(); 333 | InitializeConfigValues(); 334 | } 335 | 336 | short nodesCount = 0; 337 | float trashVar; 338 | void DoPathDraw(CVector to, RwUInt32 color, bool isTargetBlip = false, float* dist = NULL) 339 | { 340 | CPlayerPed* player = FindPlayerPed(-1); 341 | if(!IsInSupportedVehicle(player)) return; 342 | 343 | bool isGamePaused = IsGamePaused(), bScissors = (!isGamePaused || !gMobileMenu->m_bDrawMenuMap); 344 | 345 | //*ExtraPathsNeeded = true; 346 | //*ExtraPathPos = to; 347 | DoPathSearch(ThePaths, LaneDirectionRespected() && player->m_pVehicle->m_nVehicleSubType != VEHICLE_TYPE_BOAT, player->GetPosition(), 348 | CNodeAddress(), to, resultNodes, &nodesCount, maxLoadedPathNodes, dist ? dist : &trashVar, 1000000.0f, NULL, 1000000.0f, false, 349 | CNodeAddress(), false, player->m_pVehicle->m_nVehicleSubType == VEHICLE_TYPE_BOAT && IsBoatNaviAllowed()); 350 | 351 | if(nodesCount > 0) 352 | { 353 | if(isTargetBlip && bScissors && 354 | gpsDistance < pCfgClosestMaxGPSDistance->GetFloat()) 355 | { 356 | ClearRadarBlip(TargetBlip.m_nHandleIndex); 357 | gMobileMenu->m_TargetBlipHandle.m_nHandleIndex = 0; 358 | TargetBlip.m_nHandleIndex = 0; 359 | return; 360 | } 361 | 362 | CPathNode* node; 363 | CVector2D nodePos; 364 | if (isGamePaused) 365 | { 366 | for (int i = 0; i < nodesCount; ++i) 367 | { 368 | node = &ThePaths->pNodes[resultNodes[i].m_nAreaId][resultNodes[i].m_nNodeId]; 369 | nodePos = node->GetPosition2D(); 370 | TransformRealWorldPointToRadarSpace(nodePos, nodePos); 371 | LimitRadarPoint(nodePos); 372 | TransformRadarPointToScreenSpace(nodePoints[i], nodePos); 373 | nodePoints[i] *= flMenuMapScaling; 374 | } 375 | } 376 | else 377 | { 378 | for (int i = 0; i < nodesCount; ++i) 379 | { 380 | node = &ThePaths->pNodes[resultNodes[i].m_nAreaId][resultNodes[i].m_nNodeId]; 381 | nodePos = node->GetPosition2D(); 382 | TransformRealWorldPointToRadarSpace(nodePos, nodePos); 383 | TransformRadarPointToScreenSpace(nodePoints[i], nodePos); 384 | } 385 | } 386 | 387 | if(IsRadarVisible() || isGamePaused) 388 | { 389 | if (bScissors) SetScissorRect(radarRect); // Scissors 390 | RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); 391 | 392 | unsigned int vertIndex = 0; 393 | --nodesCount; 394 | 395 | CVector2D point[4], shift[2], dir; 396 | float angle; 397 | if (isGamePaused) 398 | { 399 | float mp = gMobileMenu->m_fMapZoom - 140.0f; 400 | if (mp < 140.0f) mp = 140.0f; 401 | else if (mp > 960.0f) mp = 960.0f; 402 | mp = mp / 960.0f + 0.4f; 403 | mp *= lineWidth; 404 | 405 | for (int i = 0; i < nodesCount; i++) 406 | { 407 | dir = CVector2D::Diff(nodePoints[i + 1], nodePoints[i]); 408 | angle = atan2(dir.y, dir.x); 409 | 410 | sincosf(angle - 1.5707963f, &shift[0].y, &shift[0].x); shift[0] *= mp; 411 | sincosf(angle + 1.5707963f, &shift[1].y, &shift[1].x); shift[1] *= mp; 412 | 413 | Setup2DVertex(lineVerts[vertIndex], nodePoints[i].x + shift[0].x, nodePoints[i].y + shift[0].y, color); 414 | Setup2DVertex(lineVerts[++vertIndex], nodePoints[i + 1].x + shift[0].x, nodePoints[i + 1].y + shift[0].y, color); 415 | Setup2DVertex(lineVerts[++vertIndex], nodePoints[i].x + shift[1].x, nodePoints[i].y + shift[1].y, color); 416 | Setup2DVertex(lineVerts[++vertIndex], nodePoints[i + 1].x + shift[1].x, nodePoints[i + 1].y + shift[1].y, color); 417 | ++vertIndex; 418 | } 419 | } 420 | else 421 | { 422 | for (int i = 0; i < nodesCount; i++) 423 | { 424 | dir = CVector2D::Diff(nodePoints[i + 1], nodePoints[i]); 425 | angle = atan2(dir.y, dir.x); 426 | 427 | sincosf(angle - 1.5707963f, &shift[0].y, &shift[0].x); shift[0] *= lineWidth; 428 | sincosf(angle + 1.5707963f, &shift[1].y, &shift[1].x); shift[1] *= lineWidth; 429 | 430 | Setup2DVertex(lineVerts[vertIndex], nodePoints[i].x + shift[0].x, nodePoints[i].y + shift[0].y, color); 431 | Setup2DVertex(lineVerts[++vertIndex], nodePoints[i + 1].x + shift[0].x, nodePoints[i + 1].y + shift[0].y, color); 432 | Setup2DVertex(lineVerts[++vertIndex], nodePoints[i].x + shift[1].x, nodePoints[i].y + shift[1].y, color); 433 | Setup2DVertex(lineVerts[++vertIndex], nodePoints[i + 1].x + shift[1].x, nodePoints[i + 1].y + shift[1].y, color); 434 | ++vertIndex; 435 | } 436 | } 437 | RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, lineVerts, 4 * nodesCount); 438 | if (bScissors) SetScissorRect(emptyRect); // Scissors 439 | } 440 | } 441 | } 442 | 443 | DECL_HOOKv(PostRadarDraw, bool b) 444 | { 445 | PostRadarDraw(b); 446 | 447 | if(gMobileMenu->m_TargetBlipHandle.m_nHandleIndex) 448 | { 449 | bool isGamePaused = IsGamePaused(); 450 | if(TargetBlip.m_nHandleIndex != gMobileMenu->m_TargetBlipHandle.m_nHandleIndex && !isGamePaused && IsRadarVisible()) 451 | { 452 | TargetBlip = gMobileMenu->m_TargetBlipHandle; 453 | } 454 | 455 | CVector& bpos = pRadarTrace[gMobileMenu->m_TargetBlipHandle.m_nId].m_vecWorldPosition; 456 | if(bpos.z == 0) 457 | { 458 | RequestCollision(&bpos, -1); 459 | LoadAllRequestedModels(false); 460 | bpos.z = FindGroundZForCoord(bpos.x, bpos.y) + 5.0f; 461 | } 462 | DoPathDraw(bpos, gpsLineColor, true, &gpsDistance); 463 | } 464 | else 465 | { 466 | TargetBlip.m_nHandleIndex = 0; 467 | } 468 | 469 | pTrace = NULL; 470 | if(bAllowMission && IsOnAMission()) 471 | { 472 | CPlayerPed* player = FindPlayerPed(-1); 473 | unsigned char count = 0, maxi = 0; 474 | float distances[250], maxdist; 475 | tRadarTrace* traces[250]; 476 | 477 | for(unsigned char i = 0; i < 250; ++i) 478 | { 479 | tRadarTrace& trace = pRadarTrace[i]; 480 | if(trace.m_nBlipSprite == RADAR_SPRITE_NONE && 481 | trace.m_nBlipDisplayFlag > 1) 482 | { 483 | if(trace.m_nColour == BLIP_COLOUR_DESTINATION) 484 | { 485 | pTrace = &trace; 486 | break; 487 | } 488 | traces[count] = &trace; 489 | distances[count] = DistanceBetweenPoints(player->GetPosition(), trace.m_vecWorldPosition); 490 | ++count; 491 | } 492 | } 493 | 494 | if(count > 0) 495 | { 496 | maxdist = distances[0]; 497 | for(unsigned char i = 1; i < count; ++i) 498 | { 499 | if(distances[i] > maxdist) 500 | { 501 | maxi = i; 502 | maxdist = distances[i]; 503 | } 504 | } 505 | pTrace = traces[maxi]; 506 | } 507 | 508 | if(pTrace) 509 | { 510 | CEntity *handle; 511 | switch(pTrace->m_nBlipType) 512 | { 513 | case BLIP_CAR: 514 | if((handle = GetPoolVeh(pTrace->m_nEntityHandle)) != NULL) 515 | DoPathDraw(handle->GetPosition(), GetTraceColor(pTrace->m_nColour, pTrace->m_bFriendly), false, !TargetBlip.m_nHandleIndex ? &gpsDistance : NULL); 516 | break; 517 | 518 | case BLIP_CHAR: 519 | if((handle = GetPoolPed(pTrace->m_nEntityHandle)) != NULL) 520 | DoPathDraw(handle->GetPosition(), GetTraceColor(pTrace->m_nColour, pTrace->m_bFriendly), false, !TargetBlip.m_nHandleIndex ? &gpsDistance : NULL); 521 | break; 522 | 523 | case BLIP_OBJECT: 524 | if((handle = GetPoolObj(pTrace->m_nEntityHandle)) != NULL) 525 | DoPathDraw(handle->GetPosition(), GetTraceColor(pTrace->m_nColour, pTrace->m_bFriendly), false, !TargetBlip.m_nHandleIndex ? &gpsDistance : NULL); 526 | break; 527 | 528 | case BLIP_PICKUP: 529 | { 530 | CPickup* p = &aPickUps[pTrace->m_ScriptHandle.m_nId]; 531 | DoPathDraw(UncompressLargeVector(p->m_vecPos), GetTraceColor(pTrace->m_nColour, pTrace->m_bFriendly), false, !TargetBlip.m_nHandleIndex ? &gpsDistance : NULL); 532 | break; 533 | } 534 | 535 | case BLIP_COORD: 536 | case BLIP_CONTACT_POINT: 537 | DoPathDraw(pTrace->m_vecWorldPosition, GetTraceColor(pTrace->m_nColour, pTrace->m_bFriendly), false, !TargetBlip.m_nHandleIndex ? &gpsDistance : NULL); 538 | break; 539 | 540 | default: 541 | break; 542 | } 543 | } 544 | } 545 | } 546 | 547 | DECL_HOOKv(LoadSceneForPathNodes, CPathFind* self, CVector center) 548 | { 549 | memset(ToBeStreamed, 0, 64); 550 | CPlayerPed* player = FindPlayerPed(-1); 551 | 552 | if(player) 553 | { 554 | MarkRegionsForCoors(self, center, 4300.0f); 555 | MarkRegionsForCoors(self, player->GetPosition(), 4300.0f); 556 | } 557 | else 558 | { 559 | MarkRegionsForCoors(self, center, 4300.0f); 560 | } 561 | for(int i = 0; i < 64; ++i) 562 | { 563 | if(ToBeStreamed[i] != 0) RequestModel(25511 + i, STREAMING_NONE); 564 | } 565 | } 566 | 567 | DECL_HOOKv(UpdateStreaming, CPathFind *self, bool forceLoad) 568 | { 569 | if(!forceLoad && !*ExtraPathsNeeded && (*m_snTimeInMilliseconds ^ *m_snPreviousTimeInMilliseconds) < 512) return; 570 | memset(ToBeStreamed, 0, 64); 571 | 572 | static CVector mapcorner1 = { -3000.0f, -3000.0f, 20.0f }; 573 | static CVector mapcorner2 = { -3000.0f, 3000.0f, 20.0f }; 574 | static CVector mapcorner3 = { 3000.0f, -3000.0f, 20.0f }; 575 | static CVector mapcorner4 = { 3000.0f, 3000.0f, 20.0f }; 576 | 577 | MarkRegionsForCoors(self, mapcorner1, 4300.0f); 578 | MarkRegionsForCoors(self, mapcorner2, 4300.0f); 579 | MarkRegionsForCoors(self, mapcorner3, 4300.0f); 580 | MarkRegionsForCoors(self, mapcorner4, 4300.0f); 581 | 582 | CPlayerPed* player = FindPlayerPed(-1); 583 | if(player) MarkRegionsForCoors(self, player->GetPosition(), 4300.0f); 584 | if(*ExtraPathsNeeded) 585 | { 586 | MarkRegionsForCoors(self, *ExtraPathPos, 4300.0f); 587 | *ExtraPathsNeeded = false; 588 | } 589 | for(int i = 0; i < 64; ++i) 590 | { 591 | if(ToBeStreamed[i] != 0) 592 | { 593 | if(self->pNodes[i] == NULL) RequestModel(25511 + i, STREAMING_KEEP_IN_MEMORY); 594 | } 595 | else if(self->pNodes[i] != NULL) RemoveModel(25511 + i); 596 | } 597 | } 598 | 599 | #ifdef AML64 600 | uintptr_t DoPathFind_BackTo; 601 | __attribute__((optnone)) __attribute__((naked)) void DoPathFind_Inject(void) 602 | { 603 | asm("MOV W2, WZR\nMOV W9, WZR\nEOR W12, W8, #1"); 604 | asm volatile("MOV X8, %0" :: "r"(&aNodesToBeCleared_NEW[0])); 605 | asm volatile("STR W1, [X8]"); 606 | asm volatile("MOV X16, %0\n" :: "r"(DoPathFind_BackTo)); 607 | asm("BR X16"); 608 | } 609 | #endif 610 | 611 | extern "C" void OnModLoad() 612 | { 613 | logger->SetTag("GPS AML"); 614 | pGTASA = aml->GetLib("libGTASA.so"); 615 | hGTASA = aml->GetLibHandle("libGTASA.so"); 616 | 617 | pCfgClosestMaxGPSDistance = cfg->Bind("ClosestMaxGPSDistance", 40.0f); 618 | pCfgClosestMaxGPSDistance->Clamp(0.0f, 200.0f); 619 | 620 | pCfgGPSMaxPathNodesLoaded = cfg->Bind("GPSMaxPathNodesLoaded", 50000); 621 | pCfgGPSMaxPathNodesLoaded->Clamp(5000, MAX_NODE_POINTS); 622 | maxLoadedPathNodes = pCfgGPSMaxPathNodesLoaded->GetInt(); 623 | delete pCfgGPSMaxPathNodesLoaded; 624 | 625 | pCfgGPSLineColorRGB = cfg->Bind("GPSLineColorRGB", STRINGIFY(GPS_LINE_R)" " STRINGIFY(GPS_LINE_G)" " STRINGIFY(GPS_LINE_B)" " STRINGIFY(GPS_LINE_A)); 626 | lineWidth = cfg->GetFloat("GPSLineWidth", 4.0f); 627 | pCfgGPSDrawDistance = cfg->Bind("GPSDrawDistance", true); 628 | pCfgGPSDrawDistancePosition = cfg->Bind("GPSDrawDistancePos", 0); // 0 under, 1 above, 2 left, 3 right, 4 custom 629 | pCfgGPSDrawDistanceTextScale = cfg->Bind("GPSDrawDistanceTextScale", 1.0f); 630 | pCfgGPSDrawDistanceTextOffset = cfg->Bind("GPSDrawDistanceTextOffset", "0.0 0.0"); 631 | bAllowBMX = cfg->GetBool("AllowBMX", false); 632 | bAllowBoat = cfg->GetBool("AllowBoatNavi", true); 633 | bAllowMission = cfg->GetBool("MissionRoutes", true); 634 | bImperialUnits = cfg->GetBool("UseImperialUnits", false); // People need this. https://github.com/juicermv/GTA-GPS-Redux/issues/13 635 | bRespectLanesDirection = cfg->GetBool("RespectLanesDirection", false); 636 | 637 | int r, g, b, a, sscanfed = sscanf(pCfgGPSLineColorRGB->GetString(), "%d %d %d %d", &r, &g, &b, &a); 638 | if(sscanfed == 4 && IsRGBValue(r) && IsRGBValue(g) && IsRGBValue(b) && IsRGBValue(a)) 639 | { 640 | gpsLineColor = RWRGBALONG(r, g, b, a); 641 | } 642 | else if(sscanfed == 3 && IsRGBValue(r) && IsRGBValue(g) && IsRGBValue(b)) 643 | { 644 | gpsLineColor = RWRGBALONG(r, g, b, 255); 645 | } 646 | else 647 | { 648 | pCfgGPSLineColorRGB->SetString(STRINGIFY(GPS_LINE_R)" " STRINGIFY(GPS_LINE_G)" " STRINGIFY(GPS_LINE_B)" " STRINGIFY(GPS_LINE_A)); 649 | cfg->Save(); 650 | } 651 | delete pCfgGPSLineColorRGB; 652 | 653 | cfg->Bind("Author", "", "About")->SetString("[-=KILL MAN=-]"); cfg->ClearLast(); 654 | cfg->Bind("IdeasFrom", "", "About")->SetString("DK22Pac, JuniorDjjr, juicermv"); cfg->ClearLast(); 655 | cfg->Bind("Discord", "", "About")->SetString("https://discord.gg/2MY7W39kBg"); cfg->ClearLast(); 656 | cfg->Bind("GitHub", "", "About")->SetString("https://github.com/AndroidModLoader/GTASA_GPS"); cfg->ClearLast(); 657 | cfg->Save(); 658 | 659 | // Init 660 | 661 | for(int i = 0; i < maxLoadedPathNodes; ++i) *(uint32_t*)(&aNodesToBeCleared_NEW[i]) = 0xFFFFFFFF; 662 | 663 | // Hooks 664 | 665 | HOOKPLT(PreRenderEnd, pGTASA + BYBIT(0x674188, 0x846E90)); 666 | HOOKPLT(InitRenderWare, pGTASA + BYBIT(0x66F2D0, 0x8432F0)); 667 | HOOK(PostRadarDraw, aml->GetSym(hGTASA, "_ZN6CRadar20DrawRadarGangOverlayEb")); 668 | HOOKBLX(LoadSceneForPathNodes, pGTASA + BYBIT(0x2D4AFE + 0x1, 0x3970DC)); 669 | HOOK(UpdateStreaming, aml->GetSym(hGTASA, "_ZN9CPathFind15UpdateStreamingEb")); 670 | 671 | // Vars 672 | 673 | SET_TO(ThePaths, aml->GetSym(hGTASA, "ThePaths")); 674 | SET_TO(gMobileMenu, aml->GetSym(hGTASA, "gMobileMenu")); 675 | SET_TO(RsGlobal, aml->GetSym(hGTASA, "RsGlobal")); 676 | SET_TO(NearScreenZ, aml->GetSym(hGTASA, "_ZN9CSprite2d11NearScreenZE")); 677 | SET_TO(RecipNearClip, aml->GetSym(hGTASA, "_ZN9CSprite2d13RecipNearClipE")); 678 | SET_TO(pRadarTrace, aml->GetSym(hGTASA, "_ZN6CRadar13ms_RadarTraceE")); 679 | SET_TO(m_UserPause, aml->GetSym(hGTASA, "_ZN6CTimer11m_UserPauseE")); 680 | SET_TO(m_CodePause, aml->GetSym(hGTASA, "_ZN6CTimer11m_CodePauseE")); 681 | 682 | SET_TO(FindPlayerPed, aml->GetSym(hGTASA, "_Z13FindPlayerPedi")); 683 | SET_TO(FindPlayerCoors, aml->GetSym(hGTASA, "_Z15FindPlayerCoorsi")); 684 | SET_TO(FindGroundZForCoord, aml->GetSym(hGTASA, "_ZN6CWorld19FindGroundZForCoordEff")); 685 | SET_TO(DoPathSearch, aml->GetSym(hGTASA, "_ZN9CPathFind12DoPathSearchEh7CVector12CNodeAddressS0_PS1_PsiPffS2_fbS1_bb")); 686 | SET_TO(TransformRadarPointToRealWorldSpace, aml->GetSym(hGTASA, "_ZN6CRadar35TransformRadarPointToRealWorldSpaceER9CVector2DRKS0_")); 687 | SET_TO(TransformRealWorldPointToRadarSpace, aml->GetSym(hGTASA, "_ZN6CRadar35TransformRealWorldPointToRadarSpaceER9CVector2DRKS0_")); 688 | SET_TO(TransformRadarPointToScreenSpace, aml->GetSym(hGTASA, "_ZN6CRadar32TransformRadarPointToScreenSpaceER9CVector2DRKS0_")); 689 | SET_TO(LimitRadarPoint, aml->GetSym(hGTASA, "_ZN6CRadar15LimitRadarPointER9CVector2D")); 690 | SET_TO(RwRenderStateSet, aml->GetSym(hGTASA, "_Z16RwRenderStateSet13RwRenderStatePv")); 691 | SET_TO(RwIm2DRenderPrimitive, aml->GetSym(hGTASA, "_Z28RwIm2DRenderPrimitive_BUGFIX15RwPrimitiveTypeP14RwOpenGLVertexi")); 692 | SET_TO(SetScissorRect, aml->GetSym(hGTASA, "_ZN7CWidget10SetScissorER5CRect")); 693 | SET_TO(ClearRadarBlip, aml->GetSym(hGTASA, "_ZN6CRadar9ClearBlipEi")); 694 | SET_TO(FontSetOrientation, aml->GetSym(hGTASA, "_ZN5CFont14SetOrientationEh")); 695 | SET_TO(FontSetColor, aml->GetSym(hGTASA, "_ZN5CFont8SetColorE5CRGBA")); 696 | SET_TO(FontSetBackground, aml->GetSym(hGTASA, "_ZN5CFont13SetBackgroundEhh")); 697 | SET_TO(FontSetWrapx, aml->GetSym(hGTASA, "_ZN5CFont8SetWrapxEf")); 698 | SET_TO(FontSetStyle, aml->GetSym(hGTASA, "_ZN5CFont12SetFontStyleEh")); 699 | SET_TO(FontSetScale, aml->GetSym(hGTASA, "_ZN5CFont8SetScaleEf")); 700 | SET_TO(FontSetEdge, aml->GetSym(hGTASA, "_ZN5CFont7SetEdgeEa")); 701 | SET_TO(FontSetProportional, aml->GetSym(hGTASA, "_ZN5CFont15SetProportionalEh")); 702 | SET_TO(FontSetDropShadowPosition, aml->GetSym(hGTASA, "_ZN5CFont21SetDropShadowPositionEa")); 703 | SET_TO(FontSetDropColor, aml->GetSym(hGTASA, "_ZN5CFont12SetDropColorE5CRGBA")); 704 | SET_TO(FontPrintString, aml->GetSym(hGTASA, "_ZN5CFont11PrintStringEffPt")); 705 | SET_TO(AsciiToGxtChar, aml->GetSym(hGTASA, "_Z14AsciiToGxtCharPKcPt")); 706 | SET_TO(RenderFontBuffer, aml->GetSym(hGTASA, "_ZN5CFont16RenderFontBufferEv")); 707 | SET_TO(IsOnAMission, aml->GetSym(hGTASA, "_ZN11CTheScripts18IsPlayerOnAMissionEv")); 708 | SET_TO(GetPoolPed, aml->GetSym(hGTASA, "_ZN6CPools6GetPedEi")); 709 | SET_TO(GetPoolVeh, aml->GetSym(hGTASA, "_ZN6CPools10GetVehicleEi")); 710 | SET_TO(GetPoolObj, aml->GetSym(hGTASA, "_ZN6CPools9GetObjectEi")); 711 | SET_TO(RequestModel, aml->GetSym(hGTASA, "_ZN10CStreaming12RequestModelEii")); 712 | SET_TO(RemoveModel, aml->GetSym(hGTASA, "_ZN10CStreaming11RemoveModelEi")); 713 | SET_TO(LoadAllRequestedModels, aml->GetSym(hGTASA, "_ZN10CStreaming22LoadAllRequestedModelsEb")); 714 | SET_TO(MarkRegionsForCoors, aml->GetSym(hGTASA, "_ZN9CPathFind19MarkRegionsForCoorsE7CVectorf")); 715 | SET_TO(RequestCollision, aml->GetSym(hGTASA, "_ZN9CColStore16RequestCollisionERK7CVectori")); 716 | 717 | SET_TO(aWidgets, *(void**)(pGTASA + BYBIT(0x67947C, 0x850910))); 718 | SET_TO(aPickUps, *(void**)(pGTASA + BYBIT(0x678BF8, 0x84F818))); 719 | SET_TO(ExtraPathsNeeded, pGTASA + BYBIT(0x7AEE04, 0x9905C8)); 720 | SET_TO(ExtraPathPos, pGTASA + BYBIT(0x7AEDF8, 0x9905BC)); 721 | SET_TO(ToBeStreamed, aml->GetSym(hGTASA, "ToBeStreamed")); 722 | SET_TO(m_snTimeInMilliseconds, aml->GetSym(hGTASA, "_ZN6CTimer22m_snTimeInMillisecondsE")); 723 | SET_TO(m_snPreviousTimeInMilliseconds, aml->GetSym(hGTASA, "_ZN6CTimer30m_snPreviousTimeInMillisecondsE")); 724 | 725 | // Patches 726 | 727 | aml->Write32(pGTASA + BYBIT(0x315B06, 0x3DBE58), BYBIT(MOVWBits::Create(maxLoadedPathNodes-1, 2), MOVBits::Create(maxLoadedPathNodes-1, 18, false))); // 4999 -> maxLoadedPathNodes-1 728 | aml->Write32(pGTASA + BYBIT(0x315BC4, 0x3DBE48), BYBIT(MOVWBits::Create(maxLoadedPathNodes-50, 2), MOVBits::Create(maxLoadedPathNodes-50, 14, false))); // 4950 -> maxLoadedPathNodes-50 729 | 730 | #ifdef AML32 731 | aml->WriteAddr(pGTASA + 0x315D30, (uintptr_t)aNodesToBeCleared_NEW - 0x31598A - pGTASA); 732 | aml->WriteAddr(pGTASA + 0x315D34, (uintptr_t)aNodesToBeCleared_NEW - 0x315BE2 - pGTASA); 733 | aml->WriteAddr(pGTASA + 0x315D38, (uintptr_t)aNodesToBeCleared_NEW - 0x315D08 - pGTASA); 734 | aml->WriteAddr(pGTASA + 0x315D3C, (uintptr_t)aNodesToBeCleared_NEW - 0x315B20 - pGTASA); 735 | #else // AML64 736 | aml->WriteAddr(pGTASA + 0x9904B0, (uintptr_t)&aNodesToBeCleared_NEW[0]); // using original aNodesToBeCleared as a mapping 737 | aml->Redirect(pGTASA + 0x3DBE30, (uintptr_t)DoPathFind_Inject); DoPathFind_BackTo = pGTASA + 0x3DBE40; 738 | aml->Write32(pGTASA + 0x3DBE40, 0xB0002DA1); aml->Write32(pGTASA + 0x3DBE60, 0xF9425821); 739 | aml->Write32(pGTASA + 0x3DC0B0, 0x90002DA9); aml->Write32(pGTASA + 0x3DC0B8, 0xF9425929); 740 | aml->Write32(pGTASA + 0x3DC238, 0x90002DA9); aml->Write32(pGTASA + 0x3DC240, 0xF9425929); 741 | #endif 742 | } --------------------------------------------------------------------------------