I'm glad you asked for further explanation than most new users don't. So I will run you through your code line by line. So 'cmdtext' is the text that you enter in the input box followed by a '/'. So basically by adding a '/' as the first character in your input box, opened by 'T', '`' or 'F6' by default, you are typing a command which is then passed through OnPlayerCommandText.
For example, if I type '/mycommand' in-game, it will run it through OnPlayerCommandText like this:
Код:
OnPlayerCommandText(playerid, "/mycommand");
Where 'playerid' is the number or ID that your client is currently playing with, which is the ID used to separate each player from each other, to make them all unique. Read more here:
https://sampwiki.blast.hk/wiki/OnPlayerCommandText
Now to the more important part... what your command is actually doing currently.
pawn Код:
if(strcmp("/tower", cmdtext, true, 10) == 0)
What this translate to is something like:
if the comparison of the two strings, "/tower" and cmdtext (cmdtext being what you entered in the input box), and having the two being case insensitive with a string length of 10, move forward to the next code.
strcmp = Compare two strings, if they match each other (case sensitivity is determined by the 'true' or 'false' in the third parameter), then the function will return 0.
"/tower" = The command that the player must enter in order for this code to be executed, this is the first string that is going to be compared.
cmdtext = The text that you actually entered in the input box, this is the second string to be compared. If string1 == string2, it will return 0. Basically, if the text your enter is the same as "/tower", the code below will be executed.
true = This can be set to either true or false, this is used to say whether the strings need to be case sensitive or not. This parameter is called 'ignorecase', so if a player enters "/TOWER" or "/Tower", and you have ignorecase set to false, it will not be the same as "/tower". So for command, it is recommended that you ignore the case sensitivity, so players can still execute as long as they type "/tower" in any form of capital or non-capital letters.
10 = This is the string length of the command, in your command, this is actually wrong. This is used to say how long the strings should be when at their maximum length. Now "/tower" is not 10 characters long, you can either change the 10 to a 6, or remove it altogether so it can be automatically determined by the compiler.
== 0 = If the function 'strcmp' returns 0, which is the given outcome if the strings match each other, then continue with the code. Read more here:
https://sampwiki.blast.hk/wiki/strcmp
pawn Код:
if(IsPlayerInAnyVehicle(playerid))
This one is pretty self-explanatory. If the player is in any type of vehicle, continue with the code. Read more here:
https://sampwiki.blast.hk/wiki/IsPlayerInAnyVehicle
pawn Код:
new vehicleid = GetPlayerVehicleID(playerid);
This will assign the outcome of 'GetPlayerVehicleID(playerid)' to the variable 'vehicleid'. So instead of typing GetPlayerVehicleID(playerid) all the time, we can just save it to a variable, and use that variable in future sections of the code. Read more here:
https://sampwiki.blast.hk/wiki/GetPlayerVehicleID
pawn Код:
new pState = GetPlayerState(playerid);
This is the same as the above, but instead, this will save the outcome or returned value of 'GetPlayerState(playerid)'.
pawn Код:
if(pState == PLAYER_STATE_DRIVER)
This is basically saying that if the player's state is the state of a driver, meaning the player is driving a vehicle and not just a passenger, then follow through with the code. Because we replaced 'GetPlayerState(playerid)' with 'pState', this code is basically saying: if(GetPlayerState(playerid) == PLAYER_STATE_DRIVER). Read more here:
https://sampwiki.blast.hk/wiki/GetPlayerState
pawn Код:
SetVehiclePos(vehicleid, 1544.2318, -1354.3735, 329.4725);
This will Set the position (or teleport in this instance) the vehicle to the given x, y and z coordinates. The San Andreas map is a 3D cube if you will, which has an x, y and z plane. X being the coordinates along the X plane (East to West), Y being the coordinates along the Y plane (North to South), and Z being the coordinates along the Z plane, also known as the 'height or altitude' coordinate. Read more here:
https://sampwiki.blast.hk/wiki/SetVehiclePos
pawn Код:
SetVehicleZAngle(vehicleid, 100);
This will set the angle that your vehicle faces to '100'. As in a normal circle, there is 360 degrees, this will set your facing angle too 100 degrees. Read more here (Non SA-MP related website):
http://en.wikipedia.org/wiki/Degree_%28angle%29 and read more here:
https://sampwiki.blast.hk/wiki/SetVehicleZAngle
pawn Код:
PutPlayerInVehicle(playerid, vehicleid, 0);
This code will put your player back into the vehicle after it has teleported, as the driver. It works as PutPlayerInVehicle(PlayerToTeleport, VehicleToTeleportInto, Seat), where seat is determined by the number 0 and upwards for passengers. 0 = driver, 1 = passenger seat 1, 2 = Passenger seat 2, 3 = Passenger seat 3 for vehicles with up to 4 seats. It continues with the more seats that their are. Read more here:
https://sampwiki.blast.hk/wiki/PutPlayerInVehicle and here:
https://sampwiki.blast.hk/wiki/GetPlayerVehicleSeat
This is used to execute code if the respective 'if' statement is not true. Let's say
A = 2. If I do:
The 'if' statement will not execute, because A is equal to 2, not 3. So I add an 'else' statement underneath it, but note, this will execute for any value other than 3.
pawn Код:
if(A == 3) //A is equal to 3
{
//Do stuff
}
else //A is not 3, but another value.
{
//Do other stuff
}
Read more here:
https://sampwiki.blast.hk/wiki/Keywords:Statements#else
pawn Код:
SetPlayerPos(playerid, 1541.3450,-1366.5369,329.7969);
This will set the player's position, as opposed to the vehicle's position, if the player is not a driver in a vehicle. It will teleport the player directly to the X, Y and Z coordinates that you have given. Read more here:
https://sampwiki.blast.hk/wiki/SetPlayerPos
pawn Код:
SetPlayerFacingAngle(playerid, 360);
Much like the usage of SetVehicleZAngle, this will set the player's facing angle (the angle in which the player is facing) to 360 degrees. Read more here:
https://sampwiki.blast.hk/wiki/SetPlayerFacingAngle
This is the value to return for OnPlayerCommandText, or the command itself "/tower". For OnPlayerCommandText, a returned value of '1' tells the script that the command was successful, and the command exists. A returned value of '0' for OnPlayerCommandText tells the script that the command was either not successfully processed, or the command does not exist at all. (This is part of the reason for the error you are getting.) Read more here:
https://sampwiki.blast.hk/wiki/OnPlayerCommandText and read this:
https://sampwiki.blast.hk/wiki/Keywords:Statements#return
After we run through your code, it will work normally, but will give you this error because you are only returning '1' when the player is not a driver in a vehicle. As you may notice, the return 1 is under the 'else' statement, but not under the 'if(pState == PLAYER_STATE_DRIVER)'. Meaning the command will return 'SERVER: Unknown Command' if the player is a driver in a vehicle. A way to fix this is to return 1 at the end of the command, outside of any if statements, so it will return 1 no matter what. The correct code (in your terms) would be the following:
pawn Код:
if(strcmp("/tower", cmdtext, true) == 0)
{
if(IsPlayerInAnyVehicle(playerid))
{
new vehicleid = GetPlayerVehicleID(playerid);
new pState = GetPlayerState(playerid);
if(pState == PLAYER_STATE_DRIVER)
{
SetVehiclePos(vehicleid, 1544.2318, -1354.3735, 329.4725);
SetVehicleZAngle(vehicleid, 100);
PutPlayerInVehicle(playerid, vehicleid, 0);
}
}
else
{
SetPlayerPos(playerid, 1541.3450,-1366.5369,329.7969);
SetPlayerFacingAngle(playerid, 360);
}
return 1;
}
If we neaten this up, the correct code would be:
pawn Код:
if(strcmp(cmdtext, "/tower", true) == 0)
{
if(GetPlayerState(playerid) == PLAYER_STATE_DRIVER) //If their state is 'PLAYER_STATE_DRIVER', we can determine that they are already in a vehicle, and IsPlayerInAnyVehicle does not need to be used.
{
new vehicleid = GetPlayerVehicleID(playerid); //Get the player's vehicle ID
SetVehiclePos(vehicleid, 1544.2318, -1354.3735, 329.4725); //Teleport the player's vehicle to the given coordinates
SetVehicleZAngle(vehicleid, 100); //Set the vehicle's angle to 100
PutPlayerInVehicle(playerid, vehicleid, 0); //Put the player in the vehicle again, in seat 0, which is the driver's seat.
}
else //If the player using "/tower" is not a driver in a vehicle.
{
SetPlayerPos(playerid, 1541.3450,-1366.5369,329.7969); //Teleport the player himself, to the given coordinates.
SetPlayerFacingAngle(playerid, 360); //Set the player to face at an angle of 360 degrees.
}
return 1; //Tell the callback 'OnPlayerCommandText' to return 1 to the server, meaning this command has been executed and exists. Meaning no 'SERVER: Unknown Command' will be sent to the player.
}
The above will work, but will not teleport passengers as well. Such scripting just requires a bit of logical thinking, so you have to think of the best logical method that would work. You are thinking of going through all vehicles to see if that vehicle is the one being teleported, then going through all players to see if they are in that vehicle being teleported, which is a double loop, which really, you don't want to be using in SA-MP.
So if we re-think this, what do we get?
- Passengers must be inside the same vehicle as the driver, how do we get the vehicle id of the driver? In this line: 'new vehicleid = GetPlayerVehicleID(playerid);'
- We need to go through all players, to see if they are in this vehicle... to start a loop, we use 'for(new i = 0; i < MAX_PLAYERS; i++)'. Loops are explained here:
https://sampwiki.blast.hk/wiki/Loops
- We don't want the driver of the vehicle to be included in the loop, because he has already been teleported, so we use 'if(i == playerid) continue;', meaning if the player we're looking at has the same id as the player using "/tower", skip him. More explained on 'continue' here:
https://sampwiki.blast.hk/wiki/Keywords:Statements#continue
- Once we start looking through all players, we need to check if they are in the vehicle 'vehicleid', so we use 'if(GetPlayerVehicleID(i) == vehicleid)', which means if the id of the given player's vehicle, matches the id of the driver's vehicle, then they must be in the same vehicle. There cannot be 2 drivers of a vehicle, so obviously this player is a passenger in the same vehicle.
- We now know the player is a passenger in the same vehicle, so we have to teleport him into THE SAME SEAT he was in, in the vehicle originally. So we save the id of his seat with 'new seat = GetPlayerVehicleSeat(i);'
- As we need to get their vehicle seat, we have to get their seat BEFORE we actually teleport the vehicle, so this loop will have to be before we teleport the vehicle (SetVehiclePos).
- After we teleport the vehicle, we teleport the passengers back into the vehicle, which means we may need another loop after we teleport the vehicle.
- Then teleport them into the vehicle using 'PutPlayerInVehicle', but with the seat they were originally used, which we saved in the variable 'seat'. 'PutPlayerInVehicle(i, vehicleid, seat);'
So let's construct this command:
pawn Код:
if(strcmp(cmdtext,
"/tower", true
) == 0){ if(GetPlayerState
(playerid
) == PLAYER_STATE_DRIVER
) { new vehicleid
= GetPlayerVehicleID
(playerid
);
new bool:teleportplayer
[MAX_PLAYERS
] = false;
//Used to determine whether we need to teleport the player or not. (Bool means you are using true or false instead of integers. Could not find the page for booleans, but I know there is one) new seat
[MAX_PLAYERS
];
//Used to save the seat id to their playerid. new i;
//Will be used in the loop, twice. for(i
= 0; i
< MAX_PLAYERS; i
++) { if(!IsPlayerConnected
(i
)) continue;
//If the playerid 'i' is not connected, skip it. (Meaning there is not player with this ID. Read more here: https://sampwiki.blast.hk/wiki/IsPlayerConnected) if(i
== playerid
) continue;
if(!IsPlayerInVehicle
(i, vehicleid
)) continue;
//Read more here: https://sampwiki.blast.hk/wiki/IsPlayerInVehicle seat
[i
] = GetPlayerVehicleSeat
(i
);
teleportplayer
[i
] = true;
} SetVehiclePos
(vehicleid,
1544.2318,
-1354.3735,
329.4725);
//Teleport the player's vehicle to the given coordinates SetVehicleZAngle
(vehicleid,
100);
//Set the vehicle's angle to 100 PutPlayerInVehicle
(playerid, vehicleid,
0);
//Put the player in the vehicle again, in seat 0, which is the driver's seat. for(i
= 0; i
< MAX_PLAYERS; i
++) { if(!IsPlayerConnected
(i
)) continue;
if(i
== playerid
) continue;
if(teleportplayer
[i
] != true
) continue;
PutPlayerInVehicle
(i, vehicleid, seat
[i
]);
} } return 1;
}
I hope this kind of helps you understand, if you're unsure about anything, just ask. I just realised you already posted, so I'm not sure if I even need to post here, but here you are anyway.
EDIT: Oh, and I'm sure there's a neater way to do this command, but I'm a bit blank in the head right now, so if anyone wants to correct it, feel free to do so