refactor(reaction): rework reaction code (#2331)

1. Allow interloper_reaction to use timeout.
2. Fix crash reaction(except TSE) cannot use announce in chat.
3. Allow all friends to bypass auto kick spammers, modder flag and  reactions.
Provides an alternative for users who experience this weird bug https://github.com/YimMenu/YimMenu/issues/2266 . They can just trust their friends until someone provides valuable information for developers to fix.
4. Allow trusting specific players (bypass auto kick spammers, modder flag and reactions).
5. Trust the whole session temporarily (Avoid team members being kicked when in mission).
6. Remove duplicate logs when blocking crash (except for TSE crash)
7. remove unused gamer_instruction_kick in reaction list
8. Allow announce in team only chat
This commit is contained in:
HCR-750F 2023-11-04 21:54:32 +08:00 committed by GitHub
parent b5c7a70e7b
commit 5cd260d198
19 changed files with 135 additions and 62 deletions

View File

@ -20,6 +20,14 @@ namespace big
{
if (!attacker->is_valid() || !victim->is_valid())
return;
if ((attacker->is_friend() && g.session.trust_friends) || attacker->is_trusted || g.session.trust_session)
return;
if (log)
{
uint64_t rockstar_id = attacker->get_net_data() == nullptr ? 0 : attacker->get_net_data()->m_gamer_handle.m_rockstar_id;
LOGF(WARNING, "Received {} from {} ({}), victim is {}", m_event_name, attacker->get_name(), rockstar_id, victim->get_name());
}
if (announce_in_chat)
{
@ -34,8 +42,8 @@ namespace big
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
chat,
false))
notify::draw_chat(chat, g_player_service->get_self()->get_name(), false);
is_team_only))
notify::draw_chat(chat, g_player_service->get_self()->get_name(), is_team_only);
});
}

View File

@ -14,7 +14,7 @@ namespace big
bool m_blockable;
bool m_karmaable;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(interloper_reaction, announce_in_chat, notify, log, add_to_player_db, block_joins, kick, block, karma, timeout)// json doesn't serialize parent fields automatically
NLOHMANN_DEFINE_TYPE_INTRUSIVE(interloper_reaction, announce_in_chat, is_team_only, notify, log, add_to_player_db, block_joins, kick, block, karma, timeout) // json doesn't serialize parent fields automatically
virtual void process(player_ptr attacker, player_ptr victim);
};

View File

@ -19,12 +19,6 @@ namespace big
void reaction::process_common(player_ptr player)
{
if (log)
{
uint64_t rockstar_id = player->get_net_data() == nullptr ? 0 : player->get_net_data()->m_gamer_handle.m_rockstar_id;
LOG(WARNING) << std::format("Received {} from {} ({})", m_event_name, player->get_name(), rockstar_id);
}
if (add_to_player_db)
{
auto entry = g_player_database_service->get_or_create_player(player);
@ -49,7 +43,7 @@ namespace big
player->block_net_events = true;
player->block_clone_sync = true;
player->block_clone_create = true;
LOG(WARNING) << std::format("{} has been timed out", player->get_name());
LOGF(WARNING, "{} has been timed out", player->get_name());
}
}
@ -58,6 +52,14 @@ namespace big
{
if (!player->is_valid())
return;
if ((player->is_friend() && g.session.trust_friends) || player->is_trusted || g.session.trust_session)
return;
if (log)
{
uint64_t rockstar_id = player->get_net_data() == nullptr ? 0 : player->get_net_data()->m_gamer_handle.m_rockstar_id;
LOGF(WARNING, "Received {} from {} ({})", m_event_name, player->get_name(), rockstar_id);
}
if (announce_in_chat)
{
@ -71,8 +73,8 @@ namespace big
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
chat,
false))
notify::draw_chat(chat, g_player_service->get_self()->get_name(), false);
is_team_only))
notify::draw_chat(chat, g_player_service->get_self()->get_name(), is_team_only);
});
}

View File

