[Tutorial] Everything about NPCs - creating and controlling them
#1

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:
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

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:
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.

* Record file of driving NPC:
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.

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:
pawn Code:
#include <a_npc>
main() {}
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:
pawn Code:
ConnectNPC("Player","idle");
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():
pawn Code:
if(IsPlayerNPC(playerid))
{
    new ip[16];
    GetPlayerIp(playerid,ip,sizeof(ip));
    if(strcmp(ip,"<YOUR SERVER IP HERE>") != 0) return Kick(playerid);
}
(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
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);
}
(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.
Reply
#2

Thank you for this tutorial, it is much better than the usual ones that are around these forums.

For communication between NPC processes and the server, I suggest also mentioning NPC communications implementation by Y_Less (which is perhaps a bit more complicated than a simple recording path playback, but will become useful in many scenarios).

CallRemoteFunction should not work. NPCs run in their own processes.
Reply
#3

Quote:
Originally Posted by AndreT
View Post
Thank you for this tutorial, it is much better than the usual ones that are around these forums.

For communication between NPC processes and the server, I suggest also mentioning NPC communications implementation by Y_Less (which is perhaps a bit more complicated than a simple recording path playback, but will become useful in many scenarios).

CallRemoteFunction should not work. NPCs run in their own processes.
Forgot the different processes :>, you're right about that.
Reply
#4

Thanks, Very usefull
Reply
#5

Thanks! Been wanting to know how I can pause the NPC's when there is someone in front of them! Thanks very much!
Reply
#6

It's a great job i think you have explained anything deeply.
Also the links you have given for the NPC's systems shooting,talking,responding etc are very usefull.
+Rep.
Reply
#7

Great tutorial.

I always knew about the npc feature but never payed attention to it. I recently saw how amazing this feature could be and I was looking to learn more about it. I am glad you this thread.
Reply
#8

Thank you for this good tutorial !
How i can make some npcs to kill players?
Reply
#9

Quote:
Originally Posted by Coder_
View Post
Thank you for this good tutorial !
How i can make some npcs to kill players?
There is no simple way for it. You'll have to record the npc aiming at specific position and shooting.
The advanced way which I guess will not really look fine if you'll even be able to make it,
is to set the NPC facing angle, animation and create object of shooting fire and etc. What I mean is to create the whole GTASA shooting system from scratch, which is not easy to do.
Reply
#10

Quote:
Originally Posted by Amit_B
View Post
There is no simple way for it. You'll have to record the npc aiming at specific position and shooting.
The advanced way which I guess will not really look fine if you'll even be able to make it,
is to set the NPC facing angle, animation and create object of shooting fire and etc. What I mean is to create the whole GTASA shooting system from scratch, which is not easy to do.
Can u make short tut?
Or is possible to "buy" guns for npc?
i mean
ShowPlayerDialog(playerid, etc etc?
Reply
#11

I think I tried communication with NPCs using CallRemoteFunction and it didn't work, if I recall correctly.

In addition, I'd add a few lines about how to communicate with NPCs using text (not just SendClientMessage, but also OnClientMessage. Perhaps you could also add a small link to botsync, an include by Y_Less for easy communication between bot and gamemode/filterscript (not required, but could give people an example)?

Otherwise, this looks like a good tutorial. Keep it up!
Reply
#12

Quote:
Originally Posted by Coder_
View Post
Can u make short tut?
Or is possible to "buy" guns for npc?
i mean
ShowPlayerDialog(playerid, etc etc?
As I said it will be really hard and by thinking about it again, there's no way to set the NPC aiming point to the player if the player is in a different height from the NPC. And for your question, i'm pretty sure that it's possible to give the NPC a weapon as he is almost like a normal player.

Anyway I'll not make any tutorial because scripting what you've asked is not easy if even possible, but i'm sure that SA-MP team will sometime add such options for NPCs.

Quote:
Originally Posted by Hiddos
View Post
I think I tried communication with NPCs using CallRemoteFunction and it didn't work, if I recall correctly.

In addition, I'd add a few lines about how to communicate with NPCs using text (not just SendClientMessage, but also OnClientMessage. Perhaps you could also add a small link to botsync, an include by Y_Less for easy communication between bot and gamemode/filterscript (not required, but could give people an example)?

Otherwise, this looks like a good tutorial. Keep it up!
By the mention of SendClientMessage it meant to use with OnClientMessage.
About the include - didn't knew it's exist However it's a fine way to communicate between both scripts, i'll add a link for it. Too bad I haven't seen that before...
Reply
#13

Quote:
Originally Posted by Amit_B
View Post
By the mention of SendClientMessage it meant to use with OnClientMessage.
About the include - didn't knew it's exist However it's a fine way to communicate between both scripts, i'll add a link for it. Too bad I haven't seen that before...
It's pretty hidden, the only reason I knew about it was because somebody else linked me to it :/.
Reply
#14

How to make a delay, between each NPC Connect. I got 14 npcs, and 0.3x. But the Anti-Bot just blocks them.
Reply
#15

can i use something like this or it will cuz a bug on npc ?
(spawn 4 npc with the same fs ?)
ConnectNPC("PlayerA","idle");
ConnectNPC("PlayerB","idle");
ConnectNPC("PlayerC","idle");
ConnectNPC("PlayerD","idle");
Reply
#16

Can anyone give me the correct code of allowing NPCs through login / register area?
Reply
#17

Quote:
Originally Posted by ammaz
View Post
Can anyone give me the correct code of allowing NPCs through login / register area?
Use https://sampwiki.blast.hk/wiki/IsPlayerNPC to detect if playerid is an npc and stop/bypass the login/register process for them.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)