SA-MP Forums

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

Reply
 
Thread Tools Display Modes
Old 19/02/2015, 02:09 AM   #1
JR_Junior
Huge Clucker
 
Join Date: Nov 2011
Location: Brazil
Posts: 225
Reputation: 54
Lightbulb Update Spectating Status - The solution!

INTRODUCTION
Today I present to you a very good tutorial and useful for all servers.
The system is very simple, no bugs and without the use of Timers! Enjoy!

THE SYSTEM
Are you tired of typing /spec every time the player enter/exit a vehicle, teleport, go away, etc?
Keep calm, now your problems are over!
The system will automatically detect and update all the information for the Spectator instantly.
No need Timers or anything that harms the server, are only required some standard Callbacks and 1 new to all work perfectly.
All tested and working fine!

TUTORIAL

Variables:
pawn Code:
//So, we need to create in the top of gamemode this variable
new Spectating[MAX_PLAYERS]; //Simple variable to define the spected ID for the spectator ID.

//Using this variable:

//Use Spectating[playerid] = -1; To set a none spected ID for the spectador ID.
//Use Spectating[playerid] = spectedid; To set the ID of the spected player.

Example Commands:
pawn Code:
//Now, we need to create or use an existing commands to spec a player.
/spec - To spectate another player.
/specoff - To stop spectating.

Standard Callbacks and Functions:
pawn Code:
//We gonna use this folowing callbacks and functions to make the system.
OnPlayerConnect(); - To set Spectating[playerid] = -1;(Not spectating)
OnPlayerStreamOut(); - Called when the player Streamed out for another player.
OnPlayerStateChange(); - Called when the player change your state(Die, Spawn, Enter a vehicle, Exit a vehicle, etc).
TogglePlayerSpectating(); - To Toggle on or Toggle off the spectating mode.
PlayerSpectateVehicle(); - To set spectating mode if the spectedid is in a vehicle.
PlayerSpectatePlayer(); - To set spectating mode if the spectedid is on foot.

New Callbacks and Functions:
pawn Code:
//This callback we gonna create too.
UpdateSpectatingStatus(); - Will be called when the player change the state or stream out for a player.

First step:
pawn Code:
//You make it too in OnPlayerDisconnect(playerid) and OnPlayerSpawn(playerid) or another like want.
public OnPlayerConnect(playerid)
{
   Spectating[playerid] = -1;
   //Setting this variable to -1 we toggle non-spectaing ID to the spectador ID.
   return 1;
}

Creating(if not exist) the spectating commands:
pawn Code:
//Here you can use the or make like you want.
//The tools and functions to execute the commands are old(but works too).
//This is only a example to make the Update Spectating Status work.
public OnPlayerCommandText(playerid, cmdtext[])
{
    new cmd[256],tmp[256],giveplayerid,idx;
    cmd = strtok(cmdtext, idx);
   
    if(strcmp(cmd, "/spec", true) == 0)
    {
        tmp = strtok(cmdtext, idx);//Here we gonna set the spected ID, example:  /spec 5
        giveplayerid = ReturnUser(tmp);//Getting the spected ID to the variable "giveplayerid".
        if(IsPlayerConnected(giveplayerid))
        {
            //Getting the virtual world and interior of the spected ID and setting it to the spectator ID.
            SetPlayerVirtualWorld(playerid,GetPlayerVirtualWorld(giveplayerid));
            SetPlayerInterior(playerid,GetPlayerInterior(giveplayerid));
            //Now we gonna set the spected ID(giveplayerid) to the spectator ID(playerid).
            Spectating[playerid] = giveplayerid;
            //This function will start the spectating mode for the spectator ID.
            TogglePlayerSpectating(playerid, 1);

            //Define between PlayerSpectateVehicle(); - (if spected ID is in a vehicle) or PlayerSpectatePlayer(); - (if spected ID is not in a vehicle).
            if(IsPlayerInAnyVehicle(giveplayerid)) PlayerSpectateVehicle(playerid, GetPlayerVehicleID(giveplayerid), SPECTATE_MODE_NORMAL);
            else PlayerSpectatePlayer(playerid, giveplayerid, SPECTATE_MODE_NORMAL);
        }
        else return SendClientMessage(playerid, -1, "Warning: This player is not connected!");
        return 1;
    }
    if(strcmp(cmd, "/specoff", true) == 0)
    {
        if(IsPlayerConnected(playerid))
        {
            //Here we gonna set a default virtual world and interior to the spectator ID.
            SetPlayerVirtualWorld(playerid,0);
            SetPlayerInterior(playerid,0);
            //Setting a none spected ID(important to stop the Updating system).
            Spectating[playerid] = -1;
            //Now the spectating mode is off.
            TogglePlayerSpectating(playerid, 1);
        }
        return 1;
    }
    return 0;
}