@ -9,6 +9,7 @@ namespace big
{
public:
bool announce_in_chat = false;
bool is_team_only = false;
bool notify = true;
bool log = true;
bool add_to_player_db = false;
@ -20,7 +21,7 @@ namespace big
const char* m_notify_message;
const char* m_announce_message;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reaction, announce_in_chat, notify, log, add_to_player_db, block_joins, kick, timeout)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reaction, announce_in_chat, is_team_only, notify, log, add_to_player_db, block_joins, kick, timeout)
reaction(const char* event_name, const char* notify_message, const char* announce_message);
virtual void process(player_ptr player);

View File

@ -220,9 +220,7 @@ namespace big
reaction spectate{"Spectate", "%s is spectating you", "%s is spectating me!"};
interloper_reaction spectate_others{"Spectate Others", "%s is spectating %s!", "%s is spectating %s!", false, false};
reaction gamer_instruction_kick{"Gamer Instruction Kick", "Blocked Gamer Instruction Kick from %s", "%s tried to kick me out!"};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, game_anti_cheat_modder_detection, request_control_event, report, gamer_instruction_kick, send_to_interior, spectate, spectate_others)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, game_anti_cheat_modder_detection, request_control_event, report, send_to_interior, spectate, spectate_others)
} reactions{};
struct player
@ -398,6 +396,8 @@ namespace big
bool join_in_sctv_slots = false;
bool lock_session = false;
bool allow_friends_into_locked_session = false;
bool trust_friends = false;
bool trust_session = false;
const char chat_command_prefix = '/';
const char chat_output_prefix = '>';
@ -438,7 +438,7 @@ namespace big
bool fast_join = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join, unhide_players_from_player_list, allow_friends_into_locked_session)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join, unhide_players_from_player_list, allow_friends_into_locked_session, trust_friends)
} session{};
struct settings

View File

@ -99,9 +99,13 @@ namespace big
if (auto entry = g_player_database_service->get_player_by_rockstar_id(
plyr->get_net_data()->m_gamer_handle.m_rockstar_id))
{
plyr->is_modder = entry->is_modder;
plyr->block_join = entry->block_join;
plyr->block_join_reason = entry->block_join_reason;
plyr->is_trusted = entry->is_trusted;
if (!(plyr->is_friend() && g.session.trust_friends))
{
plyr->is_modder = entry->is_modder;
plyr->block_join = entry->block_join;
plyr->block_join_reason = entry->block_join_reason;
}
if (strcmp(plyr->get_name(), entry->name.data()))
{
@ -127,17 +131,17 @@ namespace big
if (g.session.lock_session && g_player_service->get_self()->is_host() && *g_pointers->m_gta.m_is_session_started)
{
if (plyr->is_friend() && g.session.allow_friends_into_locked_session)
if ((plyr->is_friend() && g.session.allow_friends_into_locked_session) || plyr->is_trusted)
{
g_notification_service->push_success("Lock Session",
std::format("A friend with the name of {} has been allowed to join the locked session",
plyr->get_net_data()->m_name));
g_notification_service->push_success("LOBBY_LOCK"_T.data(),
std::vformat("LOBBY_LOCK_ALLOWED"_T.data(),
std::make_format_args(plyr->get_net_data()->m_name)));
}
else
{
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("multikick")))->call(plyr, {});
g_notification_service->push_warning("Lock Session",
std::format("A player with the name of {} has been denied entry", plyr->get_net_data()->m_name));
g_notification_service->push_warning("LOBBY_LOCK"_T.data(),
std::vformat("LOBBY_LOCK_DENIED"_T.data(), std::make_format_args(plyr->get_net_data()->m_name)));
}
}

View File

@ -17,6 +17,7 @@ namespace big
bool result = g_hooking->get_original<hooks::network_player_mgr_init>()(_this, a2, a3, a4);
g.session.trust_session = false;
g_player_service->player_join(_this->m_local_net_player);
g_lua_manager->trigger_event<menu_event::PlayerMgrInit>();
@ -33,6 +34,7 @@ namespace big
if (g.notifications.network_player_mgr_shutdown.notify)
g_notification_service->push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_DESTROY"_T.data());
g.session.trust_session = false;
g_hooking->get_original<hooks::network_player_mgr_shutdown>()(_this);
g_lua_manager->trigger_event<menu_event::PlayerMgrShutdown>();
}

