SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help

Reply
 
Thread Tools Display Modes
Old 21/09/2018, 01:14 PM   #1
matje
Little Clucker
 
Join Date: Sep 2016
Posts: 30
Reputation: 5
Default NPC chase the nearest player

Hi guys.
First of all, I ******d, searched multiple forums but could not find solution to this.
I'm using FCNPC. How can I create so the NPC's recognize and chase the closest player?
Can somebody shed some light on this please? Thank you.
matje is offline   Reply With Quote
Old 21/09/2018, 02:01 PM   #2
CodeStyle175
Banned
 
Join Date: Apr 2014
Posts: 455
Reputation: 35
Default Re: NPC chase the nearest player

you create timer what loops throw players, when player is near to npc for example 5.0 units, then npc idle state changes to walk state and npc starts to follow player.
CodeStyle175 is offline   Reply With Quote
Old 21/09/2018, 02:02 PM   #3
Ritzy2K
High-roller
 
Ritzy2K's Avatar
 
Join Date: Jun 2014
Location: India
Posts: 1,548
Reputation: 170
Default Re: NPC chase the nearest player

http://forum.sa-mp.com/showthread.php?t=432342

Code:
FCNPC_GoToPlayerEx
I believe this is what you're looking for!
__________________
Ritzy2K is offline   Reply With Quote
Old 21/09/2018, 02:41 PM   #4
ZiGGi
Banned
 
Join Date: Sep 2008
Location: Russia
Posts: 1,659
Reputation: 356
Default Re: NPC chase the nearest player

Just look at the bodyguard script: https://github.com/ziggi/FCNPC/blob/...bodyguards.pwn
Especially on the BG_FollowPlayer function.
ZiGGi is offline   Reply With Quote
Old 21/09/2018, 03:01 PM   #5
matje
Little Clucker
 
Join Date: Sep 2016
Posts: 30
Reputation: 5
Default Re: NPC chase the nearest player

Thanks everyone, with your help I got the NPC to recognize the closest player and chase him.
Now the issue is that the NPC's target doesn't change. They will always chase the one initial player even though other players are closer to them. I've used timer to update the closest player every half second, but the NPC does not change the target.
matje is offline   Reply With Quote
Old 21/09/2018, 03:14 PM   #6
NaS
High-roller
 
NaS's Avatar
 
Join Date: Mar 2008
Location: 🇩🇪
Posts: 1,646
Reputation: 557
Default Re: NPC chase the nearest player

Quote:
Originally Posted by matje View Post
Thanks everyone, with your help I got the NPC to recognize the closest player and chase him.
Now the issue is that the NPC's target doesn't change. They will always chase the one initial player even though other players are closer to them. I've used timer to update the closest player every half second, but the NPC does not change the target.
Could you post the related code? Otherwise we have to guess what could be the cause
NaS is offline   Reply With Quote
Old 21/09/2018, 03:21 PM   #7
matje
Little Clucker
 
Join Date: Sep 2016
Posts: 30
Reputation: 5
Default Re: NPC chase the nearest player

Quote:
Originally Posted by NaS View Post
Could you post the related code? Otherwise we have to guess what could be the cause
Sorry about that, you are right

