[Include] Arrow.inc Create And Point Arrows At Stuff
#1

arrow.inc


Description
This include allows you to create arrows (white arrow modelid: 1318) and easily point them at things. This could be very useful for GPS systems among other things.

Functions

pawn Код:
//global arrows
native Arrow:CreateArrow(Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE);
native PointArrowAtPoint(Arrow:arrowid, Float: x, Float: y, Float: z);
native DestroyArrow(Arrow:arrowid);
native SetArrowPos(Arrow:arrowid, Float: x, Float: y, Float: z);
native GetArrowPos(Arrow:arrowid, &Float: x, &Float: y, &Float: z);
native GetArrowRot(Arrow:arrowid, &Float: rx, &Float: ry, &Float: rz);
native SetArrowRot(Arrow:arrowid, Float: rx, Float: ry, Float: rz);
native PointArrowAtPlayer(Arrow:arrowid, playerid);
native PointArrowAtVehicle(Arrow:arrowid, vehicleid);
native PointArrowAtObject(Arrow:arrowid, objectid);
native SetArrowColor(Arrow:arrowid, argb_color);
//player arrows
native Arrow:CreatePlayerArrow(playerid, Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE);
native PointPlayerArrowAtPoint(playerid, Arrow:arrowid, Float: x, Float: y, Float: z);
native DestroyPlayerArrow(playerid, Arrow:arrowid);
native SetPlayerArrowPos(playerid, Arrow:arrowid, Float: x, Float: y, Float: z);
native GetPlayerArrowPos(playerid, Arrow:arrowid, &Float: x, &Float: y, &Float: z);
native GetPlayerArrowRot(playerid, Arrow:arrowid, &Float: rx, &Float: ry, &Float: rz);
native SetPlayerArrowRot(playerid, Arrow:arrowid, Float: rx, Float: ry, Float: rz);
native PointPlayerArrowAtPlayer(playerid, Arrow:arrowid, playerid);
native PointPlayerArrowAtVehicle(playerid, Arrow:arrowid, vehicleid);
native PointPlayerArrowAtObject(playerid, Arrow:arrowid, objectid);
native PointPlayerArrowAtPlayerObject(playerid, Arrow:arrowid, targetplayerid, targetobjectid);
native SetPlayerArrowColor(playerid, Arrow:arrowid, argb_color);
Most of those functions are very self explanatory, but here are a few explained.

CreateArrow
pawn Код:
/*
    Function:
        CreateArrow
    Description:
        Creates an arrow at the given point, pointing to a target location.
    Param(s):
        x, y, z      - Position to create the arrow.
        target_x/y/z - Position to point the arrow at
        stream_dist  - stream distance for the arrow (default DEFAULT_ARROW_DRAW_DISTANCE)
    Returns:
        Arrowid for the newly created arrow. (returned by CreateObject or CreateDynamicObject

*/