View File

@ -116,7 +116,8 @@ namespace big
if (g.session.log_chat_messages)
spam::log_chat(message, player, true);
player->is_spammer = true;
if (g.session.kick_chat_spammers)
if (g.session.kick_chat_spammers
&& !(player->is_trusted || (player->is_friend() && g.session.trust_friends) || g.session.trust_session))
{
if (g_player_service->get_self()->is_host())
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(player, {}),

View File

@ -379,7 +379,9 @@ namespace big
break;
}
case eRemoteEvent::DestroyPersonalVehicle: g.reactions.destroy_personal_vehicle.process(plyr); return true;
case eRemoteEvent::DestroyPersonalVehicle:
g.reactions.destroy_personal_vehicle.process(plyr);
return true;
case eRemoteEvent::KickFromInterior:
if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].SimpleInteriorData.Owner != plyr->id())
{

View File

@ -46,6 +46,7 @@ namespace big
bool block_join = false;
int block_join_reason = 1;
bool is_modder = false;
bool is_trusted = false;
bool notify_online = false;
std::unordered_set<int> infractions;
std::string custom_infraction_reason = "";
@ -66,7 +67,7 @@ namespace big
std::string game_mode_id = "";
rage::rlSessionInfo redirect_info{};
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(persistent_player, name, rockstar_id, block_join, block_join_reason, is_modder, notify_online, infractions, custom_infraction_reason, notes, command_access_level, join_redirect, join_redirect_preference)
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(persistent_player, name, rockstar_id, block_join, block_join_reason, is_modder, is_trusted, notify_online, infractions, custom_infraction_reason, notes, command_access_level, join_redirect, join_redirect_preference)
const char* get_infraction_description(int infraction);
std::string get_all_infraction_descriptions();

View File

@ -80,6 +80,7 @@ namespace big
bool m_block_permanent_vehicles = false;
bool is_modder = false;
bool is_trusted = false;
bool block_join = false;
int block_join_reason = 0;
bool is_spammer = false;

View File

@ -6,6 +6,8 @@
#include "pointers.hpp"
#include "script.hpp"
#include "services/players/player_service.hpp"
#include "fiber_pool.hpp"
#include "hooking.hpp"
#include <script/HudColor.hpp>
@ -19,17 +21,70 @@ namespace big::notify
HUD::END_TEXT_COMMAND_THEFEED_POST_TICKER(false, false);
}
inline void draw_chat(char* msg, const char* player_name, bool is_team)
{
int scaleform = GRAPHICS::REQUEST_SCALEFORM_MOVIE("MULTIPLAYER_CHAT");
while (!GRAPHICS::HAS_SCALEFORM_MOVIE_LOADED(scaleform))
script::get_current()->yield();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "ADD_MESSAGE");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player name
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_LITERAL_STRING(msg); // content
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_TEXTURE_NAME_STRING(HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(is_team ? "MP_CHAT_TEAM" : "MP_CHAT_ALL")); // scope
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(false); // teamOnly
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "SET_FOCUS");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(1); // VISIBLE_STATE_DEFAULT
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scopeType (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scope (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::DRAW_SCALEFORM_MOVIE_FULLSCREEN(scaleform, 255, 255, 255, 255, 0);
// fix broken scaleforms, when chat alrdy opened
if (const auto chat_data = *g_pointers->m_gta.m_chat_data; chat_data && (chat_data->m_chat_open || chat_data->m_timer_two))
HUD::CLOSE_MP_TEXT_CHAT();
}
inline void crash_blocked(CNetGamePlayer* player, const char* crash)
{
if (player)
{
if ((g_player_service->get_by_id(player->m_player_id)->is_friend() && g.session.trust_friends)
|| g_player_service->get_by_id(player->m_player_id)->is_trusted
|| g.session.trust_session)
return;
if (g.reactions.crash.notify)
g_notification_service->push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name()));
if (g.reactions.crash.log)
LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " ("
<< (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")";
if (g.reactions.crash.announce_in_chat)
{
g_fiber_pool->queue_job([player, crash] {
char chat[255];
snprintf(chat,
sizeof(chat),
std::format("{} {}", g.session.chat_output_prefix, "NOTIFICATION_CRASH_TYPE_BLOCKED"_T).data(),
player->get_name(),
crash);
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
chat,
g.reactions.crash.is_team_only))
draw_chat(chat, g_player_service->get_self()->get_name(), g.reactions.crash.is_team_only);
});
}
g.reactions.crash.process_common(g_player_service->get_by_id(player->m_player_id));
}
else
@ -71,33 +126,4 @@ namespace big::notify
above_map(std::format("<C>{}</C> joined.", net_game_player->get_name()));
}
inline void draw_chat(char* msg, const char* player_name, bool is_team)
{
int scaleform = GRAPHICS::REQUEST_SCALEFORM_MOVIE("MULTIPLAYER_CHAT");
while (!GRAPHICS::HAS_SCALEFORM_MOVIE_LOADED(scaleform))
script::get_current()->yield();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "ADD_MESSAGE");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player name
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_LITERAL_STRING(msg); // content
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_TEXTURE_NAME_STRING(HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(is_team ? "MP_CHAT_TEAM" : "MP_CHAT_ALL")); // scope
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(false); // teamOnly
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "SET_FOCUS");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(1); // VISIBLE_STATE_DEFAULT
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scopeType (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scope (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::DRAW_SCALEFORM_MOVIE_FULLSCREEN(scaleform, 255, 255, 255, 255, 0);
// fix broken scaleforms, when chat alrdy opened
if (const auto chat_data = *g_pointers->m_gta.m_chat_data; chat_data && (chat_data->m_chat_open || chat_data->m_timer_two))
HUD::CLOSE_MP_TEXT_CHAT();
}
}

