You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When player joins the server (PutInServer), he can't be send to spec mode instantly, because it glitchs the scoreboard, I workaround this by using set_task() with the minimum value (0.1). This is because CBasePlayer::UpdateClientData() is being send twice. Why? Because when you join the server, UpdateClientData() gets send, but when we want to set player to spec, inside CBasePlayer::StartObserver(), the function RemoveAllItems() send agains UpdateClientData(). Sending it twice is the origin of these glitches. https://github.com/rtxa/BugfixedHL/blob/master/dlls/observer.cpp#L52
If we come to a fix, the benefits are:
Not need to rely on set_tasks() or using cmd spectate, making code more easy to reason or read.
No need to manipulate BHL cvars about spectator cooldown without worrying about player not being send to spec.
Solution 1: Prevent BHL from calling UpdateClientData() on PutInServer
We can fix this by implementing a check for RemoveAllItems().
voidCBasePlayer::StartObserver( void )
{
...
// Remove all the player's stuff.// Also prevent calling UpdateClientData() twice when sending to spec on put in serverif (m_bPutInServer)
RemoveAllItems(FALSE, /*UpdateClientData =*/FALSE);
elseRemoveAllItems(FALSE);
Solution 2: Implement set_user_spectator() from AMXX side
Benefits
Not need to rely on set_task() or using cmd spectate.
We can remove the send of Spectator message in LTS/LMS to allow players to be send to spectator without displaying it in the scoreboard. This avoids hooking messages at the right moment.
Disadvantages
We need to keep it in sync with BHL code in case of future updates.
This AMXX implementation tries to mirror how the GameDLL (BugfixedHL) sets spectators. There is some stuff I couldn't mirror well like the removal of players weapons, because from AMXX side, this requires creating an entity to call player_weaponstrip (bad for servers who don't have too much entities to spares). Also, I don't have access to all the members from AMXX side.
// Matchs BugfixedHL behaviour, this should avoid using set_task and fix // bug when using it on putinserverstockag_set_user_spectator(id, bool:spectator =true, onPutInServer =false) {
if (spectator) {
StartObserver(id, onPutInServer);
} else {
StopObserver(id);
}
}
StartObserver(id, onPutInServer =false) {
newFloat:origin[3];
pev(id, pev_origin, origin);
message_begin_f(MSG_PAS, SVC_TEMPENTITY, origin);
write_byte(TE_KILLPLAYERATTACHMENTS);
write_byte(id);
message_end();
new pTank =get_ent_data_entity(id, "CBasePlayer", "m_pTank");
if (pTank != FM_NULLENT) {
ExecuteHamB(Ham_Use, pTank, id, id, USE_OFF, 0.0);
}
// Strip user weapons by default send UpdateClientData()// which is already sent when putting in server, sending it again// brokes the scoreboard for the player.if (onPutInServer) {
set_pev(id, pev_weapons, 0);
} else {
hl_strip_user_weapons(id);// Remove all items (not the HEV suit)
}
// Set HEV sounds offfor (new i; i <get_ent_data_size("CBasePlayer", "m_rgSuitPlayList"); i++) {
set_ent_data(id, "CBasePlayer", "m_rgSuitPlayList", i);
}
static CurWeapon;
if (CurWeapon || (CurWeapon =get_user_msgid("CurWeapon"))) {
message_begin(MSG_ONE, CurWeapon, .player = id);
write_byte(0);
write_byte(0);
write_byte(0);
message_end();
}
set_ent_data(id, "CBasePlayer", "m_iClientFOV", 0);
set_ent_data(id, "CBasePlayer", "m_iFOV", 0);
set_pev(id, pev_fov, 0);
static SetFOV;
if (SetFOV || (SetFOV =get_user_msgid("SetFOV"))) {
message_begin(MSG_ONE, get_user_msgid("SetFOV"), .player = id);
write_byte(0);
message_end();
}
// store view_ofsnewFloat:view_ofs[3];
pev(id, pev_view_ofs, view_ofs);
// setup flagsset_ent_data(id, "CBasePlayer", "m_iHideHUD", HIDEHUD_WEAPONS | HIDEHUD_HEALTH);
set_ent_data(id, "CBasePlayer", "m_afPhysicsFlags", get_ent_data(id, "CBasePlayer", "m_afPhysicsFlags") | PFLAG_OBSERVER);
set_pev(id, pev_view_ofs, NULL_VECTOR);
set_pev(id, pev_fixangle, 1);
set_pev(id, pev_solid, SOLID_NOT);
set_pev(id, pev_takedamage, DAMAGE_NO);
set_pev(id, pev_movetype, MOVETYPE_NONE);
set_ent_data(id, "CBasePlayer", "m_afPhysicsFlags", get_ent_data(id, "CBasePlayer", "m_afPhysicsFlags") &~PFLAG_DUCKING);
set_pev(id, pev_flags, pev(id, pev_flags) &~FL_DUCKING);
set_pev(id, pev_deadflag, DEAD_RESPAWNABLE);
set_pev(id, pev_health, 1.0);
set_pev(id, pev_effects, EF_NODRAW);
// Clear out the status barset_ent_data(id, "CBasePlayer", "m_fInitHUD", 1);
// Clear welcome cam statusset_ent_data(id, "CBasePlayer", "m_bInWelcomeCam", 0);
// set spectator at te same position of spawnnewFloat:specPos[3];
xs_vec_add(origin, view_ofs, specPos);
entity_set_origin(id, specPos);
set_ent_data_float(id, "CBasePlayer", "m_flNextObserverInput", 0.0);
// Observer_SetMode()set_pev(id, pev_iuser1, OBS_ROAMING);
set_pev(id, pev_iuser3, 0);
static TeamInfo;
if (TeamInfo || (TeamInfo =get_user_msgid("TeamInfo"))) {
message_begin(MSG_ALL, TeamInfo);
write_byte(id);
write_string("");
message_end();
}
// Message used by AG/OpenAG clients static Spectator;
if (Spectator || (Spectator =get_user_msgid("Spectator"))) {
message_begin(MSG_ALL, Spectator);
write_byte(id);
write_byte(1);
message_end();
}
}
StopObserver(id) {
// Turn off spectatorset_pev(id, pev_iuser1, 0);
set_pev(id, pev_iuser2, 0);
set_ent_data(id, "CBasePlayer", "m_iHideHUD", 0);
// dllfunc(DllFunc_Spawn, id);ExecuteHamB(Ham_Spawn, id);
set_pev(id, pev_nextthink, -1);
// Message used by AG/OpenAG clients static Spectator;
if (Spectator || (Spectator =get_user_msgid("Spectator"))) {
message_begin(MSG_ALL, Spectator);
write_byte(id);
write_byte(0);
message_end();
}
new teamName[HL_MAX_TEAMNAME_LENGTH];
// Only get it when fully connectedif (pev_valid(id) ==2) {
get_ent_data_string(id, "CBasePlayer", "m_szTeamName", teamName, charsmax(teamName));
}
newFloat:isTeamPlay;
global_get(glb_teamplay, isTeamPlay);
// Update Team Statusstatic TeamInfo;
if (TeamInfo || (TeamInfo =get_user_msgid("TeamInfo"))) {
message_begin(MSG_ALL, TeamInfo);
write_byte(id);
// if (get_cvar_num("mp_teamplay") == 1)if (isTeamPlay ==1.0)
write_string(teamName);
elsewrite_string("Players");
message_end();
}
}
The text was updated successfully, but these errors were encountered:
rtxa
changed the title
Explore refactoring how we sends player to spec mode
Explore refactoring of how we sends player to spec mode
Sep 5, 2024
rtxa
changed the title
Explore refactoring of how we sends player to spec mode
Explore refactoring of how we sends player to spec mode on put in server
Oct 2, 2024
Origin of the issue
When player joins the server (PutInServer), he can't be send to spec mode instantly, because it glitchs the scoreboard, I workaround this by using
set_task()
with the minimum value (0.1). This is becauseCBasePlayer::UpdateClientData()
is being send twice. Why? Because when you join the server,UpdateClientData()
gets send, but when we want to set player to spec, insideCBasePlayer::StartObserver()
, the functionRemoveAllItems()
send againsUpdateClientData()
. Sending it twice is the origin of these glitches. https://github.com/rtxa/BugfixedHL/blob/master/dlls/observer.cpp#L52If we come to a fix, the benefits are:
spectate
, making code more easy to reason or read.spectator
cooldown without worrying about player not being send to spec.Solution 1: Prevent BHL from calling
UpdateClientData()
on PutInServerWe can fix this by implementing a check for
RemoveAllItems()
.Solution 2: Implement set_user_spectator() from AMXX side
Benefits
spectate
.Spectator
message in LTS/LMS to allow players to be send to spectator without displaying it in the scoreboard. This avoids hooking messages at the right moment.Disadvantages
This AMXX implementation tries to mirror how the GameDLL (BugfixedHL) sets spectators. There is some stuff I couldn't mirror well like the removal of players weapons, because from AMXX side, this requires creating an entity to call
player_weaponstrip
(bad for servers who don't have too much entities to spares). Also, I don't have access to all the members from AMXX side.The text was updated successfully, but these errors were encountered: