29.06.2012, 20:30
(
Last edited by Amit_B; 05/07/2012 at 08:51 AM.
)
Introduction
I've heard a lot of people who had problems creating NPC as they want to, so i'm creating this tutorial to share anything i've discovered about this known system.
When the NPC system created, kc posted the first tutorial about creating NPCs but it isn't enough at all; the NPC system allows you to create much more than what we can learn from the tutorial.
Important: This tutorial is not instead of kc's, it's in addition of it.
About NPCs
Back to 2009, 0.3a first released after 0.2X with the NPCs (Non-Playing Characters) system that everyone wanted back then.
This system allows you to add a special player to the server, which controlled easily by scripting, and takes slot but can not be viewed in the player list / can not be killed and some more differents from normal player.
The NPCs system is using the GTA SA ped system, which is used in the single player for creating people in the streets and known people such as the ones that appears in missions. In SA-MP, the ped system is used in places like the ammunation or some restaurants, and in two of the casinos.
Recording playbacks for NPCs
Most of NPCs can be found today in servers are acting by a record file. In SA-MP, you can record yourself driving a vehicle or just walking or shooting and etc, and let NPC follow your actions by acting like the record file you created before. A record file can be created using an NPC record script, for example the npc_record.amx that comes with any server as a default filterscript.
I'm not going to explain about how exactly to use the script, full information about that can be found in kc's tutorial.
One thing that you need to know - record file can be one of three record types:
As you see, you can't easily create an NPC that entering a car, for example, because your record file have to be typed as one of the types above.
If you're intending to create a NPC followed by a record, get the .rec file (NPC record file) from /scriptfiles/ (After you created it with any record script) and move it to /npcmodes/recording/.
/npcmodes/recording/ is the directory of any .rec file. The /npcmodes/ used to place an .amx file of every NPC you have, i'll explain more later.
Creating a simple NPC followed by record file
After you have a .rec file you can make your NPC to follow it.
Any NPC have its own script that decides what exactly will he do after connecting the server. After creating a script and compiling it, the .amx file have to be in /npcmodes/ so the server will be able to read it.
An NPC script uses a specific include file called a_npc.inc which contains basic functions of scripting with NPCs and scripting at all. A script of NPC followed by record, should look in a specific way;
* Record file of on-foot NPC:
* Record file of driving NPC:
After creating the NPC script, save it in /npcmodes/ and compile so you'll have an .amx and then you're ready to add the NPC to your gamemode or to any other script.
Connecting an NPC to the server
First of all, before entering the script you want to add the NPC to, you'll have to know a few things:
- NPCs are almost like normal players for the server. They're taking a slot but can't be viewed from player lists. To make sure that we have place for the npcs, we need to take a look at the server.cfg: there are variable names "maxnpcs" which means the limit of NPCs that can connect to the server at once. It is recommended to set it as the exact number of NPCs that should be connected to the server.
- After connecting an NPC to the server, it will stay connected, as long you don't kick him from the server. If his playback ends, and it isn't using a loop, it will still be connected without a playback to play. When a gamemode ends, all of the players are getting out of the servers until the next gamemode loaded, it contains the NPCs too - if the gamemode changes they will quit as all the players, but they'll not return because they need a script to connect them.
Full information about how exactly to connect the NPCs can be found in kc's tutorial.
NPC without a playback and controlling them
We have the option to create NPCs without any record file. These NPCs can be easily manipulated using scripting functions - that's one of the differents between them and the NPCs followed by record file. We can't really manipulate NPCs that following a record file.
Anyway, to create for example just idle NPC, one that just standing somewhere, we don't need anything but an empty .amx file of NPC. Something like that:
These lines will not affect anything, but they are needed for any NPC we creating - on foot, driving or sometimes an NPC without a playback file. By connecting an NPC with that file:
we'll have NPC standing somewhere (I guess in 0.0,0.0,0.0). We can just use SetPlayerPos/FacingAngle/Skin to add basic features. We can also use ApplyAnimation. I've once created NPCs that getting their hands up when player aiming at them with a weapon.
Affecting NPCs that playing a playback
We can affect NPCs that followed by record file just by some specific features:
- Kick() - To get them out of the server.
- StartRecordingPlayback() - To play a playback from its start.
- StopRecordingPlayback() - Stopping the current playback so we'll play another one.
- PauseRecordingPlayback() - Pausing the playback in its current position.
- ResumeRecordingPlayback() - Play the playback from the position its paused.
With these functions we can make, for example, a driving NPC that detect players in front of him and stops in that case. You can see how it can be done in Kye's taxi_ls_text.pwn that comes with any downloaded server.
Passing information between script and NPC
Sometimes we'll need to pass information from a script to NPC or from NPC to a script (script means anything that connected the NPC to the server, such as a gamemode or filterscript).
There are a lot of ways to do that:
* Commands: (Script to NPC)
NPCs are able to send commands as normal players and also to read messages sent to them with SendClientMessage. By creating a command made for NPC and sending it to the chat, you can share any information in your script with any NPC on the server. Based on this idea, you can send by timer or anything else the information in client message to the NPC.
* Storing data: (Script to NPC, NPC to script)
INI Files, MySQL and more, where always the best way to store information and let it be shared with other applications. In our case, with other PAWN scripts. You can easily include for example, file.inc and use file functions to read shared data of the whole server.
* CallRemoteFunction: (Script to NPC)
Actually, I don't know if this one will work because I just didn't tested it. But theoretically it should work.
By creating a function in an NPC script and calling it from your script with CallRemoteFunction() you'll be able to pass parameter(s) with the required data. -- looks like this one will not work
Crazy hacker NPCs!
Well i'm not sure if this was fixed in 0.3e, anyway some hackers(?) figured out a way of remotely adding NPC to a server with their own recording file.
To prevent people from doing that on your server you need to:
1) Setting 'maxnpcs' as the limit of NPCs on your server.
2) Adding this code to the top of OnPlayerConnected():
(When NPCs enter the server, their IP is same as the server IP. If we got NPC that his IP is not the server IP, then he's not from this server)
Examples
Here I'll show you some examples of controlling NPCs.
* Easy and automatically connecting NPCs to the server
https://sampforum.blast.hk/showthread.php?tid=355379
* Letting an NPC to 'talk'
Here - pastebin link
* Aiming on NPC with weapon will cause him to get his hands up
(OnPlayerTargetPlayer)
* Driving NPC that finds out if there are players in front of him, and stops the playback in that case (based on Kye's idea)
Here - pastebin link (that's how I done that)
FAQ
Q: What can prevent the NPCs from joining the server?
A: A lot of people having problems in connecting the NPCs to the server. It's never fault of the the SA-MP itself; the problem will be always in the server or in the NPC script or in the script that connecting the NPC:
- Make sure that nothing prevent the NPC to just spawn to its vehicle (for example system that requires register/login). If you have anything like this, add a expression of IsPlayerNPC() to prevent it.
- Set the 'maxnpcs' to the limit of NPCs in the server.
- Check the samp-npc file you got in the server; make sure it's the right and the updated file.
- Check that the NPCs are not banned somehow (samp.ban).
- Make sure that you have the record files in /npcmodes/recording/ and the .amx files in /npcmodes/, compiled to the right version of SA-MP.
Q: The NPCs are sometimes crashes the server or causing it problems. What can I do?
A: This can be caused if your script is full of arrays like playerinfo[][] and etc. You must remember that the NPCs got ID and they're included in the MAX_PLAYERS arrays.
Q: How to prevent admins from using commands on NPCs?
A: Basically, admin commands (for example) takes ID to use the command on. To prevent admin to use commands on NPCs you'll need to add an expression if IsPlayerNPC() to every command, OR if your commands uses some id parse function, such as ReturnUser, just add to the MAX_PLAYERS loop of the function an expression that checks if the player is an NPC.
Related links
NPCs SA-MP wiki information - Not really updated (06/2012) but can be helpful to understand the NPCs.
kc's tutorial - Basic information of creating NPCs followed by playback.
botsync inc file by Y_Less - A library used to communicate information between NPC script and gamemode/filterscript (use to easily send data between the scripts if you don't want to make the whole communicating script yourself).
That's all, I hope some users will find this tutorial helpful.
I've heard a lot of people who had problems creating NPC as they want to, so i'm creating this tutorial to share anything i've discovered about this known system.
When the NPC system created, kc posted the first tutorial about creating NPCs but it isn't enough at all; the NPC system allows you to create much more than what we can learn from the tutorial.
Important: This tutorial is not instead of kc's, it's in addition of it.
About NPCs
Back to 2009, 0.3a first released after 0.2X with the NPCs (Non-Playing Characters) system that everyone wanted back then.
This system allows you to add a special player to the server, which controlled easily by scripting, and takes slot but can not be viewed in the player list / can not be killed and some more differents from normal player.
The NPCs system is using the GTA SA ped system, which is used in the single player for creating people in the streets and known people such as the ones that appears in missions. In SA-MP, the ped system is used in places like the ammunation or some restaurants, and in two of the casinos.
Recording playbacks for NPCs
Most of NPCs can be found today in servers are acting by a record file. In SA-MP, you can record yourself driving a vehicle or just walking or shooting and etc, and let NPC follow your actions by acting like the record file you created before. A record file can be created using an NPC record script, for example the npc_record.amx that comes with any server as a default filterscript.
I'm not going to explain about how exactly to use the script, full information about that can be found in kc's tutorial.
One thing that you need to know - record file can be one of three record types:
Quote:
0 - PLAYER_RECORDING_TYPE_NONE - I don't really know what is this type used for, if it can be used 1 - PLAYER_RECORDING_TYPE_DRIVER - Used for records of NPC that using a vehicle 2 - PLAYER_RECORDING_TYPE_ONFOOT - Used for on-foot records |
If you're intending to create a NPC followed by a record, get the .rec file (NPC record file) from /scriptfiles/ (After you created it with any record script) and move it to /npcmodes/recording/.
/npcmodes/recording/ is the directory of any .rec file. The /npcmodes/ used to place an .amx file of every NPC you have, i'll explain more later.
Creating a simple NPC followed by record file
After you have a .rec file you can make your NPC to follow it.
Any NPC have its own script that decides what exactly will he do after connecting the server. After creating a script and compiling it, the .amx file have to be in /npcmodes/ so the server will be able to read it.
An NPC script uses a specific include file called a_npc.inc which contains basic functions of scripting with NPCs and scripting at all. A script of NPC followed by record, should look in a specific way;
* Record file of on-foot NPC:
pawn Code:
#include "a_npc.inc"
main() {}
public OnNPCSpawn() StartRecordingPlayback(2,"MyFirstNPC");
public OnRecordingPlaybackEnd() StartRecordingPlayback(2,"MyFirstNPC");
Quote:
Code lines: #1 - Including the a_npc.inc mentioned before, to allow ourselves use its features. #2 - main() - A function that has to be found in every PAWN script. #3 - When the NPC first spawning, what should happen when we connecting it to the server, it will follow the record file "MyFirstNPC" with the type of 2 which is the on-foot record type. #4 - If the playback is end, it will start it again, so we'll have an on-foot NPC following a playback in loop. |
pawn Code:
#include "a_npc.inc"
main() {}
public OnNPCEnterVehicle(vehicleid,seatid) StartRecordingPlayback(1,"DrivingNPC");
public OnNPCExitVehicle() StopRecordingPlayback();
public OnRecordingPlaybackEnd() StartRecordingPlayback(1,"DrivingNPC");
Quote:
Code lines: #1 - Including the a_npc.inc mentioned before, to allow ourselves use its features. #2 - main() - A function that has to be found in every PAWN script. #3 - When connecting an driving NPC to our server, we have to create a vehicle for him and put him in. I'll explain later how to do that. However, this line means that when the NPC is entering to any vehicle (in our case, to the vehicle we'll create for him) he will start to follow a playback named "DrivingNPC" with a record type of 1 - driving. #4 - If somehow the NPC is found out of the vehicle (for example if someone teleported him out of the vehicle) the playback will stop. #5 - If the playback is end, it will start it again, so we'll have an driving NPC following a playback in loop. |
Connecting an NPC to the server
First of all, before entering the script you want to add the NPC to, you'll have to know a few things:
- NPCs are almost like normal players for the server. They're taking a slot but can't be viewed from player lists. To make sure that we have place for the npcs, we need to take a look at the server.cfg: there are variable names "maxnpcs" which means the limit of NPCs that can connect to the server at once. It is recommended to set it as the exact number of NPCs that should be connected to the server.
- After connecting an NPC to the server, it will stay connected, as long you don't kick him from the server. If his playback ends, and it isn't using a loop, it will still be connected without a playback to play. When a gamemode ends, all of the players are getting out of the servers until the next gamemode loaded, it contains the NPCs too - if the gamemode changes they will quit as all the players, but they'll not return because they need a script to connect them.
Full information about how exactly to connect the NPCs can be found in kc's tutorial.
NPC without a playback and controlling them
We have the option to create NPCs without any record file. These NPCs can be easily manipulated using scripting functions - that's one of the differents between them and the NPCs followed by record file. We can't really manipulate NPCs that following a record file.
Anyway, to create for example just idle NPC, one that just standing somewhere, we don't need anything but an empty .amx file of NPC. Something like that:
pawn Code:
#include <a_npc>
main() {}
pawn Code:
ConnectNPC("Player","idle");
Affecting NPCs that playing a playback
We can affect NPCs that followed by record file just by some specific features:
- Kick() - To get them out of the server.
- StartRecordingPlayback() - To play a playback from its start.
- StopRecordingPlayback() - Stopping the current playback so we'll play another one.
- PauseRecordingPlayback() - Pausing the playback in its current position.
- ResumeRecordingPlayback() - Play the playback from the position its paused.
With these functions we can make, for example, a driving NPC that detect players in front of him and stops in that case. You can see how it can be done in Kye's taxi_ls_text.pwn that comes with any downloaded server.
Passing information between script and NPC
Sometimes we'll need to pass information from a script to NPC or from NPC to a script (script means anything that connected the NPC to the server, such as a gamemode or filterscript).
There are a lot of ways to do that:
* Commands: (Script to NPC)
NPCs are able to send commands as normal players and also to read messages sent to them with SendClientMessage. By creating a command made for NPC and sending it to the chat, you can share any information in your script with any NPC on the server. Based on this idea, you can send by timer or anything else the information in client message to the NPC.
* Storing data: (Script to NPC, NPC to script)
INI Files, MySQL and more, where always the best way to store information and let it be shared with other applications. In our case, with other PAWN scripts. You can easily include for example, file.inc and use file functions to read shared data of the whole server.
* CallRemoteFunction: (Script to NPC)
Actually, I don't know if this one will work because I just didn't tested it. But theoretically it should work.
By creating a function in an NPC script and calling it from your script with CallRemoteFunction() you'll be able to pass parameter(s) with the required data. -- looks like this one will not work
Crazy hacker NPCs!
Well i'm not sure if this was fixed in 0.3e, anyway some hackers(?) figured out a way of remotely adding NPC to a server with their own recording file.
To prevent people from doing that on your server you need to:
1) Setting 'maxnpcs' as the limit of NPCs on your server.
2) Adding this code to the top of OnPlayerConnected():
pawn Code:
if(IsPlayerNPC(playerid))
{
new ip[16];
GetPlayerIp(playerid,ip,sizeof(ip));
if(strcmp(ip,"<YOUR SERVER IP HERE>") != 0) return Kick(playerid);
}
Examples
Here I'll show you some examples of controlling NPCs.
* Easy and automatically connecting NPCs to the server
https://sampforum.blast.hk/showthread.php?tid=355379
* Letting an NPC to 'talk'
Here - pastebin link
* Aiming on NPC with weapon will cause him to get his hands up
pawn Code:
public OnPlayerTargetPlayer(playerid,newtarget,oldtarget)
{
if(newtarget != INVALID_PLAYER_ID && IsPlayerConnected(newtarget) && IsPlayerNPC(newtarget) && GetPlayerWeapon(playerid) >= 22 && GetPlayerWeapon(playerid) <= 38) ApplyAnimation(newtarget,"PED","handsup",4.1,0,1,1,1,1);
}
* Driving NPC that finds out if there are players in front of him, and stops the playback in that case (based on Kye's idea)
Here - pastebin link (that's how I done that)
FAQ
Q: What can prevent the NPCs from joining the server?
A: A lot of people having problems in connecting the NPCs to the server. It's never fault of the the SA-MP itself; the problem will be always in the server or in the NPC script or in the script that connecting the NPC:
- Make sure that nothing prevent the NPC to just spawn to its vehicle (for example system that requires register/login). If you have anything like this, add a expression of IsPlayerNPC() to prevent it.
- Set the 'maxnpcs' to the limit of NPCs in the server.
- Check the samp-npc file you got in the server; make sure it's the right and the updated file.
- Check that the NPCs are not banned somehow (samp.ban).
- Make sure that you have the record files in /npcmodes/recording/ and the .amx files in /npcmodes/, compiled to the right version of SA-MP.
Q: The NPCs are sometimes crashes the server or causing it problems. What can I do?
A: This can be caused if your script is full of arrays like playerinfo[][] and etc. You must remember that the NPCs got ID and they're included in the MAX_PLAYERS arrays.
Q: How to prevent admins from using commands on NPCs?
A: Basically, admin commands (for example) takes ID to use the command on. To prevent admin to use commands on NPCs you'll need to add an expression if IsPlayerNPC() to every command, OR if your commands uses some id parse function, such as ReturnUser, just add to the MAX_PLAYERS loop of the function an expression that checks if the player is an NPC.
Related links
NPCs SA-MP wiki information - Not really updated (06/2012) but can be helpful to understand the NPCs.
kc's tutorial - Basic information of creating NPCs followed by playback.
botsync inc file by Y_Less - A library used to communicate information between NPC script and gamemode/filterscript (use to easily send data between the scripts if you don't want to make the whole communicating script yourself).
That's all, I hope some users will find this tutorial helpful.