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(playerid, newstate, oldstate)
{
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(i, GetPlayerVirtualWorld(playerid));
PlayerSpectateVehicle(i, GetPlayerVehicleID(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(i, GetPlayerVirtualWorld(playerid));
PlayerSpectatePlayer(i, playerid);
}
}
}
return 1;
}
public OnPlayerInteriorChange(playerid, newinteriorid, oldinteriorid)
{
if(IsBeingSpeced[playerid] == 1)
{
foreach(new i:Player)
{
if(IsSpecing[i] != 1) continue;
if(SpecID[i] != playerid) continue;
SetPlayerInterior(i, GetPlayerInterior(playerid));
SetPlayerVirtualWorld(i, GetPlayerVirtualWorld(playerid));
if(IsPlayerInAnyVehicle(playerid)) PlayerSpectateVehicle(i, GetPlayerVehicleID(playerid));
else PlayerSpectatePlayer(i, playerid);
}
}
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
if(IsBeingSpeced[playerid] == 1) // admins will stop specing the player if they log out.
{
foreach(new i:Player)
{
if(SpecID[i] == playerid)
{
TogglePlayerSpectating(i, 0);
SetPlayerPos(i, SpecX[i],SpecY[i],SpecZ[i]);
SetPlayerFacingAngle(i, SpecR[i]);
SetPlayerInterior(i, SpecI[i]);
SetPlayerVirtualWorld(i, SpecW[i]);
IsSpecing[playerid] = 0;
IsBeingSpeced[SpecID[playerid]] = 0;
new str2[128];
format(str2, sizeof(str2), "%s %s(%i) has quit spectating ID %i.", ReturnAdminLevel(i), ReturnICName(i), i, SpecID[playerid]);
ABroadCast(COLOR_SADMIN, str2, 1);
new action2[20];
format(action2, sizeof(action2), "spec end (quit)");
new query2[250];
mysql_format(g_SQL, query2, sizeof(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), action2, PlayerInfo[i][pDBID], ReturnName(i));
mysql_tquery(g_SQL, query2);
}
}
}
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(playerid, SpecR[playerid]);
SetPlayerInterior(playerid, SpecI[playerid]);
SetPlayerVirtualWorld(playerid, SpecW[playerid]);
SetPlayerHealth(playerid, PlayerInfo[playerid][pHealth]);
SetPlayerArmour(playerid, PlayerInfo[playerid][pArmour]);
IsSpecing[playerid] = 0;
new found_spectator = isAnyoneSpecingTarget(playerid);
if(!found_spectator)
{
IsBeingSpeced[SpecID[playerid]] = 0;
}
}
return 1;
}
CMD:spec(playerid, params[])
{
if(PlayerInfo[playerid][pAdmin] >= 1)
{
new targetid;
if(GetPlayerState(playerid) == PLAYER_STATE_SPECTATING)
{
TogglePlayerSpectating(playerid, 0);
new str[128];
format(str, sizeof(str), "%s %s(%i) has quit spectating %s(%i).", ReturnAdminLevel(playerid), ReturnICName(playerid), playerid, ReturnICName(SpecID[playerid]), SpecID[playerid]);
ABroadCast(COLOR_SADMIN, str, 1);
new action[20];
format(action, sizeof(action), "spec end");
new query[250];
mysql_format(g_SQL, query, sizeof(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), action, PlayerInfo[playerid][pDBID], ReturnName(playerid));
mysql_tquery(g_SQL, query);
}
else
{
if(sscanf(params, "u", targetid))
return SCM(playerid, COLOR_INFO, "/spec [name/id](leave blank to quit spectating)");
if(targetid == playerid)
return SCM(playerid, COLOR_ERROR, "You can not use this command on yourself.");
if(!IsPlayerConnected(targetid))
return SCM(playerid, COLOR_ERROR, "That account is not connected.");
if(!Spawned[targetid])
return SCM(playerid, COLOR_ERROR, "That player has not logged in or spawned yet.");
if(GetPlayerState(targetid) == PLAYER_STATE_SPECTATING)
return SCMEx(playerid, COLOR_ERROR, "%s(%i) is spectating %s(%i) right now. Try again later.", ReturnICName(targetid), targetid, ReturnICName(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(playerid, SpecR[playerid]);
SpecI[playerid] = GetPlayerInterior(playerid);
SpecW[playerid] = GetPlayerVirtualWorld(playerid);
SetPlayerVirtualWorld(playerid, GetPlayerVirtualWorld(targetid));
SetPlayerInterior(playerid, GetPlayerInterior(targetid));
TogglePlayerSpectating(playerid, 1);
if(IsPlayerInAnyVehicle(targetid)) PlayerSpectateVehicle(playerid, GetPlayerVehicleID(targetid));
else PlayerSpectatePlayer(playerid, targetid);
IsSpecing[playerid] = 1;
IsBeingSpeced[targetid] = 1;
SpecID[playerid] = targetid;
new str[128];
format(str, sizeof(str), "%s %s(%i) is spectating %s(%i).", ReturnAdminLevel(playerid), ReturnICName(playerid), playerid, ReturnICName(targetid), targetid);
ABroadCast(COLOR_SADMIN, str, 1);
new action[20];
format(action, sizeof(action), "spec start");
new query[250];
mysql_format(g_SQL, query, sizeof(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), action, PlayerInfo[playerid][pDBID], ReturnName(playerid));
mysql_tquery(g_SQL, query);
}
}
else return SCM(playerid,COLOR_ERROR,"You do not have the required access to execute this command.");
return 1;
}
I believe recalling TogglePlayerSpectating and setting it to 1 before using PlayerSpectatePlayer would fix this.
|
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.
|
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
|
SetPlayerVirtualWorld(playerid, GetPlayerVirtualWorld(targetid));
SetPlayerInterior(playerid, GetPlayerInterior(targetid));
TogglePlayerSpectating(playerid, 1);
if(IsPlayerInAnyVehicle(targetid)) PlayerSpectateVehicle(playerid, GetPlayerVehicleID(targetid));
else PlayerSpectatePlayer(playerid, targetid);
I have that like this.
PHP код:
|
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. |
foreach(new i : Player)
{
if(PlayerInfo[i][pSpectating] == playerid)
{
SetTimerEx("SpectateTimer", 500, false, "ii", i, playerid);
}
}
forward SpectateTimer(playerid, targetid);
public SpectateTimer(playerid, targetid)
{
if(PlayerInfo[playerid][pSpectating] == targetid)
{
SetPlayerInterior(playerid, GetPlayerInterior(targetid));
SetPlayerVirtualWorld(playerid, GetPlayerVirtualWorld(targetid));
if(IsPlayerInAnyVehicle(targetid))
{
PlayerSpectateVehicle(playerid, GetPlayerVehicleID(targetid));
}
else
{
PlayerSpectatePlayer(playerid, targetid);
}
}
}
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 код:
PHP код:
|
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).
|