View File

@ -162,6 +162,8 @@ namespace big::session
{
if (g.debug.fuzzer.enabled)
return;
if ((player->is_friend() && g.session.trust_friends) || player->is_trusted || g.session.trust_session)
return;
auto plyr = g_player_database_service->get_or_create_player(player);
if (!plyr->infractions.contains((int)infraction))

View File

@ -10,6 +10,7 @@
#include "util/session.hpp"
#include "util/toxic.hpp"
#include "views/view.hpp"
#include "backend/bool_command.hpp"
#include <network/Network.hpp>
#include <script/globals/GPBD_FM_3.hpp>
@ -130,6 +131,9 @@ namespace big
ImGui::EndGroup();
}
bool_command whitelist_friends("trustfriends", "TRUST_FRIENDS", "TRUST_FRIENDS_DESC", g.session.trust_friends);
bool_command whitelist_session("trustsession", "TRUST_SESSION", "TRUST_SESSION_DESC", g.session.trust_session);
void render_misc()
{
ImGui::BeginGroup();
@ -148,6 +152,9 @@ namespace big
ImGui::InputInt("##playercount", &g.session.player_magnet_count);
}
components::command_checkbox<"trustfriends">();
components::command_checkbox<"trustsession">();
ImGui::BeginDisabled(!g_player_service->get_self()->is_host());

View File

