├── .gitattributes ├── readme-images └── example.png ├── pawn.json ├── .travis.yml ├── test.pwn ├── .gitignore ├── LICENSE ├── .vscode └── tasks.json ├── README.md └── markerplus.inc /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pwn linguist-language=Pawn 2 | *.inc linguist-language=Pawn 3 | -------------------------------------------------------------------------------- /readme-images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramon-Sd/marker-plus/HEAD/readme-images/example.png -------------------------------------------------------------------------------- /pawn.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": "Ramon-Sd", 3 | "repo": "marker-plus", 4 | "tag": "1.0.0", 5 | "entry": "test.pwn", 6 | "output": "gamemodes/test.amx", 7 | "dependencies": [ 8 | "pawn-lang/samp-stdlib", 9 | "samp-incognito/samp-streamer-plugin" 10 | ], 11 | "runtime": { 12 | "mode": "y_testing" 13 | } 14 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | sudo: enabled 3 | install: 4 | - curl https://raw.githubusercontent.com/Southclaws/sampctl/master/install-deb.sh | sh 5 | - sudo dpkg --add-architecture i386 6 | - sudo apt update && sudo apt install -y g++-multilib 7 | script: 8 | - sampctl package ensure 9 | - sampctl package build 10 | - sampctl package run 11 | -------------------------------------------------------------------------------- /test.pwn: -------------------------------------------------------------------------------- 1 | #include "markerplus.inc" 2 | 3 | main() 4 | { 5 | return 0; 6 | } 7 | 8 | static myMarker; 9 | 10 | public OnGameModeInit() { 11 | 12 | myMarker = CreateMarker(ICON_FACTORY, true, 0.0, 0.0, 0.0); 13 | return 1; 14 | } 15 | 16 | public OnGameModeExit() { 17 | 18 | DestroyMarker(myMarker); 19 | return 1; 20 | } 21 | 22 | public OnPlayerEnterMarker(playerid, markerid) { 23 | 24 | return 1; 25 | } 26 | 27 | public OnPlayerLeaveMarker(playerid, markerid) { 28 | 29 | return 1; 30 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Package only files 3 | # 4 | 5 | # Compiled Bytecode, precompiled output and assembly 6 | *.amx 7 | *.lst 8 | *.asm 9 | 10 | # Vendor directory for dependencies 11 | dependencies/ 12 | 13 | # Dependency versions lockfile 14 | pawn.lock 15 | 16 | 17 | # 18 | # Server/gamemode related files 19 | # 20 | 21 | # compiled settings file 22 | # keep `samp.json` file on version control 23 | # but make sure the `rcon_password` field is set externally 24 | # you can use the environment variable `SAMP_RCON_PASSWORD` to do this. 25 | server.cfg 26 | 27 | # Plugins directory 28 | plugins/ 29 | 30 | # binaries 31 | *.exe 32 | *.dll 33 | *.so 34 | announce 35 | samp03svr 36 | samp-npc 37 | 38 | # logs 39 | logs/ 40 | server_log.txt 41 | crashinfo.txt 42 | 43 | # Ban list 44 | samp.ban 45 | 46 | # 47 | # Common files 48 | # 49 | 50 | *.sublime-workspace 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ramon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build only", 6 | "type": "shell", 7 | "command": "sampctl package build", 8 | "group": { 9 | "kind": "build", 10 | "isDefault": true 11 | }, 12 | "isBackground": false, 13 | "presentation": { 14 | "reveal": "silent", 15 | "panel": "dedicated" 16 | }, 17 | "problemMatcher": "$sampctl" 18 | }, 19 | { 20 | "label": "build watcher", 21 | "type": "shell", 22 | "command": "sampctl package build --watch", 23 | "group": "build", 24 | "isBackground": true, 25 | "presentation": { 26 | "reveal": "silent", 27 | "panel": "dedicated" 28 | }, 29 | "problemMatcher": "$sampctl" 30 | }, 31 | { 32 | "label": "run tests", 33 | "type": "shell", 34 | "command": "sampctl package run", 35 | "group": { 36 | "kind": "test", 37 | "isDefault": true 38 | }, 39 | "isBackground": true, 40 | "presentation": { 41 | "reveal": "silent", 42 | "panel": "dedicated" 43 | }, 44 | "problemMatcher": "$sampctl" 45 | }, 46 | { 47 | "label": "run tests watcher", 48 | "type": "shell", 49 | "command": "sampctl package run --watch", 50 | "group": "test", 51 | "isBackground": true, 52 | "presentation": { 53 | "reveal": "silent", 54 | "panel": "dedicated" 55 | }, 56 | "problemMatcher": "$sampctl" 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![samp-include](https://img.shields.io/badge/sa--mp-library-2f2f2f.svg?style=for-the-badge)](https://github.com/Ramon-Sd/marker-plus) 2 | 3 | exemplo imagem 4 | 5 | > Enables the creation of custom markers for SA-MP. 6 | 7 |
8 | 9 | 1. [Installation](#-Installation) 10 | 11 | 2. [Documentation](#-Documentation) 12 | 13 |
14 | 15 | ## 🚀 Installation 16 | 17 | You can install the "Marker Plus" library in two ways: 18 | 19 | - Using sampctl: You can install the library using the sampctl package manager. Simply run the following command in the terminal: 20 | ```bash 21 | sampctl package install Ramon-Sd/marker-plus 22 | ``` 23 | 24 | - Using Git: You can clone the library's Git repository and manually add it to your project. Run the following command in the terminal: 25 | ```bash 26 | git clone https://github.com/Ramon-Sd/marker-plus.git 27 | ``` 28 | 29 | Then, include the "markerplus.inc" include file in your code: 30 | 31 | ```pawn 32 | #include "markerplus.inc" 33 | ``` 34 | 35 | ## ☕ Documentation 36 | 37 | ### **Functions** 38 | 39 | 40 | - **CreateMarker**: Creates a custom marker. This function returns a unique marker ID. 41 | - Parameters: 42 | - `icon` (icon): The marker icon. It can be one of the icons defined in the `enum`. 43 | - `calledActive` (active): Indicates whether the marker is active or not. 44 | - `x`, `y`, `z` (coordinates): The coordinates of the marker in the SA-MP world. 45 | - `worldID` (optional): The ID of the world where the marker is located. The default is -1 (main world). 46 | - `interiorID` (optional): The ID of the interior where the marker is located. The default is -1 (no interior). 47 | - `drawDistance` (optional): The marker's draw distance. The default is 0.0 (always draw). 48 | - Return: 49 | - Returns the ID of the created marker, or a warning message if the marker limit is reached. 50 | 51 | - **DestroyMarker**: Destroys an existing marker in SA-MP. 52 | - Parameters: 53 | - `markerid` (marker ID): The ID of the marker to be destroyed. 54 | 55 | ### **Callbacks** 56 | 57 | 58 | - **OnPlayerEnterMarker**: Called when a player enters the area of a marker. 59 | - Parameters: 60 | - `playerid` (player ID): The ID of the player who entered the marker area. 61 | - `markerid` (marker ID): The ID of the marker whose area was accessed. 62 | 63 | - **OnPlayerLeaveMarker**: Called when a player leaves the area of a marker. 64 | - Parameters: 65 | - `playerid` (player ID): The ID of the player who left the marker area. 66 | - `markerid` (marker ID): The ID of the marker whose area was left. 67 | 68 | ### **Example** 69 | 70 | 71 | ```pawn 72 | #include "markerplus.inc" 73 | 74 | main() 75 | { 76 | return 0; 77 | } 78 | 79 | static myMarker; 80 | 81 | public OnGameModeInit() { 82 | 83 | myMarker = CreateMarker(ICON_FACTORY, true, 0.0, 0.0, 0.0); 84 | return 1; 85 | } 86 | 87 | public OnGameModeExit() { 88 | 89 | DestroyMarker(myMarker); 90 | return 1; 91 | } 92 | 93 | public OnPlayerEnterMarker(playerid, markerid) { 94 | 95 | return 1; 96 | } 97 | 98 | public OnPlayerLeaveMarker(playerid, markerid) { 99 | 100 | return 1; 101 | } 102 | ``` 103 | 104 |

105 | 106 | This project is licensed. See the [LICENSE](LICENSE.md) file for more details. 107 | -------------------------------------------------------------------------------- /markerplus.inc: -------------------------------------------------------------------------------- 1 | #if !defined _samp_included 2 | #include "a_samp.inc" 3 | #endif 4 | 5 | #if !defined _streamer_included 6 | #include "streamer.inc" 7 | #endif 8 | 9 | #if defined _INC_markerplus 10 | #endinput 11 | #endif 12 | #define _INC_markerplus 13 | 14 | 15 | #if !defined MAX_MARKERS 16 | #define MAX_MARKERS (401) 17 | #endif 18 | 19 | #define INVALID_MARKER_ID (-1) 20 | 21 | 22 | enum { 23 | ICON_INVALID, 24 | ICON_FACTORY, 25 | ICON_CONSTRUCTION, 26 | ICON_BANK, 27 | ICON_HOUSE, 28 | ICON_PRAIA, 29 | ICON_ROAD, 30 | ICON_CITY, 31 | ICON_HOUSE_2, 32 | ICON_AMBULANCE, 33 | ICON_FIRE_TRUCK, 34 | ICON_POLICE_CAR, 35 | ICON_SHIP, 36 | ICON_BUS 37 | } 38 | 39 | static const ICON_LETTER[][5] = { 40 | "NULL", "F", "A", "G", "H", "J", "K", "C", "B", "h", "f", "p", "o", "v" 41 | }; 42 | 43 | static const ICON_FONT[][15] = { 44 | "NULL", "Webdings", "Webdings", "Webdings", "Webdings", "Webdings", 45 | "Webdings", "Webdings", "Webdings", "Webdings", "Webdings", "Webdings", 46 | "Webdings", "Webdings" 47 | }; 48 | 49 | 50 | enum MarkerData { 51 | 52 | STREAMER_TAG_AREA:markerCalledArea, 53 | markerIcon, 54 | bool:markerCalledActive, 55 | Float:markerPosition[3], 56 | markerWorldID, 57 | markerInteriorID, 58 | Float:markerDrawDistance 59 | } 60 | 61 | enum PlayerMarkerData { 62 | 63 | markerObject[MAX_MARKERS], 64 | markerObjectIcon[MAX_MARKERS], 65 | bool:markerVisible[MAX_MARKERS] 66 | } 67 | 68 | static markerData[MAX_MARKERS][MarkerData]; 69 | static playerMarkerData[MAX_PLAYERS][PlayerMarkerData]; 70 | 71 | 72 | static IsValidMarker(markerid) { 73 | return !( 74 | 75 | markerData[markerid][markerPosition][0] == 0.0 && 76 | markerData[markerid][markerPosition][1] == 0.0 && 77 | markerData[markerid][markerPosition][2] == 0.0 78 | ); 79 | } 80 | 81 | static GetFreeMarkerID() { 82 | 83 | for (new i = 0; i < MAX_MARKERS; i++) { 84 | 85 | if (!IsValidMarker(i)) 86 | return i; 87 | } 88 | return INVALID_MARKER_ID; 89 | } 90 | 91 | static GetIconLetter(icon) { 92 | 93 | return ICON_LETTER[icon]; 94 | } 95 | 96 | static GetIconFont(icon) { 97 | 98 | return ICON_FONT[icon]; 99 | } 100 | 101 | static Player_CreateMarkers(playerID) { 102 | 103 | for (new i = 0; i < MAX_MARKERS; i++) { 104 | 105 | if (!IsValidMarker(i)) 106 | continue; 107 | 108 | playerMarkerData[playerID][markerObject][i] = CreatePlayerObject( 109 | playerID, 110 | 19197, 111 | markerData[i][markerPosition][0], markerData[i][markerPosition][1], markerData[i][markerPosition][2], 112 | 0.0, 0.0, 0.0, 113 | markerData[i][markerDrawDistance] 114 | ); 115 | 116 | SetPlayerObjectMaterial( 117 | playerID, 118 | playerMarkerData[playerID][markerObject][i], 119 | 0, 18646, 120 | "matcolours", "lightblue", 0x00000000 121 | ); 122 | 123 | playerMarkerData[playerID][markerObjectIcon][i] = CreatePlayerObject( 124 | playerID, 125 | 11737, 126 | markerData[i][markerPosition][0], markerData[i][markerPosition][1], (markerData[i][markerPosition][2] + 1.5), 127 | 90.0, 0.0, 0.0, 128 | markerData[i][markerDrawDistance] 129 | ); 130 | 131 | SetPlayerObjectMaterialText( 132 | playerID, 133 | playerMarkerData[playerID][markerObjectIcon][i], 134 | GetIconLetter(markerData[i][markerIcon]), 0, OBJECT_MATERIAL_SIZE_256x256, 135 | GetIconFont(markerData[i][markerIcon]), 150, 1, 0xFFF8F8FF, 0x00000000, 1 136 | ); 137 | playerMarkerData[playerID][markerVisible][i] = true; 138 | } 139 | } 140 | 141 | static Player_DestroyMarkers(playerID) { 142 | 143 | for (new i = 0; i < MAX_MARKERS; i++) { 144 | 145 | if (playerMarkerData[playerID][markerObjectIcon][i] >= 0) { 146 | DestroyPlayerObject(playerID, playerMarkerData[playerID][markerObjectIcon][i]); 147 | playerMarkerData[playerID][markerObjectIcon][i] = INVALID_OBJECT_ID; 148 | DestroyPlayerObject(playerID, playerMarkerData[playerID][markerObject][i]); 149 | playerMarkerData[playerID][markerObject][i] = INVALID_OBJECT_ID; 150 | playerMarkerData[playerID][markerVisible][i] = false; 151 | } 152 | } 153 | } 154 | 155 | static Player_SetIconFace(playerID) { 156 | 157 | for (new i = 0; i < MAX_MARKERS; i++) { 158 | 159 | if (!IsValidMarker(i)) 160 | continue; 161 | 162 | if (!playerMarkerData[playerID][markerVisible][i]) 163 | continue; 164 | 165 | new Float:playerPosition[3]; 166 | GetPlayerPos(playerID, playerPosition[0], playerPosition[1], playerPosition[2]); 167 | 168 | new Float:objectPosition[3]; 169 | GetPlayerObjectPos( 170 | playerID, 171 | playerMarkerData[playerID][markerObjectIcon][i], 172 | objectPosition[0], 173 | objectPosition[1], 174 | objectPosition[2] 175 | ); 176 | 177 | playerPosition[2] = atan2(playerPosition[1] - objectPosition[1], playerPosition[0] - objectPosition[0]) - 90.0; 178 | 179 | SetPlayerObjectRot( 180 | playerID, 181 | playerMarkerData[playerID][markerObjectIcon][i], 182 | 90.0, 0.0, playerPosition[2] + 180 183 | ); 184 | } 185 | } 186 | 187 | 188 | forward OnPlayerEnterMarker(playerid, markerid); 189 | forward OnPlayerLeaveMarker(playerid, markerid); 190 | 191 | 192 | stock CreateMarker(icon, calledActive, Float:x, Float:y, Float:z, worldID = -1, interiorID = -1, Float:drawDistance = 0.0) { 193 | 194 | new markerid = GetFreeMarkerID(); 195 | if (markerid == INVALID_MARKER_ID) { 196 | return printf("(!) Marker.INC -> Warning : Reached limit. (MAX_MARKERS: %d)", MAX_MARKERS); 197 | } 198 | 199 | markerData[markerid][markerCalledArea] = CreateDynamicCylinder(x, y, (z - 0.1), (z + 10.0), 1.0, worldID, interiorID, -1); 200 | 201 | markerData[markerid][markerIcon] = icon; 202 | markerData[markerid][markerCalledArea] = calledActive; 203 | markerData[markerid][markerPosition][0] = x; 204 | markerData[markerid][markerPosition][1] = y; 205 | markerData[markerid][markerPosition][2] = z; 206 | markerData[markerid][markerWorldID] = worldID; 207 | markerData[markerid][markerInteriorID] = interiorID; 208 | markerData[markerid][markerDrawDistance] = drawDistance; 209 | 210 | return markerid; 211 | } 212 | 213 | stock DestroyMarker(markerid) { 214 | 215 | new markerDataVoid[MarkerData]; 216 | markerData[markerid] = markerDataVoid; 217 | 218 | for (new i = GetPlayerPoolSize(); i >= 0; i--) { 219 | 220 | if (!IsPlayerConnected(i)) 221 | continue; 222 | 223 | if (playerMarkerData[i][markerObjectIcon][markerid] >= 0) { 224 | DestroyPlayerObject(i, playerMarkerData[i][markerObjectIcon][markerid]); 225 | playerMarkerData[i][markerObjectIcon][markerid] = INVALID_OBJECT_ID; 226 | } 227 | } 228 | } 229 | 230 | 231 | public OnPlayerEnterDynamicArea(playerid, STREAMER_TAG_AREA:areaid) { 232 | 233 | for (new i = 0; i < MAX_MARKERS; i++) { 234 | 235 | if (!IsValidMarker(i)) 236 | continue; 237 | 238 | if (!markerData[i][markerCalledArea]) 239 | continue; 240 | 241 | if (areaid == markerData[i][markerCalledArea]) { 242 | 243 | CallRemoteFunction("OnPlayerEnterMarker", "ii", playerid, i); 244 | } 245 | } 246 | 247 | #if defined MPHook_OnPlayerEnterDynamicArea 248 | return MPHook_OnPlayerEnterDynamicArea(playerid, STREAMER_TAG_AREA:areaid); 249 | #else 250 | return 1; 251 | #endif 252 | } 253 | #if defined _ALS_OnPlayerEnterDynamicArea 254 | #undef OnPlayerEnterDynamicArea 255 | #else 256 | #define _ALS_OnPlayerEnterDynamicArea 257 | #endif 258 | 259 | #define OnPlayerEnterDynamicArea MPHook_OnPlayerEnterDynamicArea 260 | #if defined MPHook_OnPlayerEnterDynamicArea 261 | forward MPHook_OnPlayerEnterDynamicArea(playerid, STREAMER_TAG_AREA:areaid); 262 | #endif 263 | 264 | public OnPlayerLeaveDynamicArea(playerid, STREAMER_TAG_AREA:areaid) { 265 | 266 | for (new i = 0; i < MAX_MARKERS; i++) { 267 | 268 | if (!IsValidMarker(i)) 269 | continue; 270 | 271 | if (!markerData[i][markerCalledActive]) 272 | continue; 273 | 274 | if (areaid == markerData[i][markerCalledArea]) { 275 | 276 | CallRemoteFunction("OnPlayerLeaveMarker", "ii", playerid, i); 277 | } 278 | } 279 | 280 | #if defined MPHook_OnPlayerLeaveDynamicArea 281 | return MPHook_OnPlayerLeaveDynamicArea(playerid, STREAMER_TAG_AREA:areaid); 282 | #else 283 | return 1; 284 | #endif 285 | } 286 | #if defined _ALS_OnPlayerLeaveDynamicArea 287 | #undef OnPlayerLeaveDynamicArea 288 | #else 289 | #define _ALS_OnPlayerLeaveDynamicArea 290 | #endif 291 | 292 | #define OnPlayerLeaveDynamicArea MPHook_OnPlayerLeaveDynamicArea 293 | #if defined MPHook_OnPlayerLeaveDynamicArea 294 | forward MPHook_OnPlayerLeaveDynamicArea(playerid, STREAMER_TAG_AREA:areaid); 295 | #endif 296 | 297 | public OnPlayerUpdate(playerid) { 298 | 299 | if (!IsPlayerConnected(playerid)) 300 | return 0; 301 | 302 | for (new i = 0; i < MAX_MARKERS; i++) { 303 | 304 | if (!IsValidMarker(i)) 305 | continue; 306 | 307 | new Float:playerPosition[3]; 308 | GetPlayerPos(playerid, playerPosition[0], playerPosition[1], playerPosition[2]); 309 | 310 | if ( 311 | playerPosition[0] > markerData[i][markerPosition][0] - 5.0 && playerPosition[1] > markerData[i][markerPosition][1] - 5.0 && 312 | playerPosition[0] < markerData[i][markerPosition][0] + 5.0 && playerPosition[1] < markerData[i][markerPosition][1] + 5.0 313 | ) { 314 | 315 | if (playerMarkerData[playerid][markerVisible][i]) { 316 | SetPlayerObjectMaterialText( 317 | playerid, 318 | playerMarkerData[playerid][markerObjectIcon][i], 319 | GetIconLetter(markerData[i][markerIcon]), 0, OBJECT_MATERIAL_SIZE_256x256, 320 | GetIconFont(markerData[i][markerIcon]), 150, 1, 0x00000000, 0x00000000, 1 321 | ); 322 | 323 | SetPlayerObjectPos( 324 | playerid, 325 | playerMarkerData[playerid][markerObjectIcon][i], 326 | markerData[i][markerPosition][0], 327 | markerData[i][markerPosition][1], 328 | ((markerData[i][markerPosition][2] + 1.5) * 2) 329 | ); 330 | 331 | playerMarkerData[playerid][markerVisible][i] = false; 332 | } 333 | } 334 | else { 335 | 336 | if (!playerMarkerData[playerid][markerVisible][i]) { 337 | 338 | SetPlayerObjectMaterialText( 339 | playerid, 340 | playerMarkerData[playerid][markerObjectIcon][i], 341 | GetIconLetter(markerData[i][markerIcon]), 0, OBJECT_MATERIAL_SIZE_256x256, 342 | GetIconFont(markerData[i][markerIcon]), 150, 1, 0xFFF8F8FF, 0x00000000, 1 343 | ); 344 | 345 | SetPlayerObjectPos( 346 | playerid, 347 | playerMarkerData[playerid][markerObjectIcon][i], 348 | markerData[i][markerPosition][0], 349 | markerData[i][markerPosition][1], 350 | (markerData[i][markerPosition][2] + 1.5) 351 | ); 352 | 353 | playerMarkerData[playerid][markerVisible][i] = true; 354 | } 355 | } 356 | Player_SetIconFace(playerid); 357 | } 358 | 359 | #if defined MPHook_OnPlayerUpdate 360 | return MPHook_OnPlayerUpdate(playerid); 361 | #else 362 | return 1; 363 | #endif 364 | } 365 | #if defined _ALS_OnPlayerUpdate 366 | #undef OnPlayerUpdate 367 | #else 368 | #define _ALS_OnPlayerUpdate 369 | #endif 370 | 371 | #define OnPlayerUpdate MPHook_OnPlayerUpdate 372 | #if defined MPHook_OnPlayerUpdate 373 | forward MPHook_OnPlayerUpdate(playerid); 374 | #endif 375 | 376 | public OnPlayerConnect(playerid) { 377 | 378 | Player_CreateMarkers(playerid); 379 | 380 | #if defined MPHook_OnPlayerConnect 381 | return MPHook_OnPlayerConnect(playerid); 382 | #else 383 | return 1; 384 | #endif 385 | } 386 | #if defined _ALS_OnPlayerConnect 387 | #undef OnPlayerConnect 388 | #else 389 | #define _ALS_OnPlayerConnect 390 | #endif 391 | 392 | #define OnPlayerConnect MPHook_OnPlayerConnect 393 | #if defined MPHook_OnPlayerConnect 394 | forward MPHook_OnPlayerConnect(playerid); 395 | #endif 396 | 397 | public OnPlayerDisconnect(playerid, reason) { 398 | 399 | Player_DestroyMarkers(playerid); 400 | 401 | #if defined MPHook_OnPlayerDisconnect 402 | return MPHook_OnPlayerDisconnect(playerid, reason); 403 | #else 404 | return 1; 405 | #endif 406 | } 407 | #if defined _ALS_OnPlayerDisconnect 408 | #undef OnPlayerDisconnect 409 | #else 410 | #define _ALS_OnPlayerDisconnect 411 | #endif 412 | 413 | #define OnPlayerDisconnect MPHook_OnPlayerDisconnect 414 | #if defined MPHook_OnPlayerDisconnect 415 | forward MPHook_OnPlayerDisconnect(playerid, reason); 416 | #endif 417 | --------------------------------------------------------------------------------