Calling the Updating system:
pawn Code:
public OnPlayerStreamOut(playerid, forplayerid)
{
     //When the spected ID(playerid) teleport, change the virtual world or interior, go away, etc...
    //"forplayerid" is the spectator ID in this case.
    if(IsPlayerConnected(forplayerid))
    {
        if(Spectating[forplayerid] == playerid)//Check if "forplayerid" is spectating the playerid.
        {
            //This new callback will check the status of the spected ID and update it to the spectator ID.
            UpdateSpectatingStatus(forplayerid, playerid);
        }
    }
    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
    //If the spected ID(playerid) enter/exit the vehicle, spawn, etc...
    for(new i = 0; i < GetMaxPlayers(); i++)
    {
        if(IsPlayerConnected(i))
        {
            if(Spectating[i] == playerid)//Check if someone is spectating him.
            {
                //This new callback will check the status of the spected ID(playerid) and update it to the spectator ID(i).
                UpdateSpectatingStatus(i, playerid);
            }
        }
    }
    return 1;
}

Last step is the function to Update the Spectating Status:
pawn Code:
stock UpdateSpectatingStatus(spectatorid, spectedid);
{
    //If the spectator ID is really spectating the spected ID...
    if(Spectating[spectatorid] == spectedid)
    {
        //This warnings you can use or not...
        if(GetPlayerState(spectedid) == PLAYER_STATE_WASTED) return GameTextForPlayer(spectatorid, "~r~Target wasted!", 5000, 3);
        if(GetPlayerState(spectedid) == PLAYER_STATE_SPECTATING) return GameTextForPlayer(spectatorid, "~r~Target in spectating mode!", 5000, 3);
        if(!IsPlayerConnected(spectedid)) return GameTextForPlayer(spectatorid, "~r~Target disconnected!", 5000, 3);
       
        //Again setting the virtual world and interior for the spectator ID.
        SetPlayerVirtualWorld(spectatorid,GetPlayerVirtualWorld(spectedid));
        SetPlayerInterior(spectatorid,GetPlayerInterior(spectedid));
        //Put the spectator ID in the spectating mode.
        TogglePlayerSpectating(spectatorid, 1);
        if(IsPlayerInAnyVehicle(spectedid)) PlayerSpectateVehicle(spectatorid, GetPlayerVehicleID(spectedid), SPECTATE_MODE_NORMAL);
        else PlayerSpectatePlayer(spectatorid, spectedid, SPECTATE_MODE_NORMAL);
    }
    return 1;
}

WARNING
- The script is just a base, using "outdated" or "slower" functions(for some expert scripters).
- Not all scripters use the "Updated or Improved" functions.
- You can use any functions you want or based in your Game Mode.
- The script is only to show how to make a simple code but functional.
- You can edit like you want.
- First test it before talk or report any thing that you don't know.
- You may get bugs if not enable/disable the variable based in the player ID.
- If you no need this or is not useful for you, leave it.
- If you have not read or did not consider these warnings, I will ignore your critical comment!

"As time went on people developed better methods (namely dcmd/sscanf, smaller arrays etc) so the old methods should have been forgotten right? Wrong!" - ******

THE SCRIPT

Here the complete script(example) to get a base/test or use it in your server:
pawn Code:
//==============================================================================//
//                       Update Spectating Status
//                           Creator: JR_Junior
//                        Date: February, 19, 2015
//
//==============================================================================//
#include <a_samp>

new Spectating[MAX_PLAYERS];

