Maintenance best practices
Coordinates

Perhaps I will continue with a series on best practices, perhaps I will not. Time will tell.

What and why

This isn't a tutorial about how to get coordinates. It is merely a set of what I think are "best practices" in regards to coordinates. I set myself one rule: I only write a set of coordinates ONCE and I don't copy it anywhere else. Why? Maintenance! Consider this example:

PHP Code:
switch(random(10))
{
/* cases */

case 7: SetPlayerCheckpoint(playerid, 1013.45, 2542.54, 13.43, 3.0);

/* cases */
}

/*

1000 more lines of code

*/

if(IsPlayerInRangeOfPoint(playerid, 3.0, 1013.45, 2542.54, 13.43))
{
// stuff
}
I see this very often. Now, should I want to move the checkpoint to another location I would have to edit those coordinates in two, or possibly even more places. This is cumbersome and - if I don't meticulously replace every single instance - prone to logic errors. The gamemode will still compile and all, but it won't work in-game. This is frustrating and hard to debug.

Solutions

There are multiple viable solutions and there isn't really "one solution to rule them all" (in a LOTR reference) because it all depends on what you're doing. If you're creating a race you would go differently about it than if you were creating some checkpoints in stores. What is important is that you stick to the rule: only write a set of coordinates ONCE.

Single set

If you only have one or a few sets of coordinates a possible solution might be to simply put a definition at the top of your script:

PHP Code:
#define MY_LOCATION 1013.45, 2542.54, 13.43
// OR
#define MY_LOCATION_X (1013.45)
#define MY_LOCATION_Y (2542.54)
#define MY_LOCATION_Z (13.43)
Multiple sets

Frequently you will be using an array.

PHP Code:
new const Float:gRaceCheckpoints[][3] = {
{1580.72, 1580.66, 11.45},
{2063.74, 1644.50, 8.68},
{1013.45, 2542.54, 13.43},
{1761.64, 2590.44, 16.04},
{2603.64, 1581.00, 3.50}
}

new gCurrentVisibleCheckpoint[MAX_PLAYERS] = {-1, ...};
If a checkpoint is enabled for a player, change the variable accordingly. For example, if I set the visible checkpoint to 2 then I know that the player's visible checkpoint is at 1013.45, 2542.54, 13.43 (array indices start at 0). This is incredibly useful when creating a checkpoint sequence, like a race. Or a sweeper job, or what have you. If using race checkpoints (as opposed to normal checkpoints) you can even point the arrow in the right direction by pulling the coordinates from the next checkpoint from the array (careful: exclude the last checkpoint).

Streamer plugin

If you are using the streamer plugin (many people are) then use it to its fullest. Locations (and more) for all entities are stored in memory and can be retrieved with creative use of the data manipulation natives. Also liberally use the STREAMER_EXTRA_ID attribute to store extra vital information. In some cases you might be able to create entities (checkpoint, pickup, object, ...) straight from dynamic storage without bothering to assign the entity id to a variable. If the entity belongs to, say, a faction then I can store the (SQL) factionID in the STREAMER_EXTRA_ID attribute as it is created. As the player interacts with the entity (enters the checkpoint, picks up a pickup, shoots an object, ...) I can get the factionID for that entity from memory and use it to query the database directly.