16.01.2019, 21:37
So I have a /spec command. However, there are a few issues:
- /spec works if a player is on foot and in the same world as the admin. Any interior. For all players. If the admin is in a different world, they see blueberry and not the player. This needs to be fixed.
- If the world updates whilst someone is spectating, blueberry appears again. Interior updating works fine.
- If a player is in a vehicle when u type /spec, or if they update and enter/exit a vehicle, it works for any player above id 1. ID 0 however, you get to see blueberry.
See all relevant code below, I hope someone can help.
- /spec works if a player is on foot and in the same world as the admin. Any interior. For all players. If the admin is in a different world, they see blueberry and not the player. This needs to be fixed.
- If the world updates whilst someone is spectating, blueberry appears again. Interior updating works fine.
- If a player is in a vehicle when u type /spec, or if they update and enter/exit a vehicle, it works for any player above id 1. ID 0 however, you get to see blueberry.
See all relevant code below, I hope someone can help.
Code:
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)
{
// spec related start
if(newstate == PLAYER_STATE_DRIVER || newstate == PLAYER_STATE_PASSENGER)
{
if(IsBeingSpeced[playerid] == 1)
{
foreach(new i:Player)
{
if(!IsPlayerConnected(i)) continue;
if(SpecID[i] == playerid)
{
PlayerSpectateVehicle(i, GetPlayerVehicleID(playerid));
}
}
}
}
if(newstate == PLAYER_STATE_ONFOOT)
{
if(IsBeingSpeced[playerid] == 1)
{
foreach(new i:Player)
{
if(!IsPlayerConnected(i)) continue;
if(SpecID[i] == playerid)
{
PlayerSpectatePlayer(i, playerid);
}
}
}
}
// spec related end
return 1;
}
public OnPlayerInteriorChange(playerid, newinteriorid, oldinteriorid)
{
if(IsBeingSpeced[playerid] == 1) // admins will re-spec the player if the int is changed. world updates too.
{
foreach(new i:Player)
{
if(SpecID[i] == playerid)
{
SetPlayerInterior(i,GetPlayerInterior(playerid));
SetPlayerVirtualWorld(i,GetPlayerVirtualWorld(playerid));
}
}
}
return 1;
}
CMD:spec(playerid, params[])
{
if(PlayerInfo[playerid][pAdmin] >= 1)
{
new targetid;
if(GetPlayerState(playerid) == PLAYER_STATE_SPECTATING)
{
TogglePlayerSpectating(playerid, 0);
SetPlayerPos(playerid,SpecX[playerid],SpecY[playerid],SpecZ[playerid]);
SetPlayerFacingAngle(playerid, SpecR[playerid]);
SetPlayerInterior(playerid, SpecI[playerid]);
SetPlayerVirtualWorld(playerid, SpecW[playerid]);
IsSpecing[playerid] = 0;
IsBeingSpeced[SpecID[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 their position, health & armour 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);
if(IsPlayerInAnyVehicle(targetid))
{
TogglePlayerSpectating(playerid, 1);
SetPlayerInterior(playerid, GetPlayerInterior(targetid));
SetPlayerVirtualWorld(playerid, GetPlayerVirtualWorld(targetid));
PlayerSpectateVehicle(playerid, targetid);
}
else
{
TogglePlayerSpectating(playerid, 1);
SetPlayerInterior(playerid, GetPlayerInterior(targetid));
SetPlayerVirtualWorld(playerid, GetPlayerVirtualWorld(targetid));
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;
}
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;
}