public OnPlayerConnect(playerid)
{
   Spectating[playerid] = -1;
   return 1;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
    new cmd[256],tmp[256],giveplayerid,idx;
    cmd = strtok(cmdtext, idx);

    if(strcmp(cmd, "/spec", true) == 0)
    {
        tmp = strtok(cmdtext, idx);
        giveplayerid = ReturnUser(tmp);
        if(IsPlayerConnected(giveplayerid))
        {
            SetPlayerVirtualWorld(playerid,GetPlayerVirtualWorld(giveplayerid));
            SetPlayerInterior(playerid,GetPlayerInterior(giveplayerid));
            Spectating[playerid] = giveplayerid;
            TogglePlayerSpectating(playerid, 1);
            if(IsPlayerInAnyVehicle(giveplayerid)) PlayerSpectateVehicle(playerid, GetPlayerVehicleID(giveplayerid), SPECTATE_MODE_NORMAL);
            else PlayerSpectatePlayer(playerid, giveplayerid, SPECTATE_MODE_NORMAL);
        }
        else return SendClientMessage(playerid, -1, "Warning: This player is not connected!");
        return 1;
    }
    if(strcmp(cmd, "/specoff", true) == 0)
    {
        if(IsPlayerConnected(playerid))
        {
            SetPlayerVirtualWorld(playerid,0);
            SetPlayerInterior(playerid,0);
            Spectating[playerid] = -1;
            TogglePlayerSpectating(playerid, 1);
        }
        return 1;
    }
    return 0;
}

public OnPlayerStreamOut(playerid, forplayerid)
{
    if(IsPlayerConnected(forplayerid))
    {
        if(Spectating[forplayerid] == playerid)
        {
            UpdateSpectatingStatus(forplayerid, playerid);
        }
    }
    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
    for(new i = 0; i < GetMaxPlayers(); i++)
    {
        if(IsPlayerConnected(i))
        {
            if(Spectating[i] == playerid)
            {
                UpdateSpectatingStatus(i, playerid);
            }
        }
    }
    return 1;
}

stock UpdateSpectatingStatus(spectatorid, spectedid);
{
    if(Spectating[spectatorid] == spectedid)
    {
        if(GetPlayerState(spectedid) == PLAYER_STATE_WASTED) return GameTextForPlayer(spectatorid, "~r~Target wasted!", 5000, 3);
        if(GetPlayerState(spectedid) == PLAYER_STATE_SPECTATING) return GameTextForPlayer(spectatorid, "~r~Target in spectating mode!", 5000, 3);
        if(!IsPlayerConnected(spectedid)) return GameTextForPlayer(spectatorid, "~r~Target disconnected!", 5000, 3);
        SetPlayerVirtualWorld(spectatorid,GetPlayerVirtualWorld(spectedid));
        SetPlayerInterior(spectatorid,GetPlayerInterior(spectedid));
        TogglePlayerSpectating(spectatorid, 1);
        if(IsPlayerInAnyVehicle(spectedid)) PlayerSpectateVehicle(spectatorid, GetPlayerVehicleID(spectedid), SPECTATE_MODE_NORMAL);
        else PlayerSpectatePlayer(spectatorid, spectedid, SPECTATE_MODE_NORMAL);
    }
    return 1;
}

//If you dont have this following funtions in yours includes or game mode, you will need it to test this script.
ReturnUser(text[])
{
    new pos = 0;
    while (text[pos] < 0x21)
    {
        if (text[pos] == 0) return INVALID_PLAYER_ID;
        pos++;
    }
    new userid = INVALID_PLAYER_ID;
    if (IsNumeric(text[pos]))
    {
        userid = strval(text[pos]);
        if(userid >=0 && userid < MAX_PLAYERS)
        {
            if(!IsPlayerConnected(userid)) userid = INVALID_PLAYER_ID;
            else return userid;
        }
    }
    new len = strlen(text[pos]);
    new count = 0;
    new name[MAX_PLAYER_NAME];
    for (new i = 0; i < MAX_PLAYERS; i++)
    {
        if(IsPlayerConnected(i))
        {
            GetPlayerName(i, name, sizeof (name));
            if (strcmp(name, text[pos], true, len) == 0)
            {
                if (len == strlen(name)) return i;
                else count++,userid = i;
            }
        }
    }
    if(count != 1) userid = INVALID_PLAYER_ID;
    return userid;
}
IsNumeric(const string[])
{
    for (new i = 0, j = strlen(string); i < j; i++) if(string[i] > '9' || string[i] < '0') return 0;
    return 1;
}
strtok(string[],&idx,seperator = ' ')
{
    new ret[128], i = 0, len = strlen(string);
    while(string[idx] == seperator && idx < len) idx++;
    while(string[idx] != seperator && idx < len) ret[i] = string[idx],i++,idx++;
    while(string[idx] == seperator && idx < len) idx++;
    return ret;
}
__________________
"You can disrespect peoples work, but then don't be surprised when they go away." - Kalcor

