diff --git a/PlayerRankings/content/materials/models/unloze/crown/crown.vmt b/PlayerRankings/content/materials/models/unloze/crown/crown.vmt new file mode 100644 index 00000000..db329fd8 --- /dev/null +++ b/PlayerRankings/content/materials/models/unloze/crown/crown.vmt @@ -0,0 +1,71 @@ +"VertexlitGeneric" +{ + "$baseTexture" "models/unloze/crown/crown" + "$bumpmap" "models/unloze/crown/crown_bump" +// "$normalalphaenvmapmask" 1 +// "$env_map" "env_cubemap" +// "$envmaptint" "[.5 .5 .5]" + "$detail" "models/unloze/crown/crown_detail" + "$detailscale" "5" + "$detailblendfactor" .01 + "$detailblendmode" 6 + "$yellow" "0" + + "$phong" "1" + "$phongexponent" "50" + "$phongboost" "8" + "$lightwarptexture" "models/unloze/crown/crown_lightwarp" + "$phongfresnelranges" "[.25 .5 1]" + //"$basemapalphaphongmask" "1" + + "$blendtintbybasealpha" "1" + "$blendtintcoloroverbase" "0" + + "$colortint_base" "{127 61 61}" + "$colortint_tmp" "[0 0 0]" + + // Rim lighting parameters + "$rimlight" "1" // To enable rim lighting (requires phong) + "$rimlightexponent" "4" // Exponent for phong component of rim lighting + "$rimlightboost" "2" // Boost for ambient cube component of rim lighting + + // Cloaking + "$cloakPassEnabled" "1" + + "Proxies" + { + "invis" + { + } + "AnimatedTexture" + { + "animatedtexturevar" "$detail" + "animatedtextureframenumvar" "$detailframe" + "animatedtextureframerate" 30 + } + "BurnLevel" + { + "resultVar" "$detailblendfactor" + } + "ItemTintColor" + { + "resultVar" "$colortint_tmp" + } + "SelectFirstIfNonZero" + { + "srcVar1" "$colortint_tmp" + "srcVar2" "$colortint_base" + "resultVar" "$color2" + } + "YellowLevel" + { + "resultVar" "$yellow" + } + "Multiply" + { + "srcVar1" "$color2" + "srcVar2" "$yellow" + "resultVar" "$color2" + } + } +} \ No newline at end of file diff --git a/PlayerRankings/content/materials/models/unloze/crown/crown.vtf b/PlayerRankings/content/materials/models/unloze/crown/crown.vtf new file mode 100644 index 00000000..f170a92a Binary files /dev/null and b/PlayerRankings/content/materials/models/unloze/crown/crown.vtf differ diff --git a/PlayerRankings/content/materials/models/unloze/crown/crown_bump.vtf b/PlayerRankings/content/materials/models/unloze/crown/crown_bump.vtf new file mode 100644 index 00000000..08564ec3 Binary files /dev/null and b/PlayerRankings/content/materials/models/unloze/crown/crown_bump.vtf differ diff --git a/PlayerRankings/content/materials/models/unloze/crown/crown_detail.vtf b/PlayerRankings/content/materials/models/unloze/crown/crown_detail.vtf new file mode 100644 index 00000000..261eb872 Binary files /dev/null and b/PlayerRankings/content/materials/models/unloze/crown/crown_detail.vtf differ diff --git a/PlayerRankings/content/materials/models/unloze/crown/crown_lightwarp.vtf b/PlayerRankings/content/materials/models/unloze/crown/crown_lightwarp.vtf new file mode 100644 index 00000000..3d5c0a82 Binary files /dev/null and b/PlayerRankings/content/materials/models/unloze/crown/crown_lightwarp.vtf differ diff --git a/PlayerRankings/content/models/unloze/crown_v2.dx80.vtx b/PlayerRankings/content/models/unloze/crown_v2.dx80.vtx new file mode 100644 index 00000000..196dd766 Binary files /dev/null and b/PlayerRankings/content/models/unloze/crown_v2.dx80.vtx differ diff --git a/PlayerRankings/content/models/unloze/crown_v2.dx90.vtx b/PlayerRankings/content/models/unloze/crown_v2.dx90.vtx new file mode 100644 index 00000000..6ac10550 Binary files /dev/null and b/PlayerRankings/content/models/unloze/crown_v2.dx90.vtx differ diff --git a/PlayerRankings/content/models/unloze/crown_v2.mdl b/PlayerRankings/content/models/unloze/crown_v2.mdl new file mode 100644 index 00000000..ecbb06d1 Binary files /dev/null and b/PlayerRankings/content/models/unloze/crown_v2.mdl differ diff --git a/PlayerRankings/content/models/unloze/crown_v2.phy b/PlayerRankings/content/models/unloze/crown_v2.phy new file mode 100644 index 00000000..7b41f4dc Binary files /dev/null and b/PlayerRankings/content/models/unloze/crown_v2.phy differ diff --git a/PlayerRankings/content/models/unloze/crown_v2.sw.vtx b/PlayerRankings/content/models/unloze/crown_v2.sw.vtx new file mode 100644 index 00000000..3d16d3ac Binary files /dev/null and b/PlayerRankings/content/models/unloze/crown_v2.sw.vtx differ diff --git a/PlayerRankings/content/models/unloze/crown_v2.vvd b/PlayerRankings/content/models/unloze/crown_v2.vvd new file mode 100644 index 00000000..9276bddc Binary files /dev/null and b/PlayerRankings/content/models/unloze/crown_v2.vvd differ diff --git a/PlayerRankings/content/sound/unloze/holy.wav b/PlayerRankings/content/sound/unloze/holy.wav new file mode 100644 index 00000000..d727ea3d Binary files /dev/null and b/PlayerRankings/content/sound/unloze/holy.wav differ diff --git a/PlayerRankings/scripting/PlayerRankings.sp b/PlayerRankings/scripting/PlayerRankings.sp new file mode 100644 index 00000000..58e75b01 --- /dev/null +++ b/PlayerRankings/scripting/PlayerRankings.sp @@ -0,0 +1,861 @@ +#include +#include +#include +#include +#include +#include + +#define SPECMODE_NONE 0 +#define SPECMODE_FIRSTPERSON 4 +#define SPECMODE_THIRDPERSON 5 +#define SPECMODE_FREELOOK 6 + +/* BOOLS */ +bool g_bEngineCSGO; +bool g_bHideCrown[MAXPLAYERS+1]; +bool g_bHideDialog[MAXPLAYERS+1]; +bool g_bProtection[MAXPLAYERS+1]; + +/* COOKIES */ +Handle g_hCookie_HideCrown; +Handle g_hCookie_HideDialog; +Handle g_hCookie_Protection; + +/* CONVARS */ +ConVar g_hCVar_Protection; +ConVar g_hCVar_ProtectionMinimal1; +ConVar g_hCVar_ProtectionMinimal2; +ConVar g_hCVar_ProtectionMinimal3; + +/* INTERGERS */ +int g_iCrownEntity = INVALID_ENT_REFERENCE; +int g_iDialogLevel = 100000; + +int g_iPlayerWinner[3]; +int g_iPlayerDamage[MAXPLAYERS+1]; +int g_iPlayerDamageHits[MAXPLAYERS+1]; +int g_iPlayerDamageFrom1K[MAXPLAYERS + 1]; +int g_iPlayerInfections[MAXPLAYERS+1]; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "Player Rankings", + author = "Neon & zaCade", + description = "Show Top Defenders & Infections after each round", + version = "1.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + CreateNative("PlayerRankings_GetClientDamage", Native_GetClientDamage); + CreateNative("PlayerRankings_GetClientHits", Native_GetClientHits); + + CreateNative("PlayerRankings_GetClientInfections", Native_GetClientInfections); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + LoadTranslations("plugin.topdefenders.phrases"); + + g_bEngineCSGO = view_as(GetEngineVersion() == Engine_CSGO); + + g_hCVar_Protection = CreateConVar("sm_topdefenders_protection", "1", "", FCVAR_NONE, true, 0.0, true, 1.0); + g_hCVar_ProtectionMinimal1 = CreateConVar("sm_topdefenders_minimal_1", "15", "", FCVAR_NONE, true, 1.0, true, 64.0); + g_hCVar_ProtectionMinimal2 = CreateConVar("sm_topdefenders_minimal_2", "30", "", FCVAR_NONE, true, 1.0, true, 64.0); + g_hCVar_ProtectionMinimal3 = CreateConVar("sm_topdefenders_minimal_3", "45", "", FCVAR_NONE, true, 1.0, true, 64.0); + + g_hCookie_HideCrown = RegClientCookie("topdefenders_hidecrown", "", CookieAccess_Private); + g_hCookie_HideDialog = RegClientCookie("topdefenders_hidedialog", "", CookieAccess_Private); + g_hCookie_Protection = RegClientCookie("topdefenders_protection", "", CookieAccess_Private); + + CreateTimer(0.1, UpdateScoreboard, INVALID_HANDLE, TIMER_REPEAT); + CreateTimer(0.1, UpdateDialog, INVALID_HANDLE, TIMER_REPEAT); + + RegConsoleCmd("sm_togglecrown", OnToggleCrown); + RegConsoleCmd("sm_toggledialog", OnToggleDialog); + RegConsoleCmd("sm_toggleimmunity", OnToggleImmunity); + + HookEvent("round_start", OnRoundStart); + HookEvent("round_end", OnRoundEnding); + HookEvent("player_hurt", OnClientHurt); + HookEvent("player_spawn", OnClientSpawn); + HookEvent("player_death", OnClientDeath); + + SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Player Rankings"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action OnToggleCrown(int client, int args) +{ + ToggleCrown(client); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action OnToggleDialog(int client, int args) +{ + ToggleDialog(client); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action OnToggleImmunity(int client, int args) +{ + ToggleImmunity(client); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void ToggleCrown(int client) +{ + g_bHideCrown[client] = !g_bHideCrown[client]; + + SetClientCookie(client, g_hCookie_HideCrown, g_bHideCrown[client] ? "1" : ""); + + CPrintToChat(client, "{cyan}%t {white}%t", "Chat Prefix", g_bHideCrown[client] ? "Crown Disabled" : "Crown Enabled"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void ToggleDialog(int client) +{ + g_bHideDialog[client] = !g_bHideDialog[client]; + + SetClientCookie(client, g_hCookie_HideDialog, g_bHideDialog[client] ? "1" : ""); + + CPrintToChat(client, "{cyan}%t {white}%t", "Chat Prefix", g_bHideDialog[client] ? "Dialog Disabled" : "Dialog Enabled"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void ToggleImmunity(int client) +{ + g_bProtection[client] = !g_bProtection[client]; + + SetClientCookie(client, g_hCookie_Protection, g_bProtection[client] ? "1" : ""); + + CPrintToChat(client, "{cyan}%t {white}%t", "Chat Prefix", g_bProtection[client] ? "Immunity Disabled" : "Immunity Enabled"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void ShowSettingsMenu(int client) +{ + Menu menu = new Menu(MenuHandler_MainMenu); + + menu.SetTitle("%T", "Cookie Menu Title", client); + + AddMenuItemTranslated(menu, "0", "%t: %t", "Crown", g_bHideCrown[client] ? "Disabled" : "Enabled"); + AddMenuItemTranslated(menu, "1", "%t: %t", "Dialog", g_bHideDialog[client] ? "Disabled" : "Enabled"); + AddMenuItemTranslated(menu, "2", "%t: %t", "Immunity", g_bProtection[client] ? "Disabled" : "Enabled"); + + menu.ExitBackButton = true; + + menu.Display(client, MENU_TIME_FOREVER); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen) +{ + switch(action) + { + case(CookieMenuAction_DisplayOption): + { + Format(buffer, maxlen, "%T", "Cookie Menu", client); + } + case(CookieMenuAction_SelectOption): + { + ShowSettingsMenu(client); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int selection) +{ + switch(action) + { + case(MenuAction_Select): + { + switch(selection) + { + case(0): ToggleCrown(client); + case(1): ToggleDialog(client); + case(2): ToggleImmunity(client); + } + + ShowSettingsMenu(client); + } + case(MenuAction_Cancel): + { + ShowCookieMenu(client); + } + case(MenuAction_End): + { + delete menu; + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnMapStart() +{ + PrecacheSound("unloze/holy.wav"); + PrecacheModel("models/unloze/crown_v2.mdl"); + + AddFileToDownloadsTable("sound/unloze/holy.wav"); + AddFileToDownloadsTable("models/unloze/crown_v2.mdl"); + AddFileToDownloadsTable("models/unloze/crown_v2.phy"); + AddFileToDownloadsTable("models/unloze/crown_v2.vvd"); + AddFileToDownloadsTable("models/unloze/crown_v2.sw.vtx"); + AddFileToDownloadsTable("models/unloze/crown_v2.dx80.vtx"); + AddFileToDownloadsTable("models/unloze/crown_v2.dx90.vtx"); + AddFileToDownloadsTable("materials/models/unloze/crown/crown.vmt"); + AddFileToDownloadsTable("materials/models/unloze/crown/crown.vtf"); + AddFileToDownloadsTable("materials/models/unloze/crown/crown_bump.vtf"); + AddFileToDownloadsTable("materials/models/unloze/crown/crown_detail.vtf"); + AddFileToDownloadsTable("materials/models/unloze/crown/crown_lightwarp.vtf"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientCookiesCached(int client) +{ + char sBuffer[4]; + GetClientCookie(client, g_hCookie_HideCrown, sBuffer, sizeof(sBuffer)); + + if (sBuffer[0]) + g_bHideCrown[client] = true; + else + g_bHideCrown[client] = false; + + GetClientCookie(client, g_hCookie_HideDialog, sBuffer, sizeof(sBuffer)); + + if (sBuffer[0]) + g_bHideDialog[client] = true; + else + g_bHideDialog[client] = false; + + GetClientCookie(client, g_hCookie_Protection, sBuffer, sizeof(sBuffer)); + + if (sBuffer[0]) + g_bProtection[client] = true; + else + g_bProtection[client] = false; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDisconnect(int client) +{ + g_iPlayerDamage[client] = 0; + g_iPlayerDamageHits[client] = 0; + g_iPlayerDamageFrom1K[client] = 0; + g_iPlayerInfections[client] = 0; + + g_bHideCrown[client] = false; + g_bHideDialog[client] = false; + g_bProtection[client] = false; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int SortRankingsList(int[] elem1, int[] elem2, const int[][] array, Handle hndl) +{ + if (elem1[1] > elem2[1]) return -1; + if (elem1[1] < elem2[1]) return 1; + + return 0; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action UpdateScoreboard(Handle timer) +{ + int iSortedList[MAXPLAYERS+1][2]; + int iSortedCount; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client)) + continue; + + SetEntProp(client, Prop_Data, "m_iDeaths", 0); + + if (!g_iPlayerDamage[client]) + continue; + + iSortedList[iSortedCount][0] = client; + iSortedList[iSortedCount][1] = g_iPlayerDamage[client]; + iSortedCount++; + } + + SortCustom2D(iSortedList, iSortedCount, SortRankingsList); + + for (int rank = 0; rank < iSortedCount; rank++) + { + SetEntProp(iSortedList[rank][0], Prop_Data, "m_iDeaths", rank + 1); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action UpdateDialog(Handle timer) +{ + if (g_bEngineCSGO || g_iDialogLevel <= 0) + return; + + int iSortedList[MAXPLAYERS+1][2]; + int iSortedCount; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || !g_iPlayerDamage[client]) + continue; + + iSortedList[iSortedCount][0] = client; + iSortedList[iSortedCount][1] = g_iPlayerDamage[client]; + iSortedCount++; + } + + SortCustom2D(iSortedList, iSortedCount, SortRankingsList); + + for (int rank = 0; rank < iSortedCount; rank++) + { + switch(rank) + { + case(0): SendDialog(iSortedList[rank][0], "#%d (D: %d | P: -%d)", g_iDialogLevel, 1, rank + 1, iSortedList[rank][1], iSortedList[rank][1] - iSortedList[rank + 1][1]); + case(1): SendDialog(iSortedList[rank][0], "#%d (D: %d | N: +%d)", g_iDialogLevel, 1, rank + 1, iSortedList[rank][1], iSortedList[rank - 1][1] - iSortedList[rank][1]); + default: SendDialog(iSortedList[rank][0], "#%d (D: %d | N: +%d | F: +%d)", g_iDialogLevel, 1, rank + 1, iSortedList[rank][1], iSortedList[rank - 1][1] - iSortedList[rank][1], iSortedList[0][1] - iSortedList[rank][1]); + } + } + + g_iDialogLevel--; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + g_iDialogLevel = 100000; + + for (int client = 1; client <= MaxClients; client++) + { + g_iPlayerDamage[client] = 0; + g_iPlayerDamageHits[client] = 0; + g_iPlayerDamageFrom1K[client] = 0; + g_iPlayerInfections[client] = 0; + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnRoundEnding(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + g_iPlayerWinner = {-1, -1, -1}; + + int iSortedListDefenders[MAXPLAYERS+1][3]; + int iSortedCountDefenders; + + int iSortedListInfectors[MAXPLAYERS+1][2]; + int iSortedCountInfectors; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client)) + continue; + + if (g_iPlayerDamage[client]) + { + iSortedListDefenders[iSortedCountDefenders][0] = client; + iSortedListDefenders[iSortedCountDefenders][1] = g_iPlayerDamage[client]; + iSortedListDefenders[iSortedCountDefenders][2] = g_iPlayerDamageHits[client]; + iSortedCountDefenders++; + } + + if (g_iPlayerInfections[client]) + { + iSortedListInfectors[iSortedCountInfectors][0] = client; + iSortedListInfectors[iSortedCountInfectors][1] = g_iPlayerInfections[client]; + iSortedCountInfectors++; + } + } + + SortCustom2D(iSortedListDefenders, iSortedCountDefenders, SortRankingsList); + SortCustom2D(iSortedListInfectors, iSortedCountInfectors, SortRankingsList); + + for (int rank = 0; rank < iSortedCountDefenders; rank++) + { + LogMessage("%d. %L - %d damage in %d hits", rank + 1, iSortedListDefenders[rank][0], iSortedListDefenders[rank][1], iSortedListDefenders[rank][2]) + } + + for (int rank = 0; rank < iSortedCountInfectors; rank++) + { + LogMessage("%d. %L - %d infections", rank + 1, iSortedListInfectors[rank][0], iSortedListInfectors[rank][1]) + } + + if (iSortedCountDefenders) + { + char sBuffer[512]; + Format(sBuffer, sizeof(sBuffer), "TOP DEFENDERS:"); + Format(sBuffer, sizeof(sBuffer), "%s\n*************************", sBuffer); + + if (iSortedListDefenders[0][0]) + { + Format(sBuffer, sizeof(sBuffer), "%s\n1. %N - %d damage in %d hits", sBuffer, iSortedListDefenders[0][0], iSortedListDefenders[0][1], iSortedListDefenders[0][2]); + + g_iPlayerWinner[0] = GetSteamAccountID(iSortedListDefenders[0][0]); + + LH_LogPlayerEvent(iSortedListDefenders[0][0], "triggered", "ze_defender_first", true); + } + + if (iSortedListDefenders[1][0]) + { + Format(sBuffer, sizeof(sBuffer), "%s\n2. %N - %d damage in %d hits", sBuffer, iSortedListDefenders[1][0], iSortedListDefenders[1][1], iSortedListDefenders[1][2]); + + g_iPlayerWinner[1] = GetSteamAccountID(iSortedListDefenders[1][0]); + + LH_LogPlayerEvent(iSortedListDefenders[1][0], "triggered", "ze_defender_second", true); + } + + if (iSortedListDefenders[2][0]) + { + Format(sBuffer, sizeof(sBuffer), "%s\n3. %N - %d damage in %d hits", sBuffer, iSortedListDefenders[2][0], iSortedListDefenders[2][1], iSortedListDefenders[2][2]); + + g_iPlayerWinner[2] = GetSteamAccountID(iSortedListDefenders[2][0]); + + LH_LogPlayerEvent(iSortedListDefenders[2][0], "triggered", "ze_defender_third", true); + } + + if (g_bEngineCSGO) + { + int iSplits + char sSplits[16][512]; + + if ((iSplits = ExplodeString(sBuffer, "\n", sSplits, sizeof(sSplits), sizeof(sSplits[]))) != 0) + { + for (int iSplit; iSplit < iSplits; iSplit++) + { + PrintToChatAll(sSplits[iSplit]); + } + } + + PrintToMessageHUD(0, 50, Float:{0.02, 0.45}, {0, 128, 255, 255}, {255, 255, 255, 255}, 0, 0.1, 0.1, 5.0, 0.0, sBuffer); + } + else + { + PrintToMessageHUD(0, 50, Float:{0.02, 0.25}, {0, 128, 255, 255}, {255, 255, 255, 255}, 0, 0.1, 0.1, 5.0, 0.0, sBuffer); + PrintToChatAll(sBuffer); + } + } + + if (iSortedCountInfectors) + { + char sBuffer[512]; + Format(sBuffer, sizeof(sBuffer), "TOP INFECTORS:"); + Format(sBuffer, sizeof(sBuffer), "%s\n*************************", sBuffer); + + if (iSortedListInfectors[0][0]) + { + Format(sBuffer, sizeof(sBuffer), "%s\n1. %N - %d infections", sBuffer, iSortedListInfectors[0][0], iSortedListInfectors[0][1]); + + LH_LogPlayerEvent(iSortedListInfectors[0][0], "triggered", "ze_infector_first", true); + } + + if (iSortedListInfectors[1][0]) + { + Format(sBuffer, sizeof(sBuffer), "%s\n2. %N - %d infections", sBuffer, iSortedListInfectors[1][0], iSortedListInfectors[1][1]); + + LH_LogPlayerEvent(iSortedListInfectors[1][0], "triggered", "ze_infector_second", true); + } + + if (iSortedListInfectors[2][0]) + { + Format(sBuffer, sizeof(sBuffer), "%s\n3. %N - %d infections", sBuffer, iSortedListInfectors[2][0], iSortedListInfectors[2][1]); + + LH_LogPlayerEvent(iSortedListInfectors[2][0], "triggered", "ze_infector_third", true); + } + + if (g_bEngineCSGO) + { + int iSplits + char sSplits[16][512]; + + if ((iSplits = ExplodeString(sBuffer, "\n", sSplits, sizeof(sSplits), sizeof(sSplits[]))) != 0) + { + for (int iSplit; iSplit < iSplits; iSplit++) + { + PrintToChatAll(sSplits[iSplit]); + } + } + + PrintToMessageHUD(0, 55, Float:{0.02, 0.63}, {255, 0, 0, 255}, {255, 255, 255, 255}, 0, 0.1, 0.1, 5.0, 0.0, sBuffer); + } + else + { + PrintToMessageHUD(0, 55, Float:{0.02, 0.43}, {255, 0, 0, 255}, {255, 255, 255, 255}, 0, 0.1, 0.1, 5.0, 0.0, sBuffer); + PrintToChatAll(sBuffer); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + int client = GetClientOfUserId(hEvent.GetInt("attacker")); + int victim = GetClientOfUserId(hEvent.GetInt("userid")); + + if (client < 1 || client > MaxClients || victim < 1 || victim > MaxClients) + return; + + if (client == victim || (IsPlayerAlive(client) && ZR_IsClientZombie(client))) + return; + + int iDamage = hEvent.GetInt("dmg_health"); + + g_iPlayerDamage[client] += iDamage; + g_iPlayerDamageHits[client] += 1; + g_iPlayerDamageFrom1K[client] += iDamage; + + if (g_iPlayerDamageFrom1K[client] >= 2000) + { + g_iPlayerDamageFrom1K[client] -= 2000; + + LH_LogPlayerEvent(client, "triggered", "ze_damage_zombie", true); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientSpawn(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + int client = GetClientOfUserId(hEvent.GetInt("userid")); + + if (g_iPlayerWinner[0] == GetSteamAccountID(client) && !g_bHideCrown[client]) + { + CreateTimer(7.0, OnClientSpawnPost, client, TIMER_FLAG_NO_MAPCHANGE); + KillCrown(); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action OnClientSpawnPost(Handle timer, int client) +{ + if (!IsClientInGame(client) || IsFakeClient(client) || !IsPlayerAlive(client)) + return; + + KillCrown(); + SpawnCrown(client); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDeath(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + int client = GetClientOfUserId(hEvent.GetInt("userid")); + + if (g_iPlayerWinner[0] == GetSteamAccountID(client) && !IsPlayerAlive(client)) + KillCrown(); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +void SpawnCrown(int client) +{ + int iCrownEntity = INVALID_ENT_REFERENCE; + if ((iCrownEntity = CreateEntityByName("prop_dynamic")) == INVALID_ENT_REFERENCE) + return; + + SetEntityModel(iCrownEntity, "models/unloze/crown_v2.mdl"); + + DispatchKeyValue(iCrownEntity, "solid", "0"); + DispatchKeyValue(iCrownEntity, "modelscale", "1.5"); + DispatchKeyValue(iCrownEntity, "disableshadows", "1"); + DispatchKeyValue(iCrownEntity, "disablereceiveshadows", "1"); + DispatchKeyValue(iCrownEntity, "disablebonefollowers", "1"); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + fVector[2] += 80.0; + fAngles[0] = 8.0; + fAngles[2] = 5.5; + + TeleportEntity(iCrownEntity, fVector, fAngles, NULL_VECTOR); + + float fDirection[3]; + fDirection[0] = 0.0; + fDirection[1] = 0.0; + fDirection[2] = 1.0; + + TE_SetupSparks(fVector, fDirection, 1000, 200); + TE_SendToAll(); + + SetVariantString("!activator"); + AcceptEntityInput(iCrownEntity, "SetParent", client); + + g_iCrownEntity = iCrownEntity; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +void KillCrown() +{ + if ((IsValidEntity(g_iCrownEntity) && AcceptEntityInput(g_iCrownEntity, "Kill")) || g_iCrownEntity != INVALID_ENT_REFERENCE) + g_iCrownEntity = INVALID_ENT_REFERENCE; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action ZR_OnClientInfect(&client, &attacker, &bool:motherInfect, &bool:respawnOverride, &bool:respawn) +{ + if (g_hCVar_Protection.BoolValue && motherInfect && !g_bProtection[client]) + { + if ((g_iPlayerWinner[0] == GetSteamAccountID(client) && GetClientCount() >= g_hCVar_ProtectionMinimal1.IntValue) || + (g_iPlayerWinner[1] == GetSteamAccountID(client) && GetClientCount() >= g_hCVar_ProtectionMinimal2.IntValue) || + (g_iPlayerWinner[2] == GetSteamAccountID(client) && GetClientCount() >= g_hCVar_ProtectionMinimal3.IntValue)) + { + PrintToMessageHUD(client, 60, Float:{-1.0, 0.3}, {255, 255, 255, 255}, {255, 255, 255, 255}, 0, 0.1, 0.1, 5.0, 0.0, "You have been protected from being Mother Zombie\nsince you were the Top Defender last round!"); + CPrintToChat(client, "{cyan}%t {white}%s", "Chat Prefix", "You have been protected from being Mother Zombie since you were the Top Defender last round!"); + + EmitSoundToClient(client, "unloze/holy.wav", .volume=1.0); + return Plugin_Handled; + } + } + + return Plugin_Continue; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn) +{ + if (client < 1 || client > MaxClients || attacker < 1 || attacker > MaxClients) + return; + + if (client == attacker || (IsPlayerAlive(attacker) && ZR_IsClientHuman(attacker))) + return; + + g_iPlayerInfections[attacker] += 1; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_GetClientDamage(Handle hPlugin, int numParams) +{ + int client = GetNativeCell(1); + if (client < 1 || client > MaxClients) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d", client); + } + + if (!IsClientInGame(client)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game", client); + } + + return g_iPlayerDamage[client]; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_GetClientHits(Handle hPlugin, int numParams) +{ + int client = GetNativeCell(1); + if (client < 1 || client > MaxClients) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d", client); + } + + if (!IsClientInGame(client)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game", client); + } + + return g_iPlayerDamageHits[client]; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_GetClientInfections(Handle hPlugin, int numParams) +{ + int client = GetNativeCell(1); + if (client < 1 || client > MaxClients) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d", client); + } + + if (!IsClientInGame(client)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game", client); + } + + return g_iPlayerInfections[client]; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +void AddMenuItemTranslated(Menu menu, const char[] info, const char[] display, any ...) +{ + char buffer[128]; + VFormat(buffer, sizeof(buffer), display, 4); + + menu.AddItem(info, buffer); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +void PrintToMessageHUD(int client, int channel, float position[2], int color1[4], int color2[4], int effect, float fadein, float fadeout, float hold, float fx, const char[] text, any ...) +{ + char buffer[512]; + VFormat(buffer, sizeof(buffer), text, 12); + + Handle hMessage = ((client == 0) ? StartMessageAll("HudMsg") : StartMessageOne("HudMsg", client)); + if (hMessage) + { + if (GetUserMessageType() == UM_Protobuf) + { + PbSetInt(hMessage, "channel", channel); + PbSetInt(hMessage, "effect", effect); + + PbSetVector2D(hMessage, "pos", position); + + PbSetColor(hMessage, "clr1", color1); + PbSetColor(hMessage, "clr2", color2); + + PbSetFloat(hMessage, "fade_in_time", fadein); + PbSetFloat(hMessage, "fade_out_time", fadeout); + PbSetFloat(hMessage, "hold_time", hold); + PbSetFloat(hMessage, "fx_time", fx); + + PbSetString(hMessage, "text", buffer); + EndMessage(); + } + else + { + BfWriteByte(hMessage, channel); + + BfWriteFloat(hMessage, position[0]); + BfWriteFloat(hMessage, position[1]); + + BfWriteByte(hMessage, color1[0]); + BfWriteByte(hMessage, color1[1]); + BfWriteByte(hMessage, color1[2]); + BfWriteByte(hMessage, color1[3]); + BfWriteByte(hMessage, color1[0]); + BfWriteByte(hMessage, color2[1]); + BfWriteByte(hMessage, color2[2]); + BfWriteByte(hMessage, color2[3]); + BfWriteByte(hMessage, effect); + + BfWriteFloat(hMessage, 0.1); + BfWriteFloat(hMessage, 0.1); + BfWriteFloat(hMessage, 5.0); + BfWriteFloat(hMessage, 0.0); + + BfWriteString(hMessage, buffer); + EndMessage(); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +void SendDialog(int client, const char[] text, const int level, const int time, any ...) +{ + char buffer[128]; + VFormat(buffer, sizeof(buffer), text, 5); + + KeyValues kv = new KeyValues("dialog", "title", buffer); + kv.SetColor("color", 255, 255, 255, 255); + kv.SetNum("level", level); + kv.SetNum("time", time); + + if (!g_bHideDialog[client]) + { + CreateDialog(client, kv, DialogType_Msg); + } + + for (int spec = 1; spec <= MaxClients; spec++) + { + if (!IsClientInGame(spec) || !IsClientObserver(spec) || g_bHideDialog[spec]) + continue; + + int specMode = GetClientSpectatorMode(spec); + int specTarget = GetClientSpectatorTarget(spec); + + if ((specMode == SPECMODE_FIRSTPERSON || specMode == SPECMODE_THIRDPERSON) && specTarget == client) + { + CreateDialog(spec, kv, DialogType_Msg); + } + } + + delete kv; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +int GetClientSpectatorMode(int client) +{ + return GetEntProp(client, Prop_Send, "m_iObserverMode"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +int GetClientSpectatorTarget(int client) +{ + return GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); +} \ No newline at end of file diff --git a/PlayerRankings/scripting/include/PlayerRankings.inc b/PlayerRankings/scripting/include/PlayerRankings.inc new file mode 100644 index 00000000..2dc64374 --- /dev/null +++ b/PlayerRankings/scripting/include/PlayerRankings.inc @@ -0,0 +1,28 @@ +#if defined _PlayerRankings_OnRoundEnd + #endinput +#endif +#define _PlayerRankings_OnRoundEnd + +/** + * Returns the current damage of a client + * + * @param client Client index. + * @return The current damage of the client. + */ +native int PlayerRankings_GetClientDamage(int client); + +/** + * Returns the current hits of a client + * + * @param client Client index. + * @return The current hits of the client. + */ +native int PlayerRankings_GetClientHits(int client); + +/** + * Returns the current infections of a client + * + * @param client Client index. + * @return The current infections of the client. + */ +native int PlayerRankings_GetClientInfections(int client); \ No newline at end of file diff --git a/PlayerRankings/translations/plugin.playerrankings.phrases.txt b/PlayerRankings/translations/plugin.playerrankings.phrases.txt new file mode 100644 index 00000000..bad41773 --- /dev/null +++ b/PlayerRankings/translations/plugin.playerrankings.phrases.txt @@ -0,0 +1,63 @@ +"Phrases" +{ + "Chat Prefix" + { + "en" "[PlayerRankings]" + } + "Cookie Menu" + { + "en" "Player Rankings" + } + "Cookie Menu Title" + { + "en" "Player Rankings Settings" + } + "Enabled" + { + "en" "Enabled" + } + "Disabled" + { + "en" "Disabled" + } + "Crown" + { + "en" "Crown" + } + "Crown Enabled" + { + "en" "You will now spawn with a crown again." + } + "Crown Disabled" + { + "en" "You will no longer spawn with a crown." + } + "Dialog" + { + "en" "Dialog" + } + "Dialog Enabled" + { + "en" "You will now see the dialog again." + } + "Dialog Disabled" + { + "en" "You will no longer see the dialog." + } + "Immunity" + { + "en" "Immunity" + } + "Immunity Enabled" + { + "en" "You will now be protected from being mother zombie." + } + "Immunity Disabled" + { + "en" "You will no longer be protected from being mother zombie." + } + "protected" + { + "en" "You have been protected from being mother zombie, since you where top defender last round." + } +} \ No newline at end of file