SA-MP Forums Archive
/spec doesnt work with virtual world even though it changes - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+--- Thread: /spec doesnt work with virtual world even though it changes (/showthread.php?tid=664592)



/spec doesnt work with virtual world even though it changes - Stefhan - 04.03.2019

The admin's world is 0.

The player's world is 5.

The admin proceeds to /spec the player.

The admin's world is set to 5, but regardless of that, I see blueberry.

If the world is the same prior to using /spec, it works fine.

Anyone knows why? All relevant code is below. Please help me fix this.

After this is fixed, I have other issues that need to be dealt with, but the above one is the main issue for now.
These other issues are, multiple people specing one person shouldnt reset the IsBeingSpeced, OnPlayerDeath you should re-spec again automatically, and if the world is updated, you should spec again so you don't see blueberry. But these are issues I will address later, the one above should be fixed first.

Before specing:


While specing:


After specing:


PHP код:
new Float:SpecX[MAX_PLAYERS], Float:SpecY[MAX_PLAYERS], Float:SpecZ[MAX_PLAYERS], Float:SpecR[MAX_PLAYERS], SpecW[MAX_PLAYERS], SpecI[MAX_PLAYERS], IsSpecing[MAX_PLAYERS], IsBeingSpeced[MAX_PLAYERS],SpecID[MAX_PLAYERS];
public 
OnPlayerStateChange(playeridnewstateoldstate)
{
    if(
newstate == PLAYER_STATE_DRIVER || newstate == PLAYER_STATE_PASSENGER)
    {
        if(
IsBeingSpeced[playerid] == 1)
        {
            foreach(new 
i:Player)
            {
                if(
IsSpecing[i] != 1) continue;
                if(
SpecID[i] != playerid) continue;
                
SetPlayerVirtualWorld(iGetPlayerVirtualWorld(playerid));
                
PlayerSpectateVehicle(iGetPlayerVehicleID(playerid));
            }
        }
    }
    if(
oldstate == PLAYER_STATE_DRIVER || oldstate == PLAYER_STATE_PASSENGER)
    {
        if(
IsBeingSpeced[playerid] == 1)
        {
            foreach(new 
i:Player)
            {
                if(
IsSpecing[i] != 1) continue;
                if(
SpecID[i] != playerid) continue;
                
SetPlayerVirtualWorld(iGetPlayerVirtualWorld(playerid));
                
PlayerSpectatePlayer(iplayerid);
            }
        }
    }
    return 
1;
}
public 
OnPlayerInteriorChange(playeridnewinterioridoldinteriorid)
{
    if(
IsBeingSpeced[playerid] == 1)
    {
        foreach(new 
i:Player)
        {
            if(
IsSpecing[i] != 1) continue;
            if(
SpecID[i] != playerid) continue;
            
SetPlayerInterior(iGetPlayerInterior(playerid));
            
SetPlayerVirtualWorld(iGetPlayerVirtualWorld(playerid));
            if(
IsPlayerInAnyVehicle(playerid)) PlayerSpectateVehicle(iGetPlayerVehicleID(playerid));
            else 
PlayerSpectatePlayer(iplayerid);
        }
    }
    return 
1;
}
public 
OnPlayerDisconnect(playeridreason)
{
   if(
IsBeingSpeced[playerid] == 1// admins will stop specing the player if they log out.
    
{
        foreach(new 
i:Player)
        {
            if(
SpecID[i] == playerid)
            {
                
TogglePlayerSpectating(i0);
                
SetPlayerPos(iSpecX[i],SpecY[i],SpecZ[i]);
                
SetPlayerFacingAngle(iSpecR[i]);
                
SetPlayerInterior(iSpecI[i]);
                
SetPlayerVirtualWorld(iSpecW[i]);
                
IsSpecing[playerid] = 0;
                
IsBeingSpeced[SpecID[playerid]] = 0;
                new 
str2[128];
                
format(str2sizeof(str2), "%s %s(%i) has quit spectating ID %i."ReturnAdminLevel(i), ReturnICName(i), iSpecID[playerid]);
                
ABroadCast(COLOR_SADMINstr21);
                new 
action2[20];
                
format(action2sizeof(action2), "spec end (quit)");
                new 
query2[250];
                
mysql_format(g_SQLquery2sizeof(query2), "INSERT INTO logs_punishments(acc_dbid, acc_name, ip_address, time, action, reason, by_acc_dbid, by_acc_name) VALUES('%i', '%e', '-1', UTC_TIMESTAMP(), '%e', '-1', '%i', '%e')"PlayerInfo[playerid][pDBID], ReturnName(playerid), action2PlayerInfo[i][pDBID], ReturnName(i));
                
mysql_tquery(g_SQLquery2);
            }
        }
    }
    
ResetPlayer(playerid);
    return 
1;
}
function:
ResetPlayer(playerid)
{
    
IsSpecing[playerid] = 0;
    
IsBeingSpeced[SpecID[playerid]] = 0;
    return 
1;
}
public 
OnPlayerSpawn(playerid)
{
    if(
FirstSpawn[playerid]) // checks if a player just logged in or registered.
    
{
        
SetPlayerSpawn(playerid);
    }
    if(
IsSpecing[playerid] == 1)
    {
        
SetPlayerPos(playerid,SpecX[playerid],SpecY[playerid],SpecZ[playerid]);
        
SetPlayerFacingAngle(playeridSpecR[playerid]);
        
SetPlayerInterior(playeridSpecI[playerid]);
        
SetPlayerVirtualWorld(playeridSpecW[playerid]);
        
SetPlayerHealth(playeridPlayerInfo[playerid][pHealth]);
        
SetPlayerArmour(playeridPlayerInfo[playerid][pArmour]);
        
IsSpecing[playerid] = 0;
        new 
found_spectator isAnyoneSpecingTarget(playerid);
        if(!
found_spectator)
        {
        
IsBeingSpeced[SpecID[playerid]] = 0;
        }
    }
    return 
1;
}
CMD:spec(playeridparams[])
{
    if(
PlayerInfo[playerid][pAdmin] >= 1)
    {
        new 
targetid;
        if(
GetPlayerState(playerid) == PLAYER_STATE_SPECTATING)
        {
            
TogglePlayerSpectating(playerid0);
            new 
str[128];
            
format(strsizeof(str), "%s %s(%i) has quit spectating %s(%i)."ReturnAdminLevel(playerid), ReturnICName(playerid), playeridReturnICName(SpecID[playerid]), SpecID[playerid]);
            
ABroadCast(COLOR_SADMINstr1);
            new 
action[20];
            
format(actionsizeof(action), "spec end");
            new 
query[250];
            
mysql_format(g_SQLquerysizeof(query), "INSERT INTO logs_punishments(acc_dbid, acc_name, ip_address, time, action, reason, by_acc_dbid, by_acc_name) VALUES('%i', '%e', '%e', UTC_TIMESTAMP(), '%e', '-1', '%i', '%e')"PlayerInfo[targetid][pDBID], ReturnName(targetid), ReturnIP(targetid), actionPlayerInfo[playerid][pDBID], ReturnName(playerid));
            
mysql_tquery(g_SQLquery);
        }
        else
        {
            if(
sscanf(params"u"targetid))
                return 
SCM(playeridCOLOR_INFO"/spec [name/id](leave blank to quit spectating)");
            if(
targetid == playerid)
                return 
SCM(playeridCOLOR_ERROR"You can not use this command on yourself.");
            if(!
IsPlayerConnected(targetid))
                return 
SCM(playeridCOLOR_ERROR"That account is not connected.");
            if(!
Spawned[targetid])
                return 
SCM(playeridCOLOR_ERROR"That player has not logged in or spawned yet.");
            if(
GetPlayerState(targetid) == PLAYER_STATE_SPECTATING)
                return 
SCMEx(playeridCOLOR_ERROR"%s(%i) is spectating %s(%i) right now. Try again later."ReturnICName(targetid), targetidReturnICName(SpecID[targetid]), SpecID[targetid]);
            
OnPlayerSave(playerid); // saves the player data so that they don't get rollbacked for not being spawned if they quit in spec mode.
            
GetPlayerPos(playerid,SpecX[playerid],SpecY[playerid],SpecZ[playerid]);
            
GetPlayerFacingAngle(playeridSpecR[playerid]);
            
SpecI[playerid] = GetPlayerInterior(playerid);
            
SpecW[playerid] = GetPlayerVirtualWorld(playerid);
            
            
SetPlayerVirtualWorld(playeridGetPlayerVirtualWorld(targetid));
            
SetPlayerInterior(playeridGetPlayerInterior(targetid));
            
            
TogglePlayerSpectating(playerid1);
            if(
IsPlayerInAnyVehicle(targetid)) PlayerSpectateVehicle(playeridGetPlayerVehicleID(targetid));
            else 
PlayerSpectatePlayer(playeridtargetid);
            
IsSpecing[playerid] = 1;
            
IsBeingSpeced[targetid] = 1;
            
SpecID[playerid] = targetid;
            new 
str[128];
            
format(strsizeof(str), "%s %s(%i) is spectating %s(%i)."ReturnAdminLevel(playerid), ReturnICName(playerid), playeridReturnICName(targetid), targetid);
            
ABroadCast(COLOR_SADMINstr1);
            new 
action[20];
            
format(actionsizeof(action), "spec start");
            new 
query[250];
            
mysql_format(g_SQLquerysizeof(query), "INSERT INTO logs_punishments(acc_dbid, acc_name, ip_address, time, action, reason, by_acc_dbid, by_acc_name) VALUES('%i', '%e', '%e', UTC_TIMESTAMP(), '%e', '-1', '%i', '%e')"PlayerInfo[targetid][pDBID], ReturnName(targetid), ReturnIP(targetid), actionPlayerInfo[playerid][pDBID], ReturnName(playerid));
            
mysql_tquery(g_SQLquery);
        }
    }
    else return 
SCM(playerid,COLOR_ERROR,"You do not have the required access to execute this command.");
    return 
1;




Re: /spec doesnt work with virtual world even though it changes - JasonRiggs - 04.03.2019

I believe recalling TogglePlayerSpectating and setting it to 1 before using PlayerSpectatePlayer would fix this.


Re: /spec doesnt work with virtual world even though it changes - Stefhan - 04.03.2019

Quote:
Originally Posted by JasonRiggs
Посмотреть сообщение
I believe recalling TogglePlayerSpectating and setting it to 1 before using PlayerSpectatePlayer would fix this.
Isn't it already like this? I'm not sure what you mean. Thanks for looking into it


Re: /spec doesnt work with virtual world even though it changes - polygxn - 05.03.2019

I had some issues with TogglePlayerSpectating before but not in a case like yours. Try to set a one second timer before you use PlayerSpectatePlayer...maybe.


Re: /spec doesnt work with virtual world even though it changes - Stefhan - 05.03.2019

Quote:
Originally Posted by polygxn
Посмотреть сообщение
I had some issues with TogglePlayerSpectating before but not in a case like yours. Try to set a one second timer before you use PlayerSpectatePlayer...maybe.
I really don't want to use a timer.. I don't see why it wouldn't work.. This is pretty upsetting.


Re: /spec doesnt work with virtual world even though it changes - JasonRiggs - 05.03.2019

Quote:
Originally Posted by Stefhan
Посмотреть сообщение
Isn't it already like this? I'm not sure what you mean. Thanks for looking into it
No it is not, before each line of "PlayerSpectatePlayer" put a line of TogglePlayerSpectating and set it to 1


Re: /spec doesnt work with virtual world even though it changes - Stefhan - 05.03.2019

Quote:
Originally Posted by JasonRiggs
Посмотреть сообщение
No it is not, before each line of "PlayerSpectatePlayer" put a line of TogglePlayerSpectating and set it to 1
I have that like this.

PHP код:
            SetPlayerVirtualWorld(playeridGetPlayerVirtualWorld(targetid));
            
SetPlayerInterior(playeridGetPlayerInterior(targetid));
            
            
TogglePlayerSpectating(playerid1);
            if(
IsPlayerInAnyVehicle(targetid)) PlayerSpectateVehicle(playeridGetPlayerVehicleID(targetid));
            else 
PlayerSpectatePlayer(playeridtargetid); 
Is it not good?


Re: /spec doesnt work with virtual world even though it changes - JasonRiggs - 05.03.2019

Quote:
Originally Posted by Stefhan
Посмотреть сообщение
I have that like this.

PHP код:
            SetPlayerVirtualWorld(playeridGetPlayerVirtualWorld(targetid));
            
SetPlayerInterior(playeridGetPlayerInterior(targetid));
            
            
TogglePlayerSpectating(playerid1);
            if(
IsPlayerInAnyVehicle(targetid)) PlayerSpectateVehicle(playeridGetPlayerVehicleID(targetid));
            else 
PlayerSpectatePlayer(playeridtargetid); 
Is it not good?
I'm talking about the part under OnPlayerStateChange and OnPlayerInteriorChange..


Re: /spec doesnt work with virtual world even though it changes - NaS - 05.03.2019

You need to put a little delay between TogglePlayerSpectating and PlayerSpactatePlayer/Vehicle if you just switched virtual worlds.

Regarding the IsBeingSpeced issue, you might want to use a simple loop to determine whether or not a player is spectating them. You'd need a loop to prevent it from reseting anyway in case there are 2 players spectating.


Re: /spec doesnt work with virtual world even though it changes - Stefhan - 05.03.2019

Quote:
Originally Posted by NaS
Посмотреть сообщение
You need to put a little delay between TogglePlayerSpectating and PlayerSpactatePlayer/Vehicle if you just switched virtual worlds.

Regarding the IsBeingSpeced issue, you might want to use a simple loop to determine whether or not a player is spectating them. You'd need a loop to prevent it from reseting anyway in case there are 2 players spectating.
How do I add a delay? Why don't other people use a delay? Literally everyone's spec works the same yet mine bugs out like this...


Re: /spec doesnt work with virtual world even though it changes - JasonRiggs - 05.03.2019

So basically you need a delay to make a gap between the changing of the target's variable and the spectator variables it's just a little timer like that
PHP код:
foreach(new Player)
    {
        if(
PlayerInfo[i][pSpectating] == playerid)
        {
            
SetTimerEx("SpectateTimer"500false"ii"iplayerid);
        }
    } 
and its function to be like that..

PHP код:
forward SpectateTimer(playeridtargetid);
public 
SpectateTimer(playeridtargetid)
{
    if(
PlayerInfo[playerid][pSpectating] == targetid)
    {
        
SetPlayerInterior(playeridGetPlayerInterior(targetid));
        
SetPlayerVirtualWorld(playeridGetPlayerVirtualWorld(targetid));

        if(
IsPlayerInAnyVehicle(targetid))
        {
            
PlayerSpectateVehicle(playeridGetPlayerVehicleID(targetid));
        }
        else
        {
            
PlayerSpectatePlayer(playeridtargetid);
        }
    }

I tested this one and it worked for me.


Re: /spec doesnt work with virtual world even though it changes - Stefhan - 05.03.2019

Quote:
Originally Posted by JasonRiggs
Посмотреть сообщение
So basically you need a delay to make a gap between the changing of the target's variable and the spectator variables it's just a little timer like that
PHP код:
foreach(new Player)
    {
        if(
PlayerInfo[i][pSpectating] == playerid)
        {
            
SetTimerEx("SpectateTimer"500false"ii"iplayerid);
        }
    } 
and its function to be like that..

PHP код:
forward SpectateTimer(playeridtargetid);
public 
SpectateTimer(playeridtargetid)
{
    if(
PlayerInfo[playerid][pSpectating] == targetid)
    {
        
SetPlayerInterior(playeridGetPlayerInterior(targetid));
        
SetPlayerVirtualWorld(playeridGetPlayerVirtualWorld(targetid));
        if(
IsPlayerInAnyVehicle(targetid))
        {
            
PlayerSpectateVehicle(playeridGetPlayerVehicleID(targetid));
        }
        else
        {
            
PlayerSpectatePlayer(playeridtargetid);
        }
    }

I tested this one and it worked for me.
I appreciate this a lot but it seems like a very inefficient way to do it like this.. Nobody has it like that from the stuff I could find on ******, why doesn't my code work when it's pretty much the same?


Re: /spec doesnt work with virtual world even though it changes - polygxn - 05.03.2019

Its not the same, as I mentioned you need that delay, even if its only 1 sec. For example if you want to kick someone but before that you want to send a SendClientMessage you need to add that 1 sec delay cause if not your kick going to be executed first, and the SCM will not be shown (hope you understand, Im pretty tired).


Re: /spec doesnt work with virtual world even though it changes - Stefhan - 06.03.2019

Quote:
Originally Posted by polygxn
Посмотреть сообщение
Its not the same, as I mentioned you need that delay, even if its only 1 sec. For example if you want to kick someone but before that you want to send a SendClientMessage you need to add that 1 sec delay cause if not your kick going to be executed first, and the SCM will not be shown (hope you understand, Im pretty tired).
Alright then. Thanks a lot everyone.