/spec doesnt work with virtual world even though it changes
#1

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;

Reply
#2

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

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
Reply
#4

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.
Reply
#5

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.
Reply
#6

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
Reply
#7

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?
Reply
#8

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..
Reply
#9

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.
Reply
#10

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...
Reply
#11

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.
Reply
#12

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?
Reply
#13

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).
Reply
#14

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.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)