Last edited by JR_Junior; 20/02/2015 at 11:51 PM. Reason: Update
JR_Junior is offline   Reply With Quote
Old 19/02/2015, 08:15 AM   #2
AndySedeyn
High-roller
 
AndySedeyn's Avatar
 
Join Date: Feb 2014
Location: Belgium
Posts: 1,207
Reputation: 681
Default Re: Update Spectating Status - The solution!

You have explained absolutely nothing and you are using outdated tools.
I didn't even bother looking at the rest of the code. This is, just like many, a copy-paste topic.
Post it as a filterscript in the right section instead of a poorly written tutorial.
AndySedeyn is offline   Reply With Quote
Old 19/02/2015, 09:48 AM   #3
JR_Junior
Huge Clucker
 
Join Date: Nov 2011
Location: Brazil
Posts: 225
Reputation: 54
Default Re: Update Spectating Status - The solution!

Quote:
Originally Posted by Bible View Post
You have explained absolutely nothing and you are using outdated tools.
I didn't even bother looking at the rest of the code. This is, just like many, a copy-paste topic.
Post it as a filterscript in the right section instead of a poorly written tutorial.
First, thank you for your comment!
My friend is a simple script, does not need much explanation. Just will not understand who is very newbie.
Outdated tools? Just because I have not used ZCMD? Just because it's a simple script but it works?
Friend, is a tutorial / base and you use the tools you want.
You may not need it, but has many they will need! Thank you!
__________________
"You can disrespect peoples work, but then don't be surprised when they go away." - Kalcor
JR_Junior is offline   Reply With Quote
Old 19/02/2015, 09:54 AM   #4
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,830
Reputation: 114
Default Re: Update Spectating Status - The solution!

Meh, you didn't even explain anything here, you are just throwing out code at us.
Go to the filterscripts section if you want to create and share a script, in a tutorial you should explain to people how and why they need to do things.
Also, you are using heavily outdated methods, such as strcmp in OnPlayerCommandText, and strtok.
__________________
[Tutorial] Custom Playerdamage system
Desert Eagle's dealing too much damage, you want one-hit sniper kills, or damage based on body parts? Check this out.
CalvinC is offline   Reply With Quote
Old 19/02/2015, 09:56 AM   #5
Ryan_Bowe
Huge Clucker
 
Join Date: Jul 2012
Location: United States
Posts: 218
Reputation: 16
Default Re: Update Spectating Status - The solution!

You're using outdated and slower methods. Even though the code is basic it still needs more explanation.

http://forum.sa-mp.com/showthread.php?t=65567
Ryan_Bowe is offline   Reply With Quote
Old 19/02/2015, 10:21 AM   #6
JR_Junior
Huge Clucker
 
Join Date: Nov 2011
Location: Brazil
Posts: 225
Reputation: 54
Default Re: Update Spectating Status - The solution!

Quote:
Originally Posted by CalvinC View Post
Meh, you didn't even explain anything here, you are just throwing out code at us.
Go to the filterscripts section if you want to create and share a script, in a tutorial you should explain to people how and why they need to do things.
Also, you are using heavily outdated methods, such as strcmp in OnPlayerCommandText, and strtok.
Quote:
Originally Posted by Ryan_Bowe View Post
You're using outdated and slower methods. Even though the code is basic it still needs more explanation.

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

"As time went on people developed better methods (namely dcmd/sscanf, smaller arrays etc) so the old methods should have been forgotten right? Wrong!" - ******

I will explain more... thank you all!
__________________
"You can disrespect peoples work, but then don't be surprised when they go away." - Kalcor
JR_Junior is offline   Reply With Quote
Old 19/02/2015, 11:41 AM   #7
Excel™
Gangsta
 
Excel™'s Avatar
 
Join Date: Jul 2012
Posts: 548
Reputation: 95
Default Re: Update Spectating Status - The solution!

