IsPlayerInRangePoint Help.... +Rep
#1

Hey guys

i made a command which creates object at playerspos when he use a specific command
and i want to make that if any player approaches near the object it should send them a clientmessage for that i think i should use IsPlayerInRangePoint under OnPlayerUpdate but how to make this for all the objects that are created in the server

Please Help me
Thanks in Advance


Edit: After showing client message and exploding the object will be destroyed so the pos should be removed from the loop
is it possible??
Reply
#2

1) Use arrays for storing object position. For example:
pawn Код:
enum objectsenum
{
    Float:ox,
    Float:oy,
    Float:oz
}
new Objects[MAX_OBJECTS][objectsenum];
MAX_OBJECTS can be your own value too.

Now when you create a object, just save the coords of position of object while creating. For example:
pawn Код:
CreateObject(model, X, Y, Z, rX, rY, r)
Objects[i][ox] = X, Objects[i][oy] = Y, Objects[i][oz] = Z;
You can also hook CeateObject.

Now onplayerupdate, i don't recommend onplayerupdate though.
pawn Код:
public OnPlayerUpdate(playerid)
{
    for(new i; i < MAX_OBJECTS; i++)
    {
        if(IsValidObject(i))
        {
            if(IsPlayerInRangeOfPoint(playerid, 5.0, Objects[i][ox], Objects[i][oy], Objects[i][oz]))
            {
                SendClientMessage(playerid, -1, "your msg");
            }
        }
    }
    return 1;
}
Reply
#3

Quote:
Originally Posted by Gammix
Посмотреть сообщение
1) Use arrays for storing object position. For example:
pawn Код:
enum objectsenum
{
    Float:ox,
    Float:oy,
    Float:oz
}
new Objects[MAX_OBJECTS][objectsenum];
MAX_OBJECTS can be your own value too.

Now when you create a object, just save the coords of position of object while creating. For example:
pawn Код:
CreateObject(model, X, Y, Z, rX, rY, r)
Objects[i][ox] = X, Objects[i][oy] = Y, Objects[i][oz] = Z;
You can also hook CeateObject.

Now onplayerupdate, i don't recommend onplayerupdate though.
pawn Код:
public OnPlayerUpdate(playerid)
{
    for(new i; i < MAX_OBJECTS; i++)
    {
        if(IsValidObject(i))
        {
            if(IsPlayerInRangeOfPoint(playerid, 5.0, Objects[i][ox], Objects[i][oy], Objects[i][oz]))
            {
                SendClientMessage(playerid, -1, "your msg");
            }
        }
    }
    return 1;
}
I think this will work only for one object
i want it to work for all the created objects

and what you recommend otherthan onplayerupdate?
Reply
#4

I think you should just attach labels to each object. This is way more efficient and they are streamed (which is what you want your message to do).

EDIT: No his version will not just be for one object, that's what the loop (which is very un-efficient but is the only way to stream the messages) is for.
Reply
#5

Quote:
Originally Posted by Crayder
Посмотреть сообщение
I think you should just attach labels to each object. This is way more efficient and they are streamed (which is what you want your message to do).
They not only sendclientmessage but also explodes thats the reason i want it

Edit: After showing client message and exploding the object will be destroyed so the pos should be reomved from the loop
is it possible??
Reply
#6

Quote:
Originally Posted by kesarthakur
Посмотреть сообщение
They not only sendclientmessage but also explodes thats the reason i want it

Edit: After showing client message and exploding the object will be destroyed so the pos should be reomved from the loop
is it possible??
1. You should use y_iterate at the least (add only objects you want to explode).
2. You have to destroy the object yourself, an explosion won't do so for you.
3. An object will no longer be in the loop if it is destroyed so the position will not need to be removed.
Reply
#7

My method will work for all objects you created and having position stored in the array. I missed a check just add this:
pawn Код:
public OnPlayerUpdate(playerid)
{
    for(new i; i < MAX_OBJECTS; i++)
    {
        if(IsValidObject(i) && Objects[i][ox] != 0.0 && Objects[i][oy] != 0.0 && Objects[i][oz] != 0.0)
        {
            if(IsPlayerInRangeOfPoint(playerid, 5.0, Objects[i][ox], Objects[i][oy], Objects[i][oz]))
            {
                SendClientMessage(playerid, -1, "your msg");
            }
        }
    }
    return 1;
}
Rather than OnPlayerUpdate, use a timer or make use of a custom callback based on player position updating(best way).
Reply
#8

Again, it is still way more efficient to use y_iterate. I'll give an example (some snips of my old proximity mine script) in a sec (done).

Код:
#include <a_samp>
#include <sscanf>
#include <YSI\y_commands> // Or ZCMD. This system is compatible with both (as is all other scripts using ZCMD).
#include <YSI\y_iterate>

#define MAX_PROX 5 //Change to your liking.

new Iterator:Proximeter[MAX_PLAYERS]<MAX_OBJECTS>, bool:Active[MAX_OBJECTS];
CMD:prox(playerid, params[])
{
	if(Iter_Count(Proximeter[playerid]) == MAX_PROX)
		return SendClientMessage(playerid, -1, "You can't have more than 5 Proximity Mines planted.");
	
	new time;
	if(sscanf(params, "i", time))
		return SendClientMessage(playerid, COLOR_ERROR, "[Command] Error: /Prox <time before activation>");
	else if(5 > time > 30)
		return SendClientMessage(playerid, COLOR_ERROR, "[Command] Error: The timer can only be set between 5 and 30 seconds.");
	
	else
	{
		GetPlayerPos(playerid, nx, ny, z);
		new id = CreateObject(19602, nx, ny, nz, rx, ry, rz);
		Iter_Add(Proximeter[playerid], id);
		Active[id] = false;
		SetTimerEx("AddProx", time*1000, false, "i", id);
		return SendClientMessage(playerid, -1, sprintf("You now have %i Proximity Mine(s) planted.", Iter_Count(Proximeter[playerid])));
	}
}

forward AddProx(proxid); public AddProx(proxid)
{
	SetObjectMaterial(proxid, 0, -1, "none", "none", 0xFFFF0000); //Turns it red when active, nice touch!
	Active[proxid] = true; //Activates the proximeter.
	return 1;
}

public OnGameModeInit()
{
	Iter_Init(Proximeter);
	return 1;
}

public OnPlayerUpdate(playerid)
{
	foreach(new p : Player) //if(GetPlayerTeam(p) != GetPlayerTeam(playerid))// Remove this comment if you want to check the teams.
	foreach(new m : Proximeter[p]) if(Active[m])
	{
		new Float:P[3];
		GetObjectPos(m, P[0], P[1], P[2]);
		if(IsPlayerInRangeOfPoint(playerid, 10.0, P[0], P[1], P[2]))
		{
			Iter_Remove(Proximeter[p], m);
			DestroyObject(m);
			CreateExplosion(P[0], P[1], P[2], 6, 10.0);
		}
	}
	return 1;
}
Features:
- Sly use of y_iterate for object handling.
- Efficient foreach (aka y_iterate) loops, the loop will not even go on if the mines do not exist.
- Command with time to run away, used to activate the mines.
- Mines are green when inactive, but turn red when they are active.
- Explosions (because you said you like explosions ofc).

@Gammix, I'm not against your method at all, just pointing out the better efficiency of this method.
Reply
#9

Thank you both

+repped
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)