25.03.2017, 17:37
Requirements
izcmd
sscanf
Let's start by making a few defines to help version our game mode, if you already have these or simply don't want to use them, skip past this step.
Now, we're going to need to create a few variables to work in the background with our DM system. This part is pretty straight forward. We have a variable to keep track of if the user is in a DM Zone or not. We also have a variable to keep track of which zone the player is in.Код:// Gamemode related defines. #define GM "DM Zones" // The name of your game mode. #define GM_VERSION_MAJOR 1 // Any major update which significantly changes the gamemode. #define GM_VERSION_MINOR 0 // Any minor update which makes some small changes or additions. #define GM_VERSION_PATCH 0 // Bug fixes or very tiny updates. // DM Zone defines #define DIALOG_DM_ZONES 100 // Our DM Zone dialog will have the ID of 100, just to make sure it doesn't overlap anything else.
Now we'll create arrays for each of our DM arenas, you can have one of these, or you can have hundreds, the sky is the limit.Код:// DM Zone feature variables. new bool: InDM[MAX_PLAYERS]; // If the player is currently in any DM zone. Boolean because this can only be either true or false. new DM[MAX_PLAYERS]; // The DM arena in which the player is currently participating in.
Notice the number 5 where we've created our float/array. That 5 represents the number of items within the array. Note that there are in fact 6 items in the array. The reason the number that we've put in is 5 is because the first item in the array is always 0, counting upwards.
As I said, you can feel free to make as many of these as you wish, just make sure to use a different name for each now one that you create.
Here we make use of those defines we made at the beginning of the tutorial to change the server's hostname at the initiation of the gamemode.Код:// DM Zone spawnpoint arrays. new Float:DMZeroSpawns[][5] = // DM 0 Spawns (LV) { {2032.3732,1343.5039,10.8203,269.5058}, {2055.6482,1335.1000,10.8167,67.7109}, {2039.6138,1323.9529,10.6719,333.1272}, {2052.9148,1366.2819,10.6719,147.8749}, {2044.8967,1378.8566,10.6719,185.4314}, {2027.6637,1374.3524,10.8203,231.7049} };
We need to make sure that when the player connects, their DM zone is not an actual zone that is being used for players deathmatching. I've set it to 1000, there's probably an easier way around this, but i wanted to be safe.Код:public OnGameModeInit() { new string[128]; // We'll need a string to hold our data. This probably could be smaller than 128, but we'll play it safe. SetGameModeText(GM); // Sets our gamemode text to our gamemode that we set earlier. format(string, sizeof(string), "hostname %s v%i.%i.%i", GM, GM_VERSION_MAJOR, GM_VERSION_MINOR, GM_VERSION_PATCH); // We concatenate the string with the data in our defines to display it as plain text/numbers. SendRconCommand(string); // This simply sends an Rcon command at the gamemode init, specifically to set our hostname. AddPlayerClass(58, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0); // You'll need a class so the player can spawn. return 1; }
Below we make use of an IF/Else statement and a switch to take care of our spawning. IF the player is in a deathmatch arena, we check which DM they're in (This is where the DM variable comes in), then apply the spawn settings we need for that DM zone. IF they are not in a deathmatch arena, we'll spawn them normally. The random generator is used to spawn the players in a random point of the array, pretty self explanatory.Код:public OnPlayerConnect(playerid) { DM[playerid] = 1000; // This is being set to a high number simply because our first DM will be DM 0. This could be avoided with the first DM being 1. return 1; }
Below we'll make a command to display this dialog, but for now, let's set up what the server will do when a player responds to the dialog they're given.Код:public OnPlayerSpawn(playerid) { if(InDM[playerid] == true) { switch (DM[playerid]) { case 0: { GivePlayerWeapon(playerid, 24, 1000); SetPlayerHealth(playerid, 99); SetPlayerArmour(playerid, 99); new spawn = random(sizeof(DMZeroSpawns)); SetPlayerPos(playerid, DMZeroSpawns[spawn][0], DMZeroSpawns[spawn][1], DMZeroSpawns[spawn][2]); SetPlayerFacingAngle(playerid, DMZeroSpawns[spawn][3]); } } } else { SetPlayerHealth(playerid, 99); SetPlayerArmour(playerid, 99); } return 1; }
Now we'll make our commands to pull this all together. We'll start with DM and DMLIST. DM is a shortcut to simply type a number in which they wish to join. DMLIST shows that dialog we made earlier.Код:public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) { new string[128], playerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, playerName, sizeof(playerName)); if(dialogid == DIALOG_DM_ZONES) // IF the dialog is the one we've made for DM Zones. { if(response) // IF they user in fact responded to the dialog. { switch(listitem) // Check which option was chosen when they responded. We only have one for now. The next would be case 1, then case 2 and so on. { case 0: { InDM[playerid] = true; DM[playerid] = 0; SpawnPlayer(playerid); } } format(string, sizeof(string), "{77B3D9}[DM Zones] {ffffff}%s(%i) has just entered {77B3D9}DM zone %i {ffffff}(/dm)", playerName, playerid, DM[playerid]); SendClientMessageToAll(-1, string); return 1; } } return 0; }
Finally, we'll need a command to let the player leave the DM arena they're in when they either want to switch to another, or just get back to the spawn of your server. We'll also check to make sure the user isn't trying to leave the dm to avoid dying.Код:CMD:dm(playerid, params[]) { new string[128], playerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, playerName, sizeof(playerName)); if(InDM[playerid] == true) // Once again, if they're in a DM arena. { return SendClientMessage(playerid, -1, "You're already in a DM arena. (/dmleave)"); // They can't join if they're already in an arena, that wouldn't make sense. } else if(sscanf(params,"i",DM[playerid])) return SendClientMessage(playerid, -1, "USAGE: /dm <zoneID> (/dmlist)"); // We use sscanf to look for an integer value provided by the user when they type DM as a command. { switch (DM[playerid]) // We switch through cases in search of the provided integer. As I said, you can add as many as you like. You could get more in depth and check to see if the DM they provide is valid. But this is a simple tutorial. { case 0: { InDM[playerid] = true; DM[playerid] = 0; SpawnPlayer(playerid); } } format(string, sizeof(string), "{77B3D9}[DM Zones] {ffffff}%s(%i) has just entered {77B3D9}DM zone %i {ffffff}(/dm)", playerName, playerid, DM[playerid]); SendClientMessageToAll(-1, string); } return 1; } CMD:dmlist(playerid, params[]) { ShowPlayerDialog(playerid, DIALOG_DM_ZONES, DIALOG_STYLE_LIST, "DM Zones", "DM 0 - LV", "Enter", "Cancel"); // Shows the player a LIST of our DM Zones. To add more, simply make a new like with \n. return 1; }
That's all folks. A very short and simple DM Zone system to help get your system started. I hope that I was descriptive enough in my explanations of the code. If I wasn't, let me know and I'll try to clear up and confusion or questions that anyone has.Код:CMD:leavedm(playerid, params[]) { new Float:pHealth; // A float to store the player's HP value. GetPlayerHealth(playerid, pHealth); // We store the player's health to the variable we made above. if(pHealth > 75.0 && InDM[playerid] == true) // IF the player's health is greater than 75 AND he's in a DM, we'll remove him from it as requested. { InDM[playerid] = false; DM[playerid] = 1000; SendClientMessage(playerid, -1, "You have left the deathmatch arena and have been sent to the default spawn."); SpawnPlayer(playerid); } else if(pHealth < 75.0 && InDM[playerid] == true) // Otherwise if the player has LESS than 75 HP in an arena, he'll be told that he simply cannot leave with less than 75 HP. { SendClientMessage(playerid, -1, "You must have more than 75 health to leave the DM arena."); } else { SendClientMessage(playerid, -1, "You're not in any deathmatch arena."); // If the player for some reason tries to leave a DM arena that he's not in, we'll tell him that he's not in a deathmatch zone. } return 1; }