@ -125,6 +125,7 @@ namespace big
if (ImGui::InputScalar("RID"_T.data(), ImGuiDataType_S64, &current_player->rockstar_id)
|| ImGui::Checkbox("IS_MODDER"_T.data(), &current_player->is_modder)
|| ImGui::Checkbox("TRUST"_T.data(), &current_player->is_trusted)
|| ImGui::Checkbox("BLOCK_JOIN"_T.data(), &current_player->block_join)
|| ImGui::Checkbox("VIEW_NET_PLAYER_DB_TRACK_PLAYER"_T.data(), &current_player->notify_online))
{

View File

@ -129,6 +129,12 @@ namespace big
ImGui::Separator();
if (ImGui::Checkbox("TRUST"_T.data(), &g_player_service->get_selected()->is_trusted))
{
auto entry = g_player_database_service->get_or_create_player(g_player_service->get_selected());
entry->is_trusted = g_player_service->get_selected()->is_trusted;
g_player_database_service->save();
}
ImGui::Checkbox("VIEW_PLAYER_INFO_BLOCK_EXPLOSIONS"_T.data(), &g_player_service->get_selected()->block_explosions);
ImGui::Checkbox("VIEW_PLAYER_INFO_BLOCK_CLONE_CREATE"_T.data(), &g_player_service->get_selected()->block_clone_create);
ImGui::Checkbox("VIEW_PLAYER_INFO_BLOCK_CLONE_SYNC"_T.data(), &g_player_service->get_selected()->block_clone_sync);

View File

@ -25,6 +25,10 @@ namespace big
{
name_appendage += std::format(" [{}]", "MOD"_T);
}
if (current_player->is_trusted)
{
name_appendage += std::format(" [{}]", "TRUST"_T);
}
strcpy(player_tab.name, std::format("{} ({}){}", current_player->get_name(), current_player->id(), name_appendage).c_str());
view::player_info();

View File

@ -45,6 +45,8 @@ namespace big
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.f, 0.67f, 0.f, 1.f));
else if (plyr->is_modder)
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.f, 0.1f, 0.1f, 1.f));
else if (plyr->is_trusted)
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.67f, 0.1f, 1.f));
if (selected_player)
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.29f, 0.45f, 0.69f, 1.f));
@ -82,7 +84,7 @@ namespace big
if (selected_player)
ImGui::PopStyleColor();
if (plyr->is_admin || plyr->is_modder)
if (plyr->is_admin || plyr->is_modder || plyr->is_trusted)
ImGui::PopStyleColor();
// render icons on top of the player button

View File

@ -18,6 +18,8 @@ namespace big
if (ImGui::TreeNode(reaction.m_event_name))
{
ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat);
ImGui::SameLine();
ImGui::Checkbox("IS_TEAM"_T.data(), &reaction.is_team_only);
ImGui::Checkbox("NOTIFY"_T.data(), &reaction.notify);
ImGui::Checkbox("LOG"_T.data(), &reaction.log);
ImGui::Checkbox("REACTION_ADD_TO_DATABASE"_T.data(), &reaction.add_to_player_db);
@ -37,12 +39,15 @@ namespace big
if (ImGui::TreeNode(reaction.m_event_name))
{
ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat);
ImGui::SameLine();
ImGui::Checkbox("IS_TEAM"_T.data(), &reaction.is_team_only);
ImGui::Checkbox("NOTIFY"_T.data(), &reaction.notify);
ImGui::Checkbox("LOG"_T.data(), &reaction.log);
ImGui::Checkbox("REACTION_ADD_TO_DATABASE"_T.data(), &reaction.add_to_player_db);
if (reaction.add_to_player_db)
ImGui::Checkbox("REACTION_BLOCK_JOINS"_T.data(), &reaction.block_joins);
ImGui::Checkbox("REACTION_KICK_ATTACKER"_T.data(), &reaction.kick);
ImGui::Checkbox("TIMEOUT"_T.data(), &reaction.timeout);
if (reaction.m_blockable || reaction.m_karmaable)
ImGui::Separator();
@ -107,8 +112,6 @@ namespace big
draw_reaction(g.reactions.request_control_event);
draw_reaction(g.reactions.spectate);
draw_interloper_reaction(g.reactions.spectate_others);
ImGui::Separator();
draw_reaction(g.reactions.gamer_instruction_kick);
components::title("SETTINGS_NOTIFICATIONS"_T);
components::sub_title("SETTINGS_NOTIFY_GTA_THREADS"_T);