#pragma semicolon 1
#include <amxmodx>
#include <reapi>
#include <json>
new const PLUGIN_VERSION[] = "0.2.1";
new const JSON_CONFIG_FILE[] = "/C4Timer.json";
const TASK_ID_C4_TIMER = 1312;
const Float:TIMER_UPDATE_INTERVAL = 1.0;
enum _:DhudSettingsStruct {
Float:DHUD_RED,
Float:DHUD_GREEN,
Float:DHUD_BLUE,
Float:DHUD_X_POS,
Float:DHUD_Y_POS,
Float:DHUD_EFFECT,
Float:DHUD_FX_TIME,
Float:DHUD_HOLD_TIME,
Float:DHUD_FADE_IN_TIME,
Float:DHUD_FADE_OUT_TIME
}
enum _:MsgIndex {
MSG_SHOW_TIMER,
MSG_ROUND_TIME
}
new g_iC4Entity,
g_fDhudSettings[DhudSettingsStruct],
Float:g_flExplodeTime,
g_szDhudMessage[128],
bool:g_bDhudEnabled,
g_iMsgId[MsgIndex];
public plugin_init() {
register_plugin("[ReAPI] C4 Timer", PLUGIN_VERSION, "mIDnight");
if (rg_find_ent_by_class(-1, "func_bomb_target") <= 0 && rg_find_ent_by_class(-1, "info_bomb_target") <= 0) {
pause("ad");
return;
}
RegisterHooks();
LoadConfig();
g_iMsgId[MSG_SHOW_TIMER] = get_user_msgid("ShowTimer");
g_iMsgId[MSG_ROUND_TIME] = get_user_msgid("RoundTime");
}
RegisterHooks() {
RegisterHookChain(RG_PlantBomb, "@PlantBomb_Post", .post = true);
RegisterHookChain(RG_RoundEnd, "@RoundEnd_Post", .post = true);
RegisterHookChain(RG_CSGameRules_RestartRound, "@RestartRound_Post", .post = true);
RegisterHookChain(RG_CGrenade_DefuseBombEnd, "@DefuseBombEnd_Post", .post = true);
}
LoadConfig() {
new szConfigFile[PLATFORM_MAX_PATH];
get_localinfo("amxx_configsdir", szConfigFile, charsmax(szConfigFile));
add(szConfigFile, charsmax(szConfigFile), JSON_CONFIG_FILE);
new JSON:settings = json_parse(szConfigFile, .is_file = true, .with_comments = true);
if (settings == Invalid_JSON || !json_is_object(settings)) {
set_fail_state("[C4 Timer] Failed to load configuration file: %s", szConfigFile);
}
g_bDhudEnabled = bool:json_object_get_bool(settings, "c4_timer_settings.dhud_enabled", .dot_not = true);
json_object_get_string(settings, "c4_timer_settings.dhud_message", g_szDhudMessage, charsmax(g_szDhudMessage), .dot_not = true);
new JSON:jsonDhudSettings = json_object_get_value(settings, "c4_timer_settings.dhud_settings", .dot_not = true);
if (jsonDhudSettings != Invalid_JSON && json_is_array(jsonDhudSettings)) {
for (new i = 0; i < DhudSettingsStruct; i++) {
g_fDhudSettings[i] = _:json_array_get_real(jsonDhudSettings, i);
}
}
json_free(settings);
server_print("[C4 Timer] Configuration loaded successfully.");
}
@RestartRound_Post() {
ResetBombState();
}
@RoundEnd_Post() {
ResetBombState();
}
@PlantBomb_Post() {
g_iC4Entity = GetHookChainReturn(ATYPE_INTEGER);
if (!is_entity(g_iC4Entity)) {
return;
}
g_flExplodeTime = get_member(g_iC4Entity, m_Grenade_flC4Blow);
StartC4TimerTask();
}
@DefuseBombEnd_Post(const id) {
ResetBombState();
}
public C4TimerTask() {
if (!is_entity(g_iC4Entity)) {
ResetBombState();
return;
}
new Float:flRemainingTime = g_flExplodeTime - get_gametime();
if (flRemainingTime <= 0.0) {
ResetBombState();
return;
}
if (g_bDhudEnabled) {
DisplayHUDTimer(flRemainingTime);
} else {
DisplayRoundTimer(flRemainingTime);
}
}
StartC4TimerTask() {
remove_task(TASK_ID_C4_TIMER);
set_task(TIMER_UPDATE_INTERVAL, "C4TimerTask", TASK_ID_C4_TIMER, .flags = "b");
}
ResetBombState() {
remove_task(TASK_ID_C4_TIMER);
g_iC4Entity = 0;
}
DisplayHUDTimer(Float:flRemainingTime) {
static szMessage[128];
formatex(szMessage, charsmax(szMessage), g_szDhudMessage, flRemainingTime);
set_dhudmessage(
floatround(g_fDhudSettings[DHUD_RED]),
floatround(g_fDhudSettings[DHUD_GREEN]),
floatround(g_fDhudSettings[DHUD_BLUE]),
g_fDhudSettings[DHUD_X_POS],
g_fDhudSettings[DHUD_Y_POS],
floatround(g_fDhudSettings[DHUD_EFFECT]),
g_fDhudSettings[DHUD_FX_TIME],
g_fDhudSettings[DHUD_HOLD_TIME],
g_fDhudSettings[DHUD_FADE_IN_TIME],
g_fDhudSettings[DHUD_FADE_OUT_TIME]
);
show_dhudmessage(0, szMessage);
}
DisplayRoundTimer(Float:flRemainingTime) {
message_begin(MSG_ALL, g_iMsgId[MSG_SHOW_TIMER]);
message_end();
message_begin(MSG_ALL, g_iMsgId[MSG_ROUND_TIME]);
write_short(floatround(flRemainingTime));
message_end();
}