Sandra Geplaatst: 27 januari 2009 Rapport Geplaatst: 27 januari 2009 (bewerkt) [Tutorial]Multi-Param Commando's Maken Welkom bij deze tutorial waarin ik je ga uitleggen hoe je commando's maakt met meerdere parameters. Lees deze tutorial goed en zorgvuldig door. Dus stap voor stap. Vooral bij admin-commando's word vaak 1, 2 of zelfs 3 extra parameters gebruikt. Zoals: - /kick [id] - /giveplayermoney [id] [amount] - /giveplayerweapon [id] [wapenid] [kogels] Ik ga er wel vanuit dat je de basis script-technieken onder de knie hebt. Een simpel commando maken is niet zo'n probleem: if(strcmp("/skatepark", cmdtext, true) == 0) { SetPlayerPos(playerid, 1922.5964, -1399.8970, 13.5703); SendClientMessage(playerid, COLOR_GREEN, "***Je bent naar het Skatepark geteleporteerd!"); return 1; } Maar als je nou als admin andere spelers ernaartoe wilt teleporteren, dan word het al een stuk lastiger omdat er een playerid moet worden doorgegeven. Je kan het natuurlijk zo doen: if(strcmp("/skatepark 0", cmdtext, true) == 0) { SetPlayerPos(0, 1922.5964, -1399.8970, 13.5703); SendClientMessage(0, COLOR_GREEN, "***Je bent naar het Skatepark geteleporteerd!"); return 1; } if(strcmp("/skatepark 1", cmdtext, true) == 0) { SetPlayerPos(1, 1922.5964, -1399.8970, 13.5703); SendClientMessage(1, COLOR_GREEN, "***Je bent naar het Skatepark geteleporteerd!"); return 1; } //enzovoort Maar om dat nou 200 keer te doen voor elk commando... dan word het een gekkenwerk. Daarom is er een functie gemaakt voor sa-mp die het ingevoerde commando (cmdtext) scheidt in losse stukjes. Het commando word gescheiden bij de spaties. Deze functie wordt "strtok" genoemd. Bijvoorbeeld, een admin voert het commando "/giveplayerweapon 4 30 560" (Geef playerid '4' een AK47 (WapenID 30) met 560 kogels.) Strtok zal deze commandregel scheiden in: /giveplayerweapon 4 30 560 Oke, om dit soort commando's aan je script toe te voegen, dien je eerst de strtok-functie onderaan script zetten: strtok(const string[], &index) { new length = strlen(string); while ((index < length) && (string[index] <= ' ')) { index++; } new result[20], offset = index; while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1))) { result[index - offset] = string[index]; index++; } result[index - offset] = EOS; return result; } Je hoeft echt niets van deze bovenstaande code te begrijpen. Laat het lekker staan en verander er niets aan. De volgende stap is een een nieuwe string en wat variabele's aanmaken. Dit doe je bovenaan de OnPlayerCommandText-callback: new cmd[256], idx, tmp[256]; Nu is het tijd om de eerste parameter (het commando zelf) uit de cmdtext te halen: cmd = strtok(cmdtext, idx); Dit zet je ook bovenaan de OnPlayerCommandText-callback: public OnPlayerCommandText(playerid, cmdtext[]) { new cmd[256], idx, tmp[256]; cmd = strtok(cmdtext, idx); //hier komen straks de commando's return 0; } De functie 'strcmp' (afkorting van string-compare (compare = vergelijk)) vergelijkt 2 strings met elkaar. Het is nu dat we de ingevoerde commando gaan vergelijken met een beschikbaar commando. Als voorbeeld neem ik het commando /giveplayerweapon Het is hetzelfde als normale commando's, alleen vervangen we de "cmdtext" in de eerste regel van elk commando met "cmd": if(strcmp(cmd, "/giveplayerweapon", true)==0) { Als een admin /giveplayerweapon heeft ingevoerd, dan gaan gaan we verder. We moeten eerst nog een paar variabelen aanmaken om het playerid, wapenid en aantal kogels in op te slaan: new giveplayerid, weaponid, ammo; Even een overzichtje, tot nu toe hebben we dit: public OnPlayerCommandText(playerid, cmdtext[]) { new cmd[256], idx, tmp[256]; cmd = strtok(cmdtext, idx); if(strcmp(cmd, "/giveplayerweapon", true)==0) { new giveplayerid, weaponid, ammo; } return 0; } We gaan nu de tweede parameter (het playerid) eruit halen, deze slaan we tijdelijk op in de 'tmp'string: tmp = strtok(cmdtext, idx); Soms wil het nog wel eens per ongeluk gebeuren dat je een parameter vergeet in te vullen. In dat geval moeten we de admin een error gegeven: Om te checken of er wel of geen text/getal is ingevoerd, gebruiken we '!strlen' (string-length). Met dat uitroepteken (!) geven we aan dat iets 'niet zo is'. Dus if(!strlen(tmp)) betekent eigenlijk "Als 'tmp' geen lengte heeft" In dat geval geven we de admin dus een berichte met de te uitleg hoe hij/zij het commando moet gebruiken: if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } Omdat de playerid's zoals sa-mp ze kent 'integers' zijn, moeten we de string (tmp) die we nu hebben, omzetten naar een integer, dat doen we met de functie 'strval': giveplayerid = strval(tmp); Overzicht wat we tot nu toe hebben: public OnPlayerCommandText(playerid, cmdtext[]) { new cmd[256], idx, tmp[256]; cmd = strtok(cmdtext, idx); if(strcmp(cmd, "/giveplayerweapon", true)==0) { new giveplayerid, weaponID, ammo; tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } giveplayerid = strval(tmp); } return 0; } Nu hebben we dus de playerid van de diegene die het wapen krijgt opgeslagen in 'giveplayerid'. Dat was het hele proces om zo'n 2e parameter te krijgen. Om de volgende param te krijgen (weaponID), herhaal je deze code: tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } weaponID = strval(tmp); Let nu dus op dat we aan het 'weaponID' hebben gebruikt om dat getal op te slaan. Bij de volgende zullen we het getal in de 'ammo'-variabele opslaan: tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } ammo = strval(tmp); We zijn bijna klaar met dit commando, we hebben nu alle gegevens die we nodig hebben: Het ID van degene die het wapen krijgt is opgeslagen in 'giveplayerid' Het ID van het wapen die de speler krijgt is opgeslagen in 'weaponID' En het aantal kogels is opgeslagen in 'ammo' Overzicht: public OnPlayerCommandText(playerid, cmdtext[]) { new cmd[256], idx, tmp[256]; cmd = strtok(cmdtext, idx); if(strcmp(cmd, "/giveplayerweapon", true)==0) { new giveplayerid, weaponID, ammo; tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } giveplayerid = strval(tmp); tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } weaponID = strval(tmp); tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /giveplayerweapon [id] [wapenid] [kogels]"); return 1; //Stopt het commando } ammo = strval(tmp); } return 0; } Nu rest ons een paar dingen te checken: - Is de ingevoerde speler wel online? - Is er wel een geldig wapenID ingevoerd? - Is het aantal ingevoerde kogels niet onder '0'? if(!IsPlayerConnected(giveplayerid)) { SendClientMessage(playerid, 0xFF0000AA, "Speler is niet online"); return 1; } if(weaponID < 1 || weaponID > 46) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik een wapenid tussen de 0 en 46"); return 1; } if(ammo < 1) { SendClientMessage(playerid, 0xFF0000AA, "Je moet minimaal 1 kogel geven!"); return 1; } We moeten ook nog kijken of de degene die het commando invoerd, wel een admin is. Om te zorgen dat niet-admin een "Unknown Command"bericht krijgt, zetten we dit in het commando: if(!IsPlayerAdmin(playerid)) return 0; (Het beste eigenlijk direct bovenaan het commando. Mochten de ingevoerde gegevens allemaal geldig te zijn, dan kunnen we de speler het wapen geven en een berichtje sturen naar de admin en ontvanger: GivePlayerWeapon(giveplayerid, weaponID, ammo); SendClientMessage(playerid, 0x00FF00AA, "Wapen gegeven!"); SendClientMessage(giveplayerid, 0xF00FF00AA, "Je hebt een wapen van een admin gekregen!"); En vergeet niet return 1; om het commando af te sluiten. Het totale commando word nu een beetje te groot om hier te plaatsen, dus ik gebruik nu even www.pastebin.com http://pastebin.com/f2a97d58b Dat was dus een commando met 3 extra parameters. Deze zijn erg lang, een commando met maar 1 extra parameter is natuurlijk veel korter. Voorbeeld /freeze [playerid]: if(strcmp(cmd, "/freeze", true)==0) { if(!IsPlayerAdmin(playerid)) return 0; new giveplayerid; tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, 0xFF0000AA, "Gebruik: /freeze [id]"); return 1; //Stopt het commando } giveplayerid = strval(tmp); if(!IsPlayerConnected(giveplayerid)) { SendClientMessage(playerid, 0xFF0000AA, "Speler is niet online"); return 1; } TogglePlayerControllable(giveplayerid, 0); SendClientMessage(playerid, 0x00FF00AA, "Speler bevroren"); SendClientMessage(giveplayerid, 0xFF0000AA, "Je bent bevroren door een admin"); return 1; } Dit commando samen met het /giveplayerweapon commando: http://pastebin.com/f16cebf8e Nog 1 script met een aantal bruikbare commando's die ik vlug in elkaar hebt gezet. Lees het helemaal rustig door, en probeer regel voor regel te begrijpen wat het doet en hoe het werkt. Commando's: /giveplayerweapon [playerid] [wapenID] [aantal kogels] /freeze [playerid] /unfreeze [playerid] /kick [playerid] /giveplayermoney [playerid] [bedrag] http://pastebin.com/f358868e9 Mochten er nog vragen zijn, stel ze gerust in dit topic. =>Sandra<= Bewerkt: 27 januari 2009 door =>Sandra<= Reageren
Freaksken Geplaatst: 27 januari 2009 Rapport Geplaatst: 27 januari 2009 (bewerkt) Mooie tut, ik zal er veel aan hebben! Net zoals al je andere tuts! Bewerkt: 27 januari 2009 door Freaksken Reageren
Big Boss Geplaatst: 28 januari 2009 Rapport Geplaatst: 28 januari 2009 (bewerkt) Uiteraard had ik dit lang geleden al uitgeknobbeld, maar toch kan hij mooi bij mijn collectie SA-MP Scripting in mijn Bladwijzers. Eerlijk gezegd vind ik dit er wel veel ingewikkelder uit zien dan zelfs je /register en /login commando's, al denk ik dat dat vooral komt doordat het forum de script regels afbreekt en omdat ik een totaal andere script stijl gebruik (als er een if staat, moet er bij mij ook altijd een else bij, gewoon om het overzichtelijk te houden). Vooral de iets gevorderde scripters zullen hier iets aan hebben, denk ik. Leren werken met strtok en strval doe je namelijk niet op 1, 2, 3. Bewerkt: 28 januari 2009 door Big Boss Reageren
jorD1 Geplaatst: 4 februari 2009 Rapport Geplaatst: 4 februari 2009 (bewerkt) Ik heb de /freeze cmd gebruikt en aangepast maar als ik het if(!IsPlayerAdmin(playerid)) return 0; aan pas naar: if(adminlevel[playerid] > 1) return 0; uit Sandra's login systeem doet /freeze helemaal niks als ik de zin weg haal werkt het wel en als ik return 0; weghaal krijg ik heel veel errors ??? de aanpassing aan /freeze zijn vrij groot zie maar en het werkt maar zodra de regel if(adminlevel[playerid] > 1) return 0; erbij komt werkt /freeze niet meer het. if(strcmp(cmd, "/freeze", true)==0) { if(adminlevel[playerid] > 1) return 0; new giveplayerid; new pName[MAX_PLAYER_NAME]; new opName[MAX_PLAYER_NAME]; new string[256]; GetPlayerName(playerid, pName, sizeof(pName)); GetPlayerName(giveplayerid, opName, sizeof(opName)); tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, COLOR_RED, "USAGE: /freeze [iD]"); return 1; //Stopt het commando } giveplayerid = strval(tmp); if(!IsPlayerConnected(giveplayerid)) { SendClientMessage(playerid, 0xFF0000AA, "Player not found"); return 1; } TogglePlayerControllable(giveplayerid, 0); format(string, sizeof(string), "*** Admin %s freezed player %s!!!", pName, opName); SendClientMessageToAll(COLOR_RED, string); return 1; } ps: opName = de naam van de freezed player Al opgelost het regeltje moest onder tmp = strtok(cmdtext, idx); komen kwam er achter toen ik iemands anders probleem zat te bekijken Bewerkt: 4 februari 2009 door jorD1 Reageren
Sandra Geplaatst: 4 februari 2009 Auteur Rapport Geplaatst: 4 februari 2009 Oke, maar let wel op dat nu je command alleen voor level 1 admins en normale spelers te gebruiken is... if(adminlevel[playerid] > 1) return 0; '>' betekend "Is Groter Dan" Dus als adminlevel[playerid] groter is dan 1, dan moet het commando worden stopgezet, en kan de speler het niet gebruiken. Ik denk dus dat je de '>' moet veranderen naar '<' Reageren
jorD1 Geplaatst: 4 februari 2009 Rapport Geplaatst: 4 februari 2009 Oke, maar let wel op dat nu je command alleen voor level 1 admins en normale spelers te gebruiken is... if(adminlevel[playerid] > 1) return 0; '>' betekend "Is Groter Dan" Dus als adminlevel[playerid] groter is dan 1, dan moet het commando worden stopgezet, en kan de speler het niet gebruiken. Ik denk dus dat je de '>' moet veranderen naar '<' nee het zat anders lees onderste 2 regels van die andere post maar Reageren
sean5874 Geplaatst: 4 december 2009 Rapport Geplaatst: 4 december 2009 Is het met deze param commands nodig om bij 'freeze [id]' getallen in te vullen zoals 'ID = 1 of kan je gewoon de spelers hun namen gebruiken? Reageren
Megadreams Geplaatst: 4 december 2009 Rapport Geplaatst: 4 december 2009 Het is nodig om de ids in te voeren, je kan enkele checks gebruiken om dat te veranderen of gewoon simpelweg DCMD en SSCANF gebruiken, check de master tutorial list voor handige tuts als die van dcmd Reageren
Recommended Posts
Een reactie plaatsen
Je kan nu een reactie plaatsen en pas achteraf registreren. Als je al lid bent, log eerst in om met je eigen account een reactie te plaatsen.