Code:
for(new i=0; i < MAX_PLAYERS; i++){
	    new Float:xp, Float: yp, Float: zp;
	    GetPlayerPos(playerid, xp, yp, zp);
        for(new iz = 0; iz < WaveZombies; iz++){
    		if(FCNPC_IsValid(Zombies[iz])){
		        if(IsPlayerInRangeOfPoint(Zombies[iz], 10, xp, yp, zp)){
		             FCNPC_GoToPlayer(Zombies[iz], playerid, FCNPC_MOVE_TYPE_RUN, FCNPC_MOVE_SPEED_RUN, false, 0.0, true, 0.0, 1.5, 250);
matje is offline   Reply With Quote
Old 21/09/2018, 03:41 PM   #8
NaS
High-roller
 
NaS's Avatar
 
Join Date: Mar 2008
Location: 🇩🇪
Posts: 1,646
Reputation: 557
Default Re: NPC chase the nearest player

Quote:
Originally Posted by matje View Post
Sorry about that, you are right

Code:
for(new i=0; i < MAX_PLAYERS; i++){
	    new Float:xp, Float: yp, Float: zp;
	    GetPlayerPos(playerid, xp, yp, zp);
        for(new iz = 0; iz < WaveZombies; iz++){
    		if(FCNPC_IsValid(Zombies[iz])){
		        if(IsPlayerInRangeOfPoint(Zombies[iz], 10, xp, yp, zp)){
		             FCNPC_GoToPlayer(Zombies[iz], playerid, FCNPC_MOVE_TYPE_RUN, FCNPC_MOVE_SPEED_RUN, false, 0.0, true, 0.0, 1.5, 250);
This code does not determine the closest player.

It will select everyone in range as target, the highest playerid will then be the final target as it is set last.

To make it actually search for closest player, you can declare two variables before the loop.
One for the target playerid and one for the distance.

Then use GetPlayerDistanceToPoint instead of IsPlayerInRangeOfPoint. If that distance is lower than the current target's distance, update the target variable and the distance.

After the loop, the target variable will contain the closest playerid.

Something like this:

Code:
new target_id = -1, Float:distance = 10.0; // max distance can be configured here

for(new i = 0; i < MAX_PLAYERS; i ++)
{
	new Float:x, Float:y, Float:z, Float:tmp_distance;
	GetPlayerPos(i, x, y, z);
	tmp_distance = GetPlayerDistanceFromPoint(ZombieID, x, y, z);

	if(tmp_distance < distance)
	{
		distance = tmp_distance;
		target_id = i;
	}
}

if(target_id != -1)
{
	// target_id is the closest player
}
else
{
	// No target found, do something else
}
This should be your inner loop, the outter loop should be the loop for the zombies (ZombieID).

Also you might want to consider using foreach in combination with the streamer plugin.
foreach will allow for more efficient loops.

With the Streamer Plugin you can create a dynamic area and attach it to the zombies. Then you can just loop through players that are already in those areas instead of checking all zombies vs all players. That will considerably lower the number of distance checks, as it's highly unlikely that all players are always near all zombies.
NaS is offline   Reply With Quote
Old 21/09/2018, 03:55 PM   #9
matje
Little Clucker
 
Join Date: Sep 2016
Posts: 30
Reputation: 5
Default Re: NPC chase the nearest player

Quote:
Originally Posted by NaS View Post
This code does not determine the closest player.

It will select everyone in range as target, the highest playerid will then be the final target as it is set last.

To make it actually search for closest player, you can declare two variables before the loop.
One for the target playerid and one for the distance.

Then use GetPlayerDistanceToPoint instead of IsPlayerInRangeOfPoint. If that distance is lower than the current target's distance, update the target variable and the distance.

After the loop, the target variable will contain the closest playerid.

Something like this:

Code:
new target_id = -1, Float:distance = 10.0; // max distance can be configured here

for(new i = 0; i < MAX_PLAYERS; i ++)
{
	new Float:x, Float:y, Float:z, Float:tmp_distance;
	GetPlayerPos(i, x, y, z);
	tmp_distance = GetPlayerDistanceFromPoint(ZombieID, x, y, z);

	if(tmp_distance < distance)
	{
		distance = tmp_distance;
		target_id = i;
	}
}

if(target_id != -1)
{
	// target_id is the closest player
}
else
{
	// No target found, do something else
}
This should be your inner loop, the outter loop should be the loop for the zombies (ZombieID).

Also you might want to consider using foreach in combination with the streamer plugin.
foreach will allow for more efficient loops.

With the Streamer Plugin you can create a dynamic area and attach it to the zombies. Then you can just loop through players that are already in those areas instead of checking all zombies vs all players. That will considerably lower the number of distance checks, as it's highly unlikely that all players are always near all zombies.
Holy fuck you are my hero
Thank you so much, it works!

I've used

Code:
foreach(Player, i)
{
    //stuff
}
Instead of

Code:
for(new i = 0; i < MAX_PLAYERS; i++)
{
    if(IsPlayerConnected(i))
    {
        //stuff
    }
}
because (I think) foreach loops only through players, not NPCS.

Also thank you for the great tips.
matje is offline   Reply With Quote
Old 21/09/2018, 06:13 PM   #10
NaS
High-roller
 
NaS's Avatar
 
Join Date: Mar 2008
Location: 🇩🇪
Posts: 1,646
Reputation: 557
Default Re: NPC chase the nearest player

Quote:
Originally Posted by matje View Post
Holy fuck you are my hero
Thank you so much, it works!

I've used

Code:
foreach(Player, i)
{
    //stuff
}
Instead of

Code:
for(new i = 0; i < MAX_PLAYERS; i++)
{
    if(IsPlayerConnected(i))
    {
        //stuff
    }
}
because (I think) foreach loops only through players, not NPCS.

Also thank you for the great tips.
By default there are Iterators for Players and NPCs. Check the foreach include, there should be definitions for both (also defines).
But even if there aren't you can always declare your own Iterator and add your Zombie NPCs to it Especially if not all NPCs on the server are Zombies.

Last edited by NaS; 21/09/2018 at 08:05 PM.
NaS is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
nearest player suni Scripting Help 7 21/06/2015 05:43 AM
how to get nearest player name Semo Scripting Help 4 14/07/2013 12:37 AM
nearest Player GoldZoroGrab Scripting Help 3 09/12/2012 11:52 AM
Nearest player budelis Help Archive 2 27/07/2011 08:11 AM
Get nearest player austin070 Help Archive 2 04/03/2011 01:07 AM


All times are GMT. The time now is 07:30 AM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.