#include <zombie_escape>
#include <ze_vip>
// Defines - Comment MULTIJUMP or PARACHUTE, so you don't need to run multijump/parachute plugin.
#define VIP_MESSAGES VIP_A
#define SCOREBOARD VIP_A
#define MULTIJUMP VIP_B
#define PARACHUTE VIP_B
#define DAMAGE VIP_C
#define NON_VIP VIP_Z
#if defined PARACHUTE
#include <ze_parachute>
#endif
#if defined MULTIJUMP
#include <ze_multijump>
#endif
// Variables
new g_szPasswordKey[65],
g_szPassword[65],
bool:g_bIsUserVIP[33],
bool:g_bSetVIP[33],
g_iFlags[33],
bool:g_bIsHappyHour,
g_iMaxPlayers
// Const.
static const g_szLocalFile[] = "addons/amxmodx/configs/ze_vips.ini"
new const szCommands[][] =
{
"say /vip",
"say /vips",
"say_team /vip",
"say_team /vips"
}
// Cvars
new g_pCvarVIPScoreboard,
g_pCvarConnectMessage,
g_pCvarAdminContact,
g_pCvarEnableHappyHours,
g_pCvarHappyHours,
g_pCvarHappyHoursFlags,
g_pCvarDamage
#if defined PARACHUTE
new g_pCvarParachute
#endif
#if defined MULTIJUMP
new g_pCvarMultijump
#endif
public plugin_natives()
{
register_native("ze_get_vip_flags", "native_ze_get_vip_flags", 1)
register_native("ze_set_vip_flags", "native_ze_set_vip_flags", 1)
register_native("ze_is_user_vip", "native_ze_is_user_vip", 1)
}
public plugin_init()
{
register_plugin("[ZE] Zombie Escape VIP", VIP_VERSION, AUTHORS)
// Hookchain
RegisterHookChain(RG_CBasePlayer_TakeDamage, "Fw_TakeDamage_Pre", 0)
// Cvars
g_pCvarConnectMessage = register_cvar("ze_connect_message", "1")
g_pCvarAdminContact = register_cvar("ze_admin_contact", "Admin Name")
g_pCvarVIPScoreboard = register_cvar("ze_show_vip_scoreboard", "1")
g_pCvarEnableHappyHours = register_cvar("ze_enable_happy_hours", "1")
g_pCvarHappyHours = register_cvar("ze_vip_happy_hours", "9-12")
g_pCvarHappyHoursFlags = register_cvar("ze_happy_hours_vip_flags", "abcd")
g_pCvarDamage = register_cvar("ze_vip_multiply_damage", "1.2")
#if defined MULTIJUMP
g_pCvarMultijump = register_cvar("ze_give_vip_multijump", "1")
#endif
#if defined PARACHUTE
g_pCvarParachute = register_cvar("ze_give_vip_parachute", "1")
#endif
register_cvar("ze_vip_version", VIP_VERSION, FCVAR_SERVER|FCVAR_SPONLY)
set_cvar_string("ze_vip_version", VIP_VERSION)
// Commands
for (new i = 0; i < charsmax(szCommands); i++)
register_clcmd(szCommands[i], "CmdVIP")
register_clcmd("say /getvip", "CmdMotd")
register_clcmd("say_team /getvip", "CmdMotd")
// Get Password Key
get_cvar_string("amx_password_field", g_szPasswordKey, charsmax(g_szPasswordKey))
// Initialize Arrays
arrayset(g_bIsUserVIP, false, 32)
arrayset(g_bSetVIP, false, 32)
// Get max players
g_iMaxPlayers = get_member_game(m_nMaxPlayers)
}
public plugin_cfg()
{
// Get our configiration file and Execute it
new szCfgDir[64]
get_localinfo("amxx_configsdir", szCfgDir, charsmax(szCfgDir))
server_cmd("exec %s/ze_vip.cfg", szCfgDir)
}
public Fw_TakeDamage_Pre(iVictim, iInflictor, iAttacker, Float:flDamage, bitsDamageType)
{
if (!is_user_alive(iVictim) || !is_user_alive(iAttacker))
return HC_CONTINUE
if (!(ze_get_vip_flags(iAttacker) & DAMAGE) || get_pcvar_num(g_pCvarDamage) == 0)
return HC_CONTINUE
SetHookChainArg(4, ATYPE_FLOAT, flDamage * get_pcvar_float(g_pCvarDamage))
return HC_CONTINUE
}
public client_putinserver(id)
{
if (ze_get_vip_flags(id) & VIP_MESSAGES)
{
if (get_pcvar_num(g_pCvarConnectMessage) != 0)
{
new szName[32]
get_user_name(id, szName, charsmax(szName))
ze_colored_print(0, "!tVIP !g%s !thas connected to the server!y.", szName)
}
}
}
public CmdMotd(id)
{
show_motd(id, "ze_vip.txt", "Zombie Escape VIP")
}
public CmdVIP(id)
{
set_task(0.1, "Print_List")
}
public Print_List()
{
Print_VIP_List()
}
public Print_VIP_List()
{
new szVIPName[33][32], szMessage[700], szContact[256]
new iPlayer, i, iVIPCount = 0, iLen = 0;
for (iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++)
{
if (!is_user_connected(iPlayer))
continue
if (ze_get_vip_flags(iPlayer) & VIP_MESSAGES)
{
get_user_name(iPlayer, szVIPName[iVIPCount], charsmax(szVIPName))
iVIPCount++
}
}
iLen = formatex(szMessage, charsmax(szMessage), "^4VIPs ONLINE^1: ")
if (iVIPCount > 0)
{
for (i = 0; i <= iVIPCount; i++)
{
iLen += formatex(szMessage[iLen], charsmax(szMessage) - iLen, "^3%s^1%s^3", szVIPName[i], (i < (iVIPCount - 1)) ? ", " : "")
}
}
else
{
szMessage = "^4No VIPs online^1."
}
client_print_color(0, print_team_default, szMessage)
get_pcvar_string(g_pCvarAdminContact, szContact, charsmax(szContact))
if (szContact[0])
{
client_print_color(0, print_team_default, "^1- ^4Contact Server Admin ^1-- ^3%s", szContact)
}
}
public ze_user_humanized(id)
{
if (!is_user_alive(id))
return
Happy_Hours()
if (g_bIsHappyHour == true && get_pcvar_num(g_pCvarEnableHappyHours) != 0)
{
new szFlags[VIP_MAX_FLAGS]
get_pcvar_string(g_pCvarHappyHoursFlags, szFlags, charsmax(szFlags))
ze_set_vip_flags(id, read_flags(szFlags))
}
#if defined MULTIJUMP
if (ze_get_vip_flags(id) & MULTIJUMP)
{
if (get_pcvar_num(g_pCvarMultijump) != 0)
{
ze_give_user_multijump(id)
}
}
#endif
#if defined PARACHUTE
if (ze_get_vip_flags(id) & PARACHUTE)
{
if (get_pcvar_num(g_pCvarParachute) != 0)
{
ze_give_user_parachute(id)
}
}
#endif
set_task(0.1, "Update_Attribute", id, _, _, "a", 10)
}
public ze_roundend(WinTeam)
{
for (new i = 0; i < get_member_game(m_nMaxPlayers); i++)
{
g_bSetVIP[i] = false
}
}
public Update_Attribute(id)
{
if ((ze_get_vip_flags(id) & SCOREBOARD) && get_pcvar_num(g_pCvarVIPScoreboard) != 0)
{
message_begin(MSG_ALL, get_user_msgid("ScoreAttrib"), {0, 0, 0}, id)
write_byte(id)
write_byte(4)
message_end()
}
}
public native_ze_get_vip_flags(id)
{
// Our file exists?
if (file_exists(g_szLocalFile))
{
/*
* We can't use new file system here, because if file opened it can not be deleted.
* Old system provide the suitable way for doing it simply. That's a reason.
*/
// Declare some useful variables
new iMaxLines, szLineToRead[129], szParse[4][65], szName[32], szSteamID[36], iTextLen
// Get max lines number in the file
iMaxLines = file_size(g_szLocalFile, FSOPT_LINES_COUNT)
// Get our player name and steamid
get_user_authid(id, szSteamID, charsmax(szSteamID))
get_user_name(id, szName, charsmax(szName))
// Loop through the whole file
for (new iLine = 0; iLine < iMaxLines; iLine++)
{
// Read line by line
read_file(g_szLocalFile, iLine, szLineToRead, charsmax(szLineToRead), iTextLen)
// Remove any space, useful to remove blank lines which only contain spaces
trim(szLineToRead)
// Check if string empty or starting with ; or // ignore the line
if (strlen(szLineToRead) == 0 || szLineToRead[0] == ';' || (szLineToRead[0] == '/' && szLineToRead[1] == '/'))
continue
// Split our line by spaces to 4 parts: name or steam, password, flags, expire date
parse(szLineToRead, szParse[0], charsmax(szParse[]), szParse[1], charsmax(szParse[]), szParse[2], charsmax(szParse[]), szParse[3], charsmax(szParse[]))
// Remove all "" from our 4 parts
remove_quotes(szParse[0])
remove_quotes(szParse[1])
remove_quotes(szParse[2])
remove_quotes(szParse[3])
// Check expire date for this steam/name (Steam/Name unique to check with)
CheckDate(szParse[3], szParse[0])
// Check if user in file is same who we check
if (equali(szSteamID, szParse[0]) || equali(szName, szParse[0]))
{
// Player exists in the file, this means he is VIP
g_bIsUserVIP[id] = true
copy(g_szPassword, charsmax(g_szPassword), szParse[1])
// Return his flags
return read_flags(szParse[2])
}
}
}
else
{
// File not exists, then create it (Here we can use new file system without problems)
new iFileHandler = fopen(g_szLocalFile, "wt")
fputs(iFileHandler, "; Zombie Escape VIP^n^n")
fputs(iFileHandler, ";Flags:^n^n")
fputs(iFileHandler, "; a -- Connect Message and VIP List^n")
fputs(iFileHandler, "; b -- Multi-Jump^n")
fputs(iFileHandler, "; c -- Parachute^n")
fputs(iFileHandler, "; d -- Scoreboard Attrib.^n")
fputs(iFileHandler, "; e -- VIP Damage^n^n")
fputs(iFileHandler, ";Usage Example:^n^n")
fputs(iFileHandler, "; ^"Steam/Nick^" ^"Password^" ^"Flags^" ^"ExpireDate^"")
fclose(iFileHandler)
}
g_bIsUserVIP[id] = false
if (g_bSetVIP[id] == true)
{
return g_iFlags[id]
}
else
{
return NON_VIP
}
}
public native_ze_set_vip_flags(id, Flags)
{
g_bSetVIP[id] = true
g_iFlags[id] = Flags
ze_get_vip_flags(id)
}
public native_ze_is_user_vip(id)
{
if (ze_get_vip_flags(id) & VIP_Z)
return false
return true
}
/*
* Dedicated stock for our plugin, to delete expired lines.
* You should give it the expire date, and key.
* Key should be unique like steam or name, so we can in another stock detect this line and delete it.
*/
stock CheckDate(const szEndDate[], const szKey[])
{
new szCurrentDate[64],
szFormatedEndDate[64],
szCurrentDay[32],
szCurrentMonth[32],
szCurrentYear[32],
szEndDay[32],
szEndMonth[32],
szEndYear[32]
copy(szFormatedEndDate, charsmax(szFormatedEndDate), szEndDate)
get_time("%m-%d-%Y", szCurrentDate, charsmax(szCurrentDate))
for (new ch = 0; ch <= charsmax(szFormatedEndDate); ch++)
{
if (szFormatedEndDate[ch] == '-')
szFormatedEndDate[ch] = ' '
}
for (new ch = 0; ch <= charsmax(szCurrentDate); ch++)
{
if (szCurrentDate[ch] == '-')
szCurrentDate[ch] = ' '
}
parse(szCurrentDate, szCurrentMonth, charsmax(szCurrentMonth), szCurrentDay, charsmax(szCurrentDay), szCurrentYear, charsmax(szCurrentYear))
parse(szFormatedEndDate, szEndMonth, charsmax(szEndMonth), szEndDay, charsmax(szEndDay), szEndYear, charsmax(szEndYear))
if (str_to_num(szFormatedEndDate) == 0)
return
new iCurrentMonth,
iCurrentDay,
iCurrentYear,
iEndDay,
iEndMonth,
iEndYear
iCurrentMonth = str_to_num(szCurrentMonth)
iCurrentDay = str_to_num(szCurrentDay)
iCurrentYear = str_to_num(szCurrentYear)
iEndMonth = str_to_num(szEndMonth)
iEndDay = str_to_num(szEndDay)
iEndYear = str_to_num(szEndYear)
// Just a check, maybe useless
if ((!iCurrentMonth && !iCurrentDay && !iCurrentYear) || (!iEndMonth && !iEndDay && !iEndYear))
return
/*
* Check expire date algorithm idea:
*
* If current year > Expire year -- This means it's already expired so delete this line.
*
* If Same year then check by month:
* If current month > expire month -- Expired delete the line.
*
* If same month then check by day:
* If current day > expire date -- Expired detete the line.
*/
if (iEndYear < iCurrentYear)
{
Delete_Line(g_szLocalFile, szKey)
}
else if (iEndYear == iCurrentYear)
{
if (iEndMonth < iCurrentMonth)
{
Delete_Line(g_szLocalFile, szKey)
}
else if (iEndMonth == iCurrentMonth)
{
if (iEndDay < iCurrentDay)
{
Delete_Line(g_szLocalFile, szKey)
}
}
}
}
/*
* Stock used to delete line in file, based on key.
* Key is steamid or name.
* For some purposes we can't use new file system here.
*/
stock Delete_Line(const szFile[], const szKey[])
{
// Check if file there or not
if (file_exists(szFile))
{
// Get max lines in the file
new iMaxLines = file_size(szFile, FSOPT_LINES_COUNT)
// Some variables
new Array:szFileLines, szLineToRead[400], iTextLen, szParse[4][65]
// Create dynamic array to handle all lines in our file (every line will be in element)
szFileLines = ArrayCreate(400)
// Loop through whole file
for (new iLine = 0; iLine < iMaxLines; iLine++)
{
// Read line by line
read_file(szFile, iLine, szLineToRead, charsmax(szLineToRead), iTextLen)
// Just split our line so we get the steamid or name and compare with key
parse(szLineToRead, szParse[0], charsmax(szParse[]), szParse[1], charsmax(szParse[]), szParse[2], charsmax(szParse[]), szParse[3], charsmax(szParse[]))
// Remove any ""
remove_quotes(szParse[0])
remove_quotes(szParse[1])
remove_quotes(szParse[2])
remove_quotes(szParse[3])
// If steamid or name is same as one we need to delete, then don't copy to our array
if (equal(szParse[0], szKey))
continue
// Push all lines to our array except one we need to delete
ArrayPushString(szFileLines, szLineToRead)
}
// Delete the file
delete_file(szFile)
// Recreate the file and print all data to it
for (new iLine = 0; iLine < ArraySize(szFileLines); iLine++)
{
// Get strings in our array
ArrayGetString(szFileLines, iLine, szLineToRead, charsmax(szLineToRead))
// Write them to our file
write_file(szFile, szLineToRead)
}
// Destroy this array and free it's memory
ArrayDestroy(szFileLines)
}
}
stock Happy_Hours()
{
new szTime[3], szHappyHours[32], szHappyHours_Start[32], szHappyHours_End[32]
get_time("%H", szTime, charsmax(szTime))
get_pcvar_string(g_pCvarHappyHours, szHappyHours, charsmax(szHappyHours))
for (new ch = 0; ch <= charsmax(szHappyHours); ch++)
{
if (szHappyHours[ch] == '-')
szHappyHours[ch] = ' '
}
parse(szHappyHours, szHappyHours_Start, charsmax(szHappyHours_Start), szHappyHours_End, charsmax(szHappyHours_End))
new iTime, iHappyHourStart, iHappyHourEnd
iTime = str_to_num(szTime)
iHappyHourStart = str_to_num(szHappyHours_Start)
iHappyHourEnd = str_to_num(szHappyHours_End)
if(iHappyHourEnd > iTime >= iHappyHourStart)
{
g_bIsHappyHour = true
}
else
{
g_bIsHappyHour = false
}
}