stock Arrow:CreateArrow(Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE
PointArrowAtPoint
pawn Код:
/*
    Function:
        PointArrowAtPoint
    Description:
        Points the given arrow at the given point
    Param(s):
        arrowid  - The arrowid returned by "CreateArrow" function.
        x, y, z  - The point, to point the arrow at
    Returns:
        This function does not return a value

*/

stock PointArrowAtPoint(Arrow:arrowid, Float: x, Float: y, Float: z)
DestroyArrow
pawn Код:
/*
    Function:
        DestroyArrow
    Description:
        Destroys the given arrow.
    Param(s):
        arrowid - The arrowid returned by "CreateArrow" function
    Returns:
        Value returned by DestroyObject or DestroyDynamicObject

*/

stock DestroyArrow(Arrow:arrowid)
SetArrowPos
pawn Код:
/*
    Function:
        SetArrowPos
    Description:
        Sets a new position for the given arrow.
    Param(s):
        arrowid - The arrowid returned by "CreateArrow" function.
        x, y, z - The new position for the arrow to be placed.
    Returns:
        Value returned by SetObjectPos or SetDynamicObjectPos

*/

stock SetArrowPos(Arrow:arrowid, Float: x, Float: y, Float: z)
Basic Usage

A simple command to create a player arrow and point it at a player, This command deletes the arrow when used a second time.
pawn Код:
#include <arrow>
#include <zcmd>

new Arrow:gArrows[MAX_PLAYERS];//arrow ids now have the Arrow: tag.
new bool:gPlayerHasArrow[MAX_PLAYERS];

COMMAND:arrow(playerid, params[])
{
    if( !gPlayerHasArrow[ playerid ] )
    {
        new
            targetplayerid = strval(params),
            Float: x, Float: y, Float: z
        ;
       
        GetPlayerPos(playerid, x, y, z);
       
        //create a player arrow at playerids location pointing to 0.0, 0.0, 0.0
        gArrows[playerid] = CreatePlayerArrow(playerid, x, y, z, 0.0, 0.0, 0.0);//assign arrowid to var
       
        //NOTE: colours are in ARGB format
        SetArrowColor( gArrows[playerid], 0xAAFF0000 );//set arrow color to red
       
        //point the arrow at a target player
        PointPlayerArrowAtPlayer( playerid, gArrows[playerid], targetplayerid );
        gPlayerHasArrow[ playerid ] = true;
    }
    else
    {
        DestroyPlayerArrow( playerid, gArrows[playerid] );
        gPlayerHasArrow[ playerid ] = false;
    }
    return 1;
}
Basic Usage 2
A small script i wrote fast that adds a /locate <playername/id> command. This creates an arrow above the players head that points at a player.
pawn Код:
#define FILTERSCRIPT

#include <a_samp>
#include <zcmd>//Credit Zeex
#include <sscanf2>//credit ******
#include <arrow>

#define ARROW_UPDATE_TIME           (50) //how often locator arrows position updates (ms)

enum E_PLAYER_DATA
{
    Arrow: e_LOCATOR_ARROW,
   
    bool: e_IS_LOCATING,
   
    e_LOCATOR_TIMER_ID,
    e_LOCATOR_TARGETID,
}

new gPlayerData[ MAX_PLAYERS ][ E_PLAYER_DATA ];


//simple timer function to update the arrows position and point it to target
forward public OnArrowUpdate(playerid);    

public OnFilterScriptInit()
{
    print("\n--------------------------------------");
    print(" arrow.inc example");
    print("--------------------------------------\n");
   
    for( new i=0; i < MAX_PLAYERS; ++i )
    {
        gPlayerData[ i ][ e_LOCATOR_TIMER_ID ] = -1;
        gPlayerData[i][e_LOCATOR_ARROW] = INVALID_ARROW_ID;
        gPlayerData[i][ e_IS_LOCATING ] = false;
        gPlayerData[ i ][ e_LOCATOR_TARGETID ] = INVALID_PLAYER_ID;
    }
    return 1;
}

public OnFilterScriptExit()
{
    //clean up arrows
    for( new i=0; i < MAX_PLAYERS; ++i )
    {
        KillArrowTimer( i );
    }
    return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
    KillArrowTimer( playerid );
    return 1;
}

COMMAND:locate(playerid, params[])
{
    if( !gPlayerData[ playerid ][ e_IS_LOCATING ] )
    {
        new
            iTargetID = INVALID_PLAYER_ID
        ;
       
        if( sscanf(params, "u", iTargetID ) )
        {
            SendClientMessage(playerid, -1, "<Syntax Error>: Usage /locate <username/id>");
            return 1;
        }
        else
        {
            if( iTargetID != INVALID_PLAYER_ID )
            {
                //now target is online, so get both players position
                //set variables, create arrow and start timer.
           
                new
                    Float: ax, Float: ay, Float: az,//arrow position
                    Float: tx, Float: ty, Float: tz//target position
                ;
               
                GetPlayerPos(playerid, ax, ay, az);
                GetPlayerPos(iTargetID, tx, ty, tz);
               
                gPlayerData[ playerid ][ e_LOCATOR_TARGETID ] = iTargetID;
               
                gPlayerData[ playerid ][ e_IS_LOCATING ] = true;
               
                //create and assign the arrow, pointint to target player
                gPlayerData[ playerid ][ e_LOCATOR_ARROW ] = CreatePlayerArrow(playerid, ax, ay, az+1.2, tx, ty, tz);
               
                gPlayerData[ playerid ][ e_LOCATOR_TIMER_ID ] = SetTimerEx("OnArrowUpdate", ARROW_UPDATE_TIME, true, "d", playerid);
            }
        }
    }
    else
    {
        //player already locating, so stop this one.
        KillArrowTimer( playerid );
        SendClientMessage(playerid, -1, "<Player Locator>: Finished locating target.");
    }
    return 1;
}

public OnArrowUpdate(playerid)
{
    static
        Float: _s_px = 0.0, Float: _s_py = 0.0, Float: _s_pz = 0.0
    ;
   
    if( !IsPlayerConnected( gPlayerData[ playerid ][ e_LOCATOR_TARGETID ] ) )
    {
        KillArrowTimer( playerid );
        SendClientMessage(playerid, -1, "<Player Locator>: Finished locating target. (target disconnected)");
        return 1;
    }
   
    if( GetPlayerPos( playerid, _s_px, _s_py, _s_pz ) )
    {
        //both player connected, set pos and rotation of arrow..
        SetPlayerArrowPos( playerid, gPlayerData[ playerid ][ e_LOCATOR_ARROW ], _s_px, _s_py, _s_pz+1.2 );//1.2 == slightly avove ped head
        PointPlayerArrowAtPlayer( playerid, gPlayerData[ playerid ][ e_LOCATOR_ARROW ], gPlayerData[ playerid ][ e_LOCATOR_TARGETID ] );
    }
    else
    {
        //make sure timer dies if player isn't connected
        KillArrowTimer( playerid );
    }
    return 1;
}

stock KillArrowTimer( playerid )
{
    if( gPlayerData[ playerid][ e_LOCATOR_TIMER_ID ] != -1 )
    {
        KillTimer(gPlayerData[ playerid ][ e_LOCATOR_TIMER_ID ]);
        gPlayerData[ playerid][ e_LOCATOR_TIMER_ID ] = -1;
        DestroyPlayerArrow(playerid, gPlayerData[ playerid ][ e_LOCATOR_ARROW ]);
        gPlayerData[playerid][e_LOCATOR_ARROW] = INVALID_ARROW_ID;
        gPlayerData[playerid][ e_IS_LOCATING ] = false;
        gPlayerData[ playerid ][ e_LOCATOR_TARGETID ] = INVALID_PLAYER_ID;
    }
}
Streamer config
Because the streamer plugin is very popular and allows you to create more objects, this include uses it by default. If you don't use the streamer plugin, please make the following definition BEFORE including arrow.inc.

EG:
pawn Код:
#define ARROW_NO_STREAMER
#include <arrow>
NOTES
  • All arrowids now have the Arrow: tag.
  • When setting an arrows colour please use the ARGB format, not RGBA like SendClientMessage.
  • PointArrowAtPoint is an expensive function, as there is a lot of floating point arithmetic, so do speed tests on your system before calling it for example in OnPlayerUpdate every update (not a good idea).
Changelog:
Код:
<27/07/13 v1.3>	
	* Values returned by CreateArrow now have the Arrow: tag, to avoid confusion with normal objectids.
	* All function headers expecting an arrowid have changed to accept the new Arrow: tag.
	* Added functions:
		SetArrowRot
		SetPlayerArrowRot
		
	* Fixed more comment errors.
		
24/07/13 v1.2:
	*Player arrows added.
	* Added functions:
		CreatePlayerArrow
		PointPlayerArrowAtPoint
		DestroyPlayerArrow
		SetPlayerArrowPos
		GetPlayerArrowPos
		GetPlayerArrowRot
		PointPlayerArrowAtPlayer
		PointPlayerArrowAtVehicle
		PointPlayerArrowAtObject
		PointPlayerArrowAtPlayerObject
		SetPlayerArrowColor
		
	*Functions changed
		PointArrowAtPoint   - No loner does rotation calculations if the arrow isn't a valid object. And returns 0 on failure.
	
	*Fixed some comment errors.
		
23/07/13 v1.1:
	*Arrows now rotate along the Y-Axis, so they an point vertically. (Antonio144)
22/07/13 v1.0:
	*Initial release.
Credits
Incoginto - Streamer plugin
Antonio144 - GetYRotation function
Sa:mp Team - Sa:mp

Download
Pastebin
Solidfiles
Dropbox

[ame]www.youtube.com/watch?v=Bj5uTvZu2_A[/ame]
Reply
#2

Screenshots please?
Reply
#3

What about attaching? You'll need some extra rotation patches if you add that through, otherwise this is simple and nice, especially for beginners ^ who have problems with points
Reply
#4

I did a system for attaching but it meant constantly updating the arrows position above the players head (or other offset) constantly. That was quite inefficient, so i thought i'd leave it to the end user. I couldn't get it working with AttachObject because rotating the object doesn't work.

If you have any ideas how to get it to attach to the player and still be able to point it at things, please let me know. (if it's not what i describe above)
Reply
#5

In creating this arrow is this Object? or something that checkpoint?
Reply
#6

You should use a variable to store the object id's and return the index the coding looks good but lacks checking when doing actions which could lead to the potential of modifying objects that are not even part of the system. That is what I would do to it so you have some fail safes in place when something goes wrong.

http://pastebin.com/ndL2hxWr
Reply
#7

here you go

pawn Код:
new Float:x, Float:y, Float:z;
GetVehiclePos(vehicleid, x, y, z);
GetVehicleZAngle(vehicleid, angle);
new Float:r_Z = atan2(y - DestY, x - DestX) - angle;
Credits to RyDeR`, he thought me about angles with some functions he gave me.
Reply
#8

Quote:
Originally Posted by [uL]Pottus
Посмотреть сообщение
You should use a variable to store the object id's and return the index the coding looks good but lacks checking when doing actions which could lead to the potential of modifying objects that are not even part of the system. That is what I would do to it so you have some fail safes in place when something goes wrong.
I didn't want to introduce limits, using variables would have to have "MAX_ARROWS" defined and i didn't want to do that. This include has a very small footprint (0 global variables), using variables to store info on 10000 (i know thats a lot but you never know) arrows would munch up lot's of space. It is up to the end user to use this correctly. It's very simple to use, and if people have trouble using the correct objectid.... they should give their head a wobble. I suggested GetObjectModelID in Suggestions for future SA:MP updates, for that reason. I do get where your coming from though.
Quote:
Originally Posted by Kar
Here you go...
Thanks pal, i have a very busy day today so i will test this out tonight. If it works accurately i will use that and give credit. Seems like that would be a lot faster than the method I'm using.

EDIT: @ToiletDuck please read the first sentence in the thread, and look at screenies.

Thanks all for your input.
Reply
#9

10,000 takes up an insignificant amount also you can't expect the user to use it correctly and when something does go wrong the absolute last thing you want is your system to be setting arbitrary actions on random objects the user will have no idea how it's happening. Less code does not mean it's better code any dynamic should index it's associated components always cutting corners like you did is bad practice.
Reply
#10

Why is there no target z?
Reply
#11

Quote:
Originally Posted by [uL]Pottus
View Post
10,000 takes up an insignificant amount also you can't expect the user to use it correctly and when something does go wrong the absolute last thing you want is your system to be setting arbitrary actions on random objects the user will have no idea how it's happening. Less code does not mean it's better code any dynamic should index it's associated components always cutting corners like you did is bad practice.
You have a very valid point.

Your right i shouldn't expect the end user to use it correctly. I just thought the benefits outweigh the risks, that was probably a bit naive. It is unlikely that a player will do "PointArrowAtPoint" on a normal object id. But if anything can go wrong, it will go wrong i guess. May edit it, not sure yet. Thanks again for your input.

Wish there was a "GetObjectModelID" function badly.

Quote:
Originally Posted by wups
View Post
Why is there no target z?
I don't know how to make those calculations. If you know how plz let me know.
Reply
#12

I fixed it last night maybe you missed the pastebin link

Some other good things with this way you can do.

- Put the arrow object reference ids in an enum with with say a playerid as an enum field then you could make global and player associated arrows (INVALID_PLAYER_ID would signify it is a global arrow) this way when a player disconnects all their arrows can be destroyed by the user by initiating a system function which is good ex - DestroyPlayerArrows(playerid);

- You can make a function to delete all arrows global and/or player

http://pastebin.com/ndL2hxWr
Reply
#13

Not sure i want to use variables yet TBH. There are some (easy to fix) major problems with your fix too, CreateArrow assigns the arrow to the first slot in the array then returns (every time). There are also no bounds checks. When/if i edit it, i will use something similar to what you did, and give cred.

Also nice suggestion for player arrows, that will definitely be implemented. Thanks for the suggestion.

I'm also going to try and find a good font/font size, to add text to the arrows. (or let user decide)
Reply
#14

Ya your right, I wrote that last night when I was dead tired

It's actually only one line missing.

if(gArrowObjectID[i] != INVALID_ARROW_ID) continue;

For OOB checking just add this at the top of all functions that require it.

pawn Code:
if(arrowid < 0 || arrowid >= MAX_ARROWS)
{
    printf("Error: Arrows.Inc::FunctionName()::OOB arrowid reference Arrowid: %i", arrowid);
    return INVALID_ARROW_ID;
}
pawn Code:
Or if you want it a bit cleaner

#define OOBCheck(%0,%1); if(%0 < 0 || %0 >= MAX_ARROWS) { \
    printf("Error: Arrows.Inc::%s Arrowid: %i", %1, %0); \
    return INVALID_ARROW_ID; }

becomes

OOBCheck(arrowid, "Error: Arrows.Inc::FunctionName()::OOB arrowid reference");

I don't usually put OOB checking in my code crashdetect usually works fine but your right if something can go wrong it will go wrong so it's probably a good idea to put into released code.
Reply
#15

Here's the code for target_z, ie object Y rotation
pawn Code:
// x,y,z arrow position; ax,ay,az, target position
stock Float:GetYRotation(Float:x,Float:y,Float:z, Float:ax, Float:ay, Float:az)
{
    new Float:Yoff;
    new Float:xd = ax - x;
    new Float:yd = ay - y;
    new Float:zd = az - z;
    new Float:dist = floatsqroot(xd*xd+yd*yd+zd*zd);
    Yoff = acos((az-z)/dist);
    return Yoff-180;
}
EDIT: This is 20% faster since it uses two less calculations
pawn Code:
stock Float:GetYRotation(Float:x,Float:y,Float:z, Float:ax, Float:ay, Float:az)
{
    new Float:xd = ax - x;
    new Float:yd = ay - y;
    new Float:dist = floatsqroot(xd*xd+yd*yd);
    new Float:Yoff = atan((z-az)/dist);
    return Yoff-90;
}
Reply
#16

Quote:
Originally Posted by Antonio144
View Post
Here's the code for target_z, ie object Y rotation...
Works perfect! Thanks Antonio.

@Pottus: As for the risk of user using random objects, i might just use an "arw:" tag for the vars returned by "CreateArrow" that way the compiler will throw a warning if an objectid is used with an arrow function. I think that would be a better solution, than using large arrays.

EG,
pawn Code:
arw:CreateArrow(...)
Still not sure yet.

UPDATE:
Example/Links have been updated. Arrows can now rotate along the Y-Axis (up/down), so they can point at flying vehicles or top of a building from the bottom etc.

Changes to functions:

Create arrow now uses "target_z" parameter.
pawn Code:
CreateArrow(Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE);
PointArrowAtPoint now takes "z" parameter.
pawn Code:
PointArrowAtPoint(arrowid, Float: x, Float: y, Float: z);
Use other rotation functions the same (PointArrowAtPlayer etc), but they will now point directly at the target.

UPDATE 2:
Player arrows added.
pawn Code:
native CreatePlayerArrow(playerid, Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE);
native PointPlayerArrowAtPoint(playerid, arrowid, Float: x, Float: y, Float: z);
native DestroyPlayerArrow(playerid, arrowid);
native SetPlayerArrowPos(playerid, arrowid, Float: x, Float: y, Float: z);
native GetPlayerArrowPos(playerid, arrowid, &Float: x, &Float: y, &Float: z);
native GetPlayerArrowRot(playerid, arrowid, &Float: rx, &Float: ry, &Float: rz);
native PointPlayerArrowAtPlayer(playerid, arrowid, playerid);
native PointPlayerArrowAtVehicle(playerid, arrowid, vehicleid);
native PointPlayerArrowAtObject(playerid, arrowid, objectid);
native PointPlayerArrowAtPlayerObject(playerid, arrowid, targetplayerid, targetobjectid);
native SetPlayerArrowColor(playerid, arrowid, argb_color);
Reply
#17

UPDATE V1.3:
IMPORTANT: If you are already using this include, updating will cause lots of tag mismatch warnings. I won't be changing the syntax from now on, sorry about that.

Values returned by "CreateArrow" now carry the "Arrow:" tag. This must be used when declaring variables that will hold arrowids. Examples and function list on first post have been updated.
EG,
pawn Code:
#include <arrow>
#include <zcmd>

new Arrow:gArrows[MAX_PLAYERS];//arrow ids now have the Arrow: tag.
new bool:gPlayerHasArrow[MAX_PLAYERS];

COMMAND:arrow(playerid, params[])
{
    if( !gPlayerHasArrow[ playerid ] )
    {
        new
            targetplayerid = strval(params),
            Float: x, Float: y, Float: z
        ;
       
        GetPlayerPos(playerid, x, y, z);
       
        //create a player arrow at playerids location pointing to 0.0, 0.0, 0.0
        gArrows[playerid] = CreatePlayerArrow(playerid, x, y, z, 0.0, 0.0, 0.0);//assign arrowid to var
       
        //NOTE: colours are in ARGB format
        SetArrowColor( gArrows[playerid], 0xAAFF0000 );//set arrow color to red
       
        //point the arrow at a target player
        PointPlayerArrowAtPlayer( playerid, gArrows[playerid], targetplayerid );
        gPlayerHasArrow[ playerid ] = true;
    }
    else
    {
        DestroyPlayerArrow( playerid, gArrows[playerid] );
        gPlayerHasArrow[ playerid ] = false;
    }
    return 1;
}
pawn Code:
//global arrows
native Arrow:CreateArrow(Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE);
native PointArrowAtPoint(Arrow:arrowid, Float: x, Float: y, Float: z);
native DestroyArrow(Arrow:arrowid);
native SetArrowPos(Arrow:arrowid, Float: x, Float: y, Float: z);
native GetArrowPos(Arrow:arrowid, &Float: x, &Float: y, &Float: z);
native GetArrowRot(Arrow:arrowid, &Float: rx, &Float: ry, &Float: rz);
native SetArrowRot(Arrow:arrowid, Float: rx, Float: ry, Float: rz);//new func in 1.3
native PointArrowAtPlayer(Arrow:arrowid, playerid);
native PointArrowAtVehicle(Arrow:arrowid, vehicleid);
native PointArrowAtObject(Arrow:arrowid, objectid);
native SetArrowColor(Arrow:arrowid, argb_color);
//player arrows
native Arrow:CreatePlayerArrow(playerid, Float: x, Float: y, Float: z, Float: target_x, Float: target_y, Float: target_z, Float: stream_dist = DEFAULT_ARROW_DRAW_DISTANCE);
native PointPlayerArrowAtPoint(playerid, Arrow:arrowid, Float: x, Float: y, Float: z);
native DestroyPlayerArrow(playerid, Arrow:arrowid);
native SetPlayerArrowPos(playerid, Arrow:arrowid, Float: x, Float: y, Float: z);
native GetPlayerArrowPos(playerid, Arrow:arrowid, &Float: x, &Float: y, &Float: z);
native GetPlayerArrowRot(playerid, Arrow:arrowid, &Float: rx, &Float: ry, &Float: rz);
native SetPlayerArrowRot(playerid, Arrow:arrowid, Float: rx, Float: ry, Float: rz);//new func in 1.3
native PointPlayerArrowAtPlayer(playerid, Arrow:arrowid, playerid);
native PointPlayerArrowAtVehicle(playerid, Arrow:arrowid, vehicleid);
native PointPlayerArrowAtObject(playerid, Arrow:arrowid, objectid);
native PointPlayerArrowAtPlayerObject(playerid, Arrow:arrowid, targetplayerid, targetobjectid);
native SetPlayerArrowColor(playerid, Arrow:arrowid, argb_color);
EDIT: After doing some experimentation with "SetObjectMaterial/MaterialText" i have come to the conclusion that unfortunately, it can't be done for textures and text with this object.
Reply


Forum Jump:


Users browsing this thread: 4 Guest(s)