Code:
UpdateSpectatingStatus
Not used in calling nor in timers, so why not this is stock function -_-

Code:
public OnPlayerCommandText(playerid, cmdtext[])
Why not use zcmd standards

Code:
strcmp
This is slow as he'll and thats why people recommend zcmd!

Code:
strtok
Another slow motion there, implement sscanf!
__________________
NO MORE CODING SAMP :V
JUST PLAYING...
Excel™ is offline   Reply With Quote
Old 19/02/2015, 11:44 AM   #8
JR_Junior
Huge Clucker
 
Join Date: Nov 2011
Location: Brazil
Posts: 225
Reputation: 54
Default Re: Update Spectating Status - The solution!

Quote:
Originally Posted by Excel™ View Post
Code:
UpdateSpectatingStatus
Not used in calling nor in timers, so why not this is stock function -_-
Thanks for remember this!
__________________
"You can disrespect peoples work, but then don't be surprised when they go away." - Kalcor
JR_Junior is offline   Reply With Quote
Old 19/02/2015, 11:50 AM   #9
CalvinC
High-roller
 
CalvinC's Avatar
 
Join Date: Nov 2014
Location: Denmark
Posts: 1,830
Reputation: 114
Default Re: Update Spectating Status - The solution!

Quote:
Originally Posted by Excel™ View Post
Code:
UpdateSpectatingStatus
Not used in calling nor in timers, so why not this is stock function -_-

Code:
public OnPlayerCommandText(playerid, cmdtext[])
Why not use zcmd standards

Code:
strcmp
This is slow as he'll and thats why people recommend zcmd!

Code:
strtok
Another slow motion there, implement sscanf!
Excel, "stock" and a function is 2 different things.
Stock will make the compiler ignore something if it's not used in your script, thereby also hiding warnings/errors, and not including it in your .amx file.

Example of a normal function:
pawn Code:
FuncName(parameters)
Using stock:
pawn Code:
stock FuncName(parameters)
Or:
pawn Code:
new stock VariableName;
Haven't used stock for anything else, but you might be able to use it for more.

I believe that public functions can be called between filterscripts etc. by adding it like this:
pawn Code:
public FuncName(parameters)

Thereby, "public" and "stock" are 2 different add-ons.
But in that example, both "stock" and "public" is useless, unless you wanna use it between scripts.
__________________
[Tutorial] Custom Playerdamage system
Desert Eagle's dealing too much damage, you want one-hit sniper kills, or damage based on body parts? Check this out.
CalvinC is offline   Reply With Quote
Old 19/02/2015, 11:54 AM   #10
Excel™
Gangsta
 
Excel™'s Avatar
 
Join Date: Jul 2012
Posts: 548
Reputation: 95
Default Re: Update Spectating Status - The solution!

Quote:
Originally Posted by CalvinC View Post
Excel, "stock" and a function is 2 different things.
Stock will make the compiler ignore something if it's not used in your script, thereby also hiding warnings/errors, and not including it in your .amx file.

Example of a normal function:
pawn Code:
FuncName(parameters)
Using stock:
pawn Code:
stock FuncName(parameters)
Or:
pawn Code:
new stock VariableName;
Haven't used stock for anything else, but you might be able to use it for more.

I believe that public functions can be called between filterscripts etc. by adding it like this:
pawn Code:
public FuncName(parameters)

Thereby, "public" and "stock" are 2 different add-ons, i don't think any of them are necessary for this script though.
I can't control but here it is: I never compared stock or local functions. I just for simplicity stated stock function but I apologize! Secondally, using stock Is better than a callback! Can be used in the form of an include!
__________________
NO MORE CODING SAMP :V
JUST PLAYING...
Excel™ 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
how to update a texdraws status? rangerxxll Scripting Help 4 06/03/2014 04:14 AM
Update Vehicle Damage Status problem... Ins1d3 Scripting Help 0 26/01/2014 06:11 PM
Spectating help +rep! [M.A]Angel[M.A] Scripting Help 4 09/08/2012 11:46 PM
update vehicle damage status Q WillyP Help Archive 0 28/10/2010 06:33 PM
[0.3a - solution] 0x006F5636 Address crash solution JonyAvati Client Support 0 24/12/2009 03:13 PM


All times are GMT. The time now is 09:10 AM.


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