diff --git a/addons/sourcemod/plugins/optional/l4d2_skill_detect.smx b/addons/sourcemod/plugins/optional/l4d2_skill_detect.smx index 0d516d152..53adea22a 100644 Binary files a/addons/sourcemod/plugins/optional/l4d2_skill_detect.smx and b/addons/sourcemod/plugins/optional/l4d2_skill_detect.smx differ diff --git a/addons/sourcemod/plugins/optional/l4d2_stats.smx b/addons/sourcemod/plugins/optional/l4d2_stats.smx index 92207bc0f..a6bf5fc95 100644 Binary files a/addons/sourcemod/plugins/optional/l4d2_stats.smx and b/addons/sourcemod/plugins/optional/l4d2_stats.smx differ diff --git a/addons/sourcemod/scripting/l4d2_skill_detect.sp b/addons/sourcemod/scripting/l4d2_skill_detect.sp index a28d70431..ff4ae6efa 100644 --- a/addons/sourcemod/scripting/l4d2_skill_detect.sp +++ b/addons/sourcemod/scripting/l4d2_skill_detect.sp @@ -61,7 +61,7 @@ #include #include -#define PLUGIN_VERSION "1.1.1" +#define PLUGIN_VERSION "1.1.2" #define SHOTGUN_BLAST_TIME 0.1 #define POUNCE_CHECK_TIME 0.1 @@ -183,39 +183,40 @@ char g_csSIClassName[][] = { char g_sDebugFile[256]; // debug file name bool g_bLateLoad = false; // whether we're loading late (after map has started) -Handle - g_hForwardSkeet = INVALID_HANDLE, - g_hForwardSkeetHurt = INVALID_HANDLE, - g_hForwardSkeetMelee = INVALID_HANDLE, - g_hForwardSkeetMeleeHurt = INVALID_HANDLE, - g_hForwardSkeetSniper = INVALID_HANDLE, - g_hForwardSkeetSniperHurt = INVALID_HANDLE, - g_hForwardSkeetGL = INVALID_HANDLE, - g_hForwardHunterDeadstop = INVALID_HANDLE, - g_hForwardSIShove = INVALID_HANDLE, - g_hForwardBoomerPop = INVALID_HANDLE, - g_hForwardLevel = INVALID_HANDLE, - g_hForwardLevelHurt = INVALID_HANDLE, - g_hForwardCrown = INVALID_HANDLE, - g_hForwardDrawCrown = INVALID_HANDLE, - g_hForwardTongueCut = INVALID_HANDLE, - g_hForwardSmokerSelfClear = INVALID_HANDLE, - g_hForwardRockSkeeted = INVALID_HANDLE, - g_hForwardRockEaten = INVALID_HANDLE, - g_hForwardHunterDP = INVALID_HANDLE, - g_hForwardJockeyDP = INVALID_HANDLE, - g_hForwardDeathCharge = INVALID_HANDLE, - g_hForwardClear = INVALID_HANDLE, - g_hForwardVomitLanded = INVALID_HANDLE, - g_hForwardBHopStreak = INVALID_HANDLE, - g_hForwardAlarmTriggered = INVALID_HANDLE, - - g_hTrieWeapons = INVALID_HANDLE, // weapon check - g_hTrieEntityCreated = INVALID_HANDLE, // getting classname of entity created - g_hTrieAbility = INVALID_HANDLE, // ability check - g_hWitchTrie = INVALID_HANDLE, // witch tracking (Crox) - g_hRockTrie = INVALID_HANDLE, // tank rock tracking - g_hCarTrie = INVALID_HANDLE; // car alarm tracking +GlobalForward + g_hForwardSkeet = null, + g_hForwardSkeetHurt = null, + g_hForwardSkeetMelee = null, + g_hForwardSkeetMeleeHurt = null, + g_hForwardSkeetSniper = null, + g_hForwardSkeetSniperHurt = null, + g_hForwardSkeetGL = null, + g_hForwardHunterDeadstop = null, + g_hForwardSIShove = null, + g_hForwardBoomerPop = null, + g_hForwardLevel = null, + g_hForwardLevelHurt = null, + g_hForwardCrown = null, + g_hForwardDrawCrown = null, + g_hForwardTongueCut = null, + g_hForwardSmokerSelfClear = null, + g_hForwardRockSkeeted = null, + g_hForwardRockEaten = null, + g_hForwardHunterDP = null, + g_hForwardJockeyDP = null, + g_hForwardDeathCharge = null, + g_hForwardClear = null, + g_hForwardVomitLanded = null, + g_hForwardBHopStreak = null, + g_hForwardAlarmTriggered = null; + +StringMap + g_hTrieWeapons = null, // weapon check + g_hTrieEntityCreated = null, // getting classname of entity created + g_hTrieAbility = null, // ability check + g_hWitchTrie = null, // witch tracking (Crox) + g_hRockTrie = null, // tank rock tracking + g_hCarTrie = null; // car alarm tracking // all SI / pinners float @@ -436,31 +437,31 @@ public APLRes { RegPluginLibrary("skill_detect"); - g_hForwardSkeet = CreateGlobalForward("OnSkeet", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardSkeetHurt = CreateGlobalForward("OnSkeetHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); - g_hForwardSkeetMelee = CreateGlobalForward("OnSkeetMelee", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardSkeetMeleeHurt = CreateGlobalForward("OnSkeetMeleeHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); - g_hForwardSkeetSniper = CreateGlobalForward("OnSkeetSniper", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardSkeetSniperHurt = CreateGlobalForward("OnSkeetSniperHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); - g_hForwardSkeetGL = CreateGlobalForward("OnSkeetGL", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardSIShove = CreateGlobalForward("OnSpecialShoved", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); - g_hForwardHunterDeadstop = CreateGlobalForward("OnHunterDeadstop", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardBoomerPop = CreateGlobalForward("OnBoomerPop", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Float); - g_hForwardLevel = CreateGlobalForward("OnChargerLevel", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardLevelHurt = CreateGlobalForward("OnChargerLevelHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); - g_hForwardCrown = CreateGlobalForward("OnWitchCrown", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardDrawCrown = CreateGlobalForward("OnWitchDrawCrown", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); - g_hForwardTongueCut = CreateGlobalForward("OnTongueCut", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardSmokerSelfClear = CreateGlobalForward("OnSmokerSelfClear", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); - g_hForwardRockSkeeted = CreateGlobalForward("OnTankRockSkeeted", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardRockEaten = CreateGlobalForward("OnTankRockEaten", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardHunterDP = CreateGlobalForward("OnHunterHighPounce", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Cell, Param_Cell); - g_hForwardJockeyDP = CreateGlobalForward("OnJockeyHighPounce", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Cell); - g_hForwardDeathCharge = CreateGlobalForward("OnDeathCharge", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Cell); - g_hForwardClear = CreateGlobalForward("OnSpecialClear", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Cell); - g_hForwardVomitLanded = CreateGlobalForward("OnBoomerVomitLanded", ET_Ignore, Param_Cell, Param_Cell); - g_hForwardBHopStreak = CreateGlobalForward("OnBunnyHopStreak", ET_Ignore, Param_Cell, Param_Cell, Param_Float); - g_hForwardAlarmTriggered = CreateGlobalForward("OnCarAlarmTriggered", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + g_hForwardSkeet = new GlobalForward("OnSkeet", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardSkeetHurt = new GlobalForward("OnSkeetHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + g_hForwardSkeetMelee = new GlobalForward("OnSkeetMelee", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardSkeetMeleeHurt = new GlobalForward("OnSkeetMeleeHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + g_hForwardSkeetSniper = new GlobalForward("OnSkeetSniper", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardSkeetSniperHurt = new GlobalForward("OnSkeetSniperHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + g_hForwardSkeetGL = new GlobalForward("OnSkeetGL", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardSIShove = new GlobalForward("OnSpecialShoved", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + g_hForwardHunterDeadstop = new GlobalForward("OnHunterDeadstop", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardBoomerPop = new GlobalForward("OnBoomerPop", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Float); + g_hForwardLevel = new GlobalForward("OnChargerLevel", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardLevelHurt = new GlobalForward("OnChargerLevelHurt", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + g_hForwardCrown = new GlobalForward("OnWitchCrown", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardDrawCrown = new GlobalForward("OnWitchDrawCrown", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + g_hForwardTongueCut = new GlobalForward("OnTongueCut", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardSmokerSelfClear = new GlobalForward("OnSmokerSelfClear", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + g_hForwardRockSkeeted = new GlobalForward("OnTankRockSkeeted", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardRockEaten = new GlobalForward("OnTankRockEaten", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardHunterDP = new GlobalForward("OnHunterHighPounce", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Cell, Param_Cell); + g_hForwardJockeyDP = new GlobalForward("OnJockeyHighPounce", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Cell); + g_hForwardDeathCharge = new GlobalForward("OnDeathCharge", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Cell); + g_hForwardClear = new GlobalForward("OnSpecialClear", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Float, Param_Float, Param_Cell); + g_hForwardVomitLanded = new GlobalForward("OnBoomerVomitLanded", ET_Ignore, Param_Cell, Param_Cell); + g_hForwardBHopStreak = new GlobalForward("OnBunnyHopStreak", ET_Ignore, Param_Cell, Param_Cell, Param_Float); + g_hForwardAlarmTriggered = new GlobalForward("OnCarAlarmTriggered", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); g_bLateLoad = late; return APLRes_Success; @@ -516,7 +517,7 @@ public void OnPluginStart() // cvars: built in g_cvarPounceInterrupt = FindConVar("z_pounce_damage_interrupt"); - HookConVarChange(g_cvarPounceInterrupt, CvarChange_PounceInterrupt); + g_cvarPounceInterrupt.AddChangeHook(CvarChange_PounceInterrupt); g_iPounceInterrupt = g_cvarPounceInterrupt.IntValue; g_cvarChargerHealth = FindConVar("z_charger_health"); @@ -535,28 +536,28 @@ public void OnPluginStart() g_cvarMaxPounceDamage = CreateConVar("z_hunter_max_pounce_bonus_damage", "49", "Not available on this server, added by l4d2_skill_detect.", FCVAR_NONE, true, 0.0, false); // tries - g_hTrieWeapons = CreateTrie(); - SetTrieValue(g_hTrieWeapons, "hunting_rifle", WPTYPE_SNIPER); - SetTrieValue(g_hTrieWeapons, "sniper_military", WPTYPE_SNIPER); - SetTrieValue(g_hTrieWeapons, "sniper_awp", WPTYPE_SNIPER); - SetTrieValue(g_hTrieWeapons, "sniper_scout", WPTYPE_SNIPER); - SetTrieValue(g_hTrieWeapons, "pistol_magnum", WPTYPE_MAGNUM); - SetTrieValue(g_hTrieWeapons, "grenade_launcher_projectile", WPTYPE_GL); - - g_hTrieEntityCreated = CreateTrie(); - SetTrieValue(g_hTrieEntityCreated, "tank_rock", OEC_TANKROCK); - SetTrieValue(g_hTrieEntityCreated, "witch", OEC_WITCH); - SetTrieValue(g_hTrieEntityCreated, "trigger_hurt", OEC_TRIGGER); - SetTrieValue(g_hTrieEntityCreated, "prop_car_alarm", OEC_CARALARM); - SetTrieValue(g_hTrieEntityCreated, "prop_car_glass", OEC_CARGLASS); - - g_hTrieAbility = CreateTrie(); - SetTrieValue(g_hTrieAbility, "ability_lunge", ABL_HUNTERLUNGE); - SetTrieValue(g_hTrieAbility, "ability_throw", ABL_ROCKTHROW); - - g_hWitchTrie = CreateTrie(); - g_hRockTrie = CreateTrie(); - g_hCarTrie = CreateTrie(); + g_hTrieWeapons = new StringMap(); + g_hTrieWeapons.SetValue("hunting_rifle", WPTYPE_SNIPER); + g_hTrieWeapons.SetValue("sniper_military", WPTYPE_SNIPER); + g_hTrieWeapons.SetValue("sniper_awp", WPTYPE_SNIPER); + g_hTrieWeapons.SetValue("sniper_scout", WPTYPE_SNIPER); + g_hTrieWeapons.SetValue("pistol_magnum", WPTYPE_MAGNUM); + g_hTrieWeapons.SetValue("grenade_launcher_projectile", WPTYPE_GL); + + g_hTrieEntityCreated = new StringMap(); + g_hTrieEntityCreated.SetValue("tank_rock", OEC_TANKROCK); + g_hTrieEntityCreated.SetValue("witch", OEC_WITCH); + g_hTrieEntityCreated.SetValue("trigger_hurt", OEC_TRIGGER); + g_hTrieEntityCreated.SetValue("prop_car_alarm", OEC_CARALARM); + g_hTrieEntityCreated.SetValue("prop_car_glass", OEC_CARGLASS); + + g_hTrieAbility = new StringMap(); + g_hTrieAbility.SetValue("ability_lunge", ABL_HUNTERLUNGE); + g_hTrieAbility.SetValue("ability_throw", ABL_ROCKTHROW); + + g_hWitchTrie = new StringMap(); + g_hRockTrie = new StringMap(); + g_hCarTrie = new StringMap(); static char logFile[PLATFORM_MAX_PATH]; Format(logFile, sizeof(logFile), "/logs/l4d2_skill_detect.log"); @@ -610,9 +611,9 @@ void OnHookEvent() HookEvent("triggered_car_alarm", Event_CarAlarmGoesOff, EventHookMode_Post); } -void CvarChange_PounceInterrupt(Handle convar, const char[] oldValue, const char[] newValue) +void CvarChange_PounceInterrupt(ConVar convar, const char[] oldValue, const char[] newValue) { - g_iPounceInterrupt = GetConVarInt(convar); + g_iPounceInterrupt = convar.IntValue; } public void OnClientPostAdminCheck(int client) diff --git a/addons/sourcemod/scripting/l4d2_skill_detect/report.sp b/addons/sourcemod/scripting/l4d2_skill_detect/report.sp index 95553278d..50452e7ef 100644 --- a/addons/sourcemod/scripting/l4d2_skill_detect/report.sp +++ b/addons/sourcemod/scripting/l4d2_skill_detect/report.sp @@ -112,9 +112,22 @@ stock void HandleSkeet(int attacker, int victim, bool bMelee = false, bool bSnip CPrintToChatAll("%t %t", "Tag+", "TeamSkeetedBot"); } else if (IsValidClientInGame(attacker) && IsValidClientInGame(victim) && !IsFakeClient(victim)) - CPrintToChatAll("%t %t", "Tag++", "Skeeted", attacker, (bMelee) ? Melee() : ((bSniper) ? Headshot() : ((bGL) ? Grenade() : "")), victim); + { + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClientInGame(i) && !IsFakeClient(i)) + CPrintToChat(i, "%t %t", "Tag++", "Skeeted", attacker, (bMelee) ? Melee(i) : ((bSniper) ? Headshot(i) : ((bGL) ? Grenade(i) : "")), victim); + } + } + else if (IsValidClientInGame(attacker)) - CPrintToChatAll("%t %t", "Tag+", "SkeetedBot", attacker, (bMelee) ? Melee() : ((bSniper) ? Headshot() : ((bGL) ? Grenade() : ""))); + { + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClientInGame(i) && !IsFakeClient(i)) + CPrintToChat(i, "%t %t", "Tag++", "SkeetedBot", attacker, (bMelee) ? Melee(i) : ((bSniper) ? Headshot(i) : ((bGL) ? Grenade(i) : "")), ""); + } + } } // call forward @@ -155,12 +168,19 @@ stock void HandleNonSkeet(int attacker, int victim, int damage, bool bOverKill = // report? if (g_cvarReport.BoolValue && g_cvarRepHurtSkeet.BoolValue) { - char buffer[64]; - Format(buffer, sizeof(buffer), "%t", "Unchipped"); - if (IsValidClientInGame(victim)) - CPrintToChatAll("%t %t", "Tag+", "HurtSkeet", victim, damage, (bOverKill) ? buffer : ""); - else - CPrintToChatAll("%t %t", "Tag+", "HurtSkeetBot", damage, (bOverKill) ? buffer : ""); + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClientInGame(i) && !IsFakeClient(i)) + { + char buffer[64]; + Format(buffer, sizeof(buffer), "%T", "Unchipped", i); + + if (IsValidClientInGame(victim)) + CPrintToChat(i, "%t %t", "Tag+", "HurtSkeet", victim, damage, (bOverKill) ? buffer : ""); + else + CPrintToChat(i, "%t %t", "Tag+", "HurtSkeetBot", damage, (bOverKill) ? buffer : ""); + } + } } // call forward @@ -255,13 +275,19 @@ void HandleSmokerSelfClear(int attacker, int victim, bool withShove = false) // report? if (g_cvarReport.BoolValue && g_cvarRepSelfClear.BoolValue && (!withShove || g_cvarRepSelfClearShove.BoolValue)) { - char Buffer[64]; - Format(Buffer, sizeof(Buffer), "%t", "Shoving"); + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClientInGame(i) && !IsFakeClient(i)) + { + char Buffer[64]; + Format(Buffer, sizeof(Buffer), "%T", "Shoving", i); - if (IsValidClientInGame(attacker) && IsValidClientInGame(victim) && !IsFakeClient(victim)) - CPrintToChatAll("%t %t", "Tag++", "SelfClearedTongue", attacker, victim, (withShove) ? Buffer : ""); - else if (IsValidClientInGame(attacker)) - CPrintToChatAll("%t %t", "Tag++", "SelfClearedTongueBot", attacker, (withShove) ? Buffer : ""); + if (IsValidClientInGame(attacker) && IsValidClientInGame(victim) && !IsFakeClient(victim)) + CPrintToChat(i, "%t %t", "Tag++", "SelfClearedTongue", attacker, victim, (withShove) ? Buffer : ""); + else if (IsValidClientInGame(attacker)) + CPrintToChat(i, "%t %t", "Tag++", "SelfClearedTongueBot", attacker, (withShove) ? Buffer : ""); + } + } } // call forward @@ -347,13 +373,19 @@ stock void HandleDeathCharge(int attacker, int victim, float height, float dista // report? if (g_cvarReport.BoolValue && g_cvarRepDeathCharge.BoolValue && height >= g_cvarDeathChargeHeight.FloatValue) { - char Buffer[64]; - Format(Buffer, sizeof(Buffer), "%t", "Bowling"); + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClientInGame(i) && !IsFakeClient(i)) + { + char Buffer[64]; + Format(Buffer, sizeof(Buffer), "%T", "Bowling", i); - if (IsValidClientInGame(attacker) && IsValidClientInGame(victim) && !IsFakeClient(attacker)) - CPrintToChatAll("%t %t", "Tag++++", "DeathCharged", attacker, victim, (bCarried) ? "" : Buffer, RoundFloat(height)); - else if (IsValidClientInGame(victim)) - CPrintToChatAll("%t %t", "Tag++++", "DeathChargedBot", victim, (bCarried) ? "" : Buffer, RoundFloat(height)); + if (IsValidClientInGame(attacker) && IsValidClientInGame(victim) && !IsFakeClient(attacker)) + CPrintToChat(i, "%t %t", "Tag++++", "DeathCharged", attacker, victim, (bCarried) ? "" : Buffer, RoundFloat(height)); + else if (IsValidClientInGame(victim)) + CPrintToChat(i, "%t %t", "Tag++++", "DeathChargedBot", victim, (bCarried) ? "" : Buffer, RoundFloat(height)); + } + } } Call_StartForward(g_hForwardDeathCharge); @@ -426,7 +458,7 @@ stock void HandleVomitLanded(int attacker, int boomCount) stock void HandleBHopStreak(int survivor, int streak, float maxVelocity) { if (g_cvarRepBhopStreak.BoolValue && IsValidClientInGame(survivor) && !IsFakeClient(survivor) && streak >= g_cvarBHopMinStreak.IntValue) - CPrintToChat(survivor, "%t %t", "Tag+", "BunnyHop", streak, (streak > 1) ? PluralCount() : "", maxVelocity); + CPrintToChat(survivor, "%t %t", "Tag+", "BunnyHop", streak, (streak > 1) ? PluralCount(survivor) : "", maxVelocity); Call_StartForward(g_hForwardBHopStreak); Call_PushCell(survivor); @@ -487,31 +519,31 @@ stock void HandleCarAlarmTriggered(int survivor, int infected, int reason) Call_Finish(); } -char[] Melee() +char[] Melee(int client) { char sBuffer[32]; - Format(sBuffer, sizeof(sBuffer), "%t", "Melee"); + Format(sBuffer, sizeof(sBuffer), "%T", "Melee", client); return sBuffer; } -char[] Headshot() +char[] Headshot(int client) { char sBuffer[32]; - Format(sBuffer, sizeof(sBuffer), "%t", "HeadShot"); + Format(sBuffer, sizeof(sBuffer), "%T", "HeadShot", client); return sBuffer; } -char[] Grenade() +char[] Grenade(int client) { char sBuffer[32]; - Format(sBuffer, sizeof(sBuffer), "%t", "Grenade"); + Format(sBuffer, sizeof(sBuffer), "%T", "Grenade", client); return sBuffer; } -char[] PluralCount() +char[] PluralCount(int client) { char sBuffer[32]; - Format(sBuffer, sizeof(sBuffer), "%t", "PluralCount"); + Format(sBuffer, sizeof(sBuffer), "%T", "PluralCount", client); return sBuffer; } diff --git a/addons/sourcemod/scripting/l4d2_skill_detect/tracking.sp b/addons/sourcemod/scripting/l4d2_skill_detect/tracking.sp index 01617aa4f..326f4550d 100644 --- a/addons/sourcemod/scripting/l4d2_skill_detect/tracking.sp +++ b/addons/sourcemod/scripting/l4d2_skill_detect/tracking.sp @@ -3,7 +3,7 @@ #endif #define _skill_detect_tracking_included -Action Event_RoundStart(Handle event, const char[] name, bool dontBroadcast) +void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) { g_iRocksBeingThrownCount = 0; @@ -16,33 +16,31 @@ Action Event_RoundStart(Handle event, const char[] name, bool dontBroadcast) g_fVictimLastShove[i][j] = 0.0; } } - return Plugin_Continue; } -Action Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast) +void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) { // clean trie, new cars will be created - ClearTrie(g_hCarTrie); - return Plugin_Continue; + g_hCarTrie.Clear(); } -Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) +void Event_PlayerHurt(Event event, const char[] name, bool dontBroadcast) { - int victim = GetClientOfUserId(GetEventInt(event, "userid")); - int attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int victim = GetClientOfUserId(event.GetInt("userid")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); int zClass; - int damage = GetEventInt(event, "dmg_health"); - int damagetype = GetEventInt(event, "type"); + int damage = event.GetInt("dmg_health"); + int damagetype = event.GetInt("type"); if (IsValidInfected(victim)) { zClass = GetEntProp(victim, Prop_Send, "m_zombieClass"); - int health = GetEventInt(event, "health"); - int hitgroup = GetEventInt(event, "hitgroup"); + int health = event.GetInt("health"); + int hitgroup = event.GetInt("hitgroup"); if (damage < 1) - return Plugin_Continue; + return; switch (zClass) { @@ -52,7 +50,7 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) if (!IsValidSurvivor(attacker)) { g_iHunterLastHealth[victim] = health; - return Plugin_Continue; + return; } // if the damage done is greater than the health we know the hunter to have remaining, reduce the damage done @@ -105,9 +103,9 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) char weaponB[32]; strWeaponType weaponTypeB; - GetEventString(event, "weapon", weaponB, sizeof(weaponB)); + event.GetString("weapon", weaponB, sizeof(weaponB)); - if (GetTrieValue(g_hTrieWeapons, weaponB, weaponTypeB) && weaponTypeB == WPTYPE_GL) + if (g_hTrieWeapons.GetValue(weaponB, weaponTypeB) && weaponTypeB == WPTYPE_GL) { if (g_cvarAllowGLSkeet.BoolValue) HandleSkeet(attacker, victim, false, false, true); @@ -117,9 +115,9 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) // headshot with bullet based weapon (only single shots) -- only snipers char weaponA[32]; strWeaponType weaponTypeA; - GetEventString(event, "weapon", weaponA, sizeof(weaponA)); + event.GetString("weapon", weaponA, sizeof(weaponA)); - if (GetTrieValue(g_hTrieWeapons, weaponA, weaponTypeA) && (weaponTypeA == WPTYPE_SNIPER || weaponTypeA == WPTYPE_MAGNUM)) + if (g_hTrieWeapons.GetValue(weaponA, weaponTypeA) && (weaponTypeA == WPTYPE_SNIPER || weaponTypeA == WPTYPE_MAGNUM)) { if (damage >= g_iPounceInterrupt) { @@ -206,7 +204,7 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) case ZC_SMOKER: { if (!IsValidSurvivor(attacker)) - return Plugin_Continue; + return; g_iSmokerVictimDamage[victim] += damage; } } @@ -227,7 +225,7 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) case ZC_TANK: { char weapon[10]; - GetEventString(event, "weapon", weapon, sizeof(weapon)); + event.GetString("weapon", weapon, sizeof(weapon)); if (StrEqual(weapon, "tank_rock")) { @@ -239,13 +237,13 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) FormatEx(rock_key, sizeof(rock_key), "%x", g_iTankRock[attacker]); int rock_array[3]; rock_array[rckDamage] = -1; - SetTrieArray(g_hRockTrie, rock_key, rock_array, sizeof(rock_array), true); + g_hRockTrie.SetArray(rock_key, rock_array, sizeof(rock_array), true); } if (IsValidSurvivor(victim)) HandleRockEaten(attacker, victim); } - return Plugin_Continue; + return; } } } @@ -262,17 +260,16 @@ Action Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) else if (damagetype & DMG_FALL && damage >= MIN_DC_FALL_DMG) g_iVictimFlags[victim] = g_iVictimFlags[victim] | VICFLG_HURTLOTS; } - - return Plugin_Continue; } -Action Event_PlayerSpawn(Handle event, const char[] name, bool dontBroadcast) +void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); + if (!IsValidInfected(client)) - return Plugin_Continue; - int zClass = GetEntProp(client, Prop_Send, "m_zombieClass"); + return; + int zClass = GetEntProp(client, Prop_Send, "m_zombieClass"); g_fSpawnTime[client] = GetGameTime(); g_fPinTime[client][0] = 0.0; g_fPinTime[client][1] = 0.0; @@ -313,26 +310,24 @@ Action Event_PlayerSpawn(Handle event, const char[] name, bool dontBroadcast) g_iChargerHealth[client] = g_cvarChargerHealth.IntValue; } } - - return Plugin_Continue; } // player about to get incapped -Action Event_IncapStart(Handle event, const char[] name, bool dontBroadcast) +void Event_IncapStart(Event event, const char[] name, bool dontBroadcast) { // test for deathcharges - int client = GetClientOfUserId(GetEventInt(event, "userid")); - // int attacker = GetClientOfUserId( GetEventInt(event, "attacker") ); - int attackent = GetEventInt(event, "attackerentid"); - int dmgtype = GetEventInt(event, "type"); + int client = GetClientOfUserId(event.GetInt("userid")); + // int attacker = GetClientOfUserId( event.GetInt("attacker") ); + int attackent = event.GetInt("attackerentid"); + int dmgtype = event.GetInt("type"); char classname[24]; strOEC classnameOEC; if (IsValidEntity(attackent)) { GetEdictClassname(attackent, classname, sizeof(classname)); - if (GetTrieValue(g_hTrieEntityCreated, classname, classnameOEC)) + if (g_hTrieEntityCreated.GetValue(classname, classnameOEC)) { g_iVictimFlags[client] = g_iVictimFlags[client] | VICFLG_TRIGGER; } @@ -347,8 +342,6 @@ Action Event_IncapStart(Handle event, const char[] name, bool dontBroadcast) if (flow < WEIRD_FLOW_THRESH) g_iVictimFlags[client] = g_iVictimFlags[client] | VICFLG_WEIRDFLOW; - - return Plugin_Continue; } // trace attacks on hunters @@ -389,10 +382,10 @@ Action TraceAttack_Jockey(int victim, int& attacker, int& inflictor, float& dama return Plugin_Continue; } -Action Event_PlayerDeath(Handle hEvent, const char[] name, bool dontBroadcast) +void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) { - int victim = GetClientOfUserId(GetEventInt(hEvent, "userid")); - int attacker = GetClientOfUserId(GetEventInt(hEvent, "attacker")); + int victim = GetClientOfUserId(event.GetInt( "userid")); + int attacker = GetClientOfUserId(event.GetInt( "attacker")); if (IsValidInfected(victim)) { @@ -403,7 +396,7 @@ Action Event_PlayerDeath(Handle hEvent, const char[] name, bool dontBroadcast) case ZC_HUNTER: { if (!IsValidSurvivor(attacker)) - return Plugin_Continue; + return; if (g_iHunterShotDmgTeam[victim] > 0 && g_bHunterKilledPouncing[victim]) { @@ -434,7 +427,7 @@ Action Event_PlayerDeath(Handle hEvent, const char[] name, bool dontBroadcast) case ZC_SMOKER: { if (!IsValidSurvivor(attacker)) - return Plugin_Continue; + return; if (g_bSmokerClearCheck[victim] && g_iSmokerVictim[victim] == attacker && g_iSmokerVictimDamage[victim] >= g_cvarSelfClearThresh.IntValue) HandleSmokerSelfClear(attacker, victim); @@ -468,8 +461,8 @@ Action Event_PlayerDeath(Handle hEvent, const char[] name, bool dontBroadcast) else if (IsValidSurvivor(victim)) { // check for deathcharges - // new atkent = GetEventInt(hEvent, "attackerentid"); - int dmgtype = GetEventInt(hEvent, "type"); + // new atkent = event.GetInt( "attackerentid"); + int dmgtype = event.GetInt( "type"); // PrintDebug("Died [%N]: attk: %i / %i - dmgtype: %i", victim, attacker, atkent, dmgtype ); @@ -479,19 +472,17 @@ Action Event_PlayerDeath(Handle hEvent, const char[] name, bool dontBroadcast) // if something other than the charger killed them, remember (not a DC) g_iVictimFlags[victim] = g_iVictimFlags[victim] | VICFLG_KILLEDBYOTHER; } - - return Plugin_Continue; } -Action Event_PlayerShoved(Handle event, const char[] name, bool dontBroadcast) +void Event_PlayerShoved(Event event, const char[] name, bool dontBroadcast) { - int victim = GetClientOfUserId(GetEventInt(event, "userid")); - int attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int victim = GetClientOfUserId(event.GetInt("userid")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); PrintDebug("Shove from %i on %i", attacker, victim); if (!IsValidSurvivor(attacker) || !IsValidInfected(victim)) - return Plugin_Continue; + return; int zClass = GetEntProp(victim, Prop_Send, "m_zombieClass"); PrintDebug(" --> Shove from %N on %N (class: %i) -- (last shove time: %.2f / %.2f)", attacker, victim, zClass, g_fVictimLastShove[victim][attacker], ( GetGameTime() - g_fVictimLastShove[victim][attacker] ) ); @@ -531,13 +522,12 @@ Action Event_PlayerShoved(Handle event, const char[] name, bool dontBroadcast) g_bSmokerShoved[victim] = true; PrintDebug("shove by %i on %i", attacker, victim ); - return Plugin_Continue; } -Action Event_LungePounce(Handle event, const char[] name, bool dontBroadcast) +void Event_LungePounce(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); + int client = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); g_fPinTime[client][0] = GetGameTime(); @@ -550,7 +540,7 @@ Action Event_LungePounce(Handle event, const char[] name, bool dontBroadcast) && g_fPouncePosition[client][1] == 0.0 && g_fPouncePosition[client][2] == 0.0) { - return Plugin_Continue; + return; } float endPos[3]; @@ -578,38 +568,37 @@ Action Event_LungePounce(Handle event, const char[] name, bool dontBroadcast) else if (fDamage > fMaxDmg + 1.0) fDamage = fMaxDmg + 1.0; - Handle pack = CreateDataPack(); - WritePackCell(pack, client); - WritePackCell(pack, victim); - WritePackFloat(pack, fDamage); - WritePackFloat(pack, fHeight); + DataPack pack = new DataPack(); + pack.WriteCell(client); + pack.WriteCell(victim); + pack.WriteFloat(fDamage); + pack.WriteFloat(fHeight); CreateTimer(0.05, Timer_HunterDP, pack); - - return Plugin_Continue; } -Action Timer_HunterDP(Handle timer, Handle pack) +Action Timer_HunterDP(Handle timer, DataPack pack) { - ResetPack(pack); - int client = ReadPackCell(pack); - int victim = ReadPackCell(pack); - float fDamage = ReadPackFloat(pack); - float fHeight = ReadPackFloat(pack); - CloseHandle(pack); + pack.Reset(); + int client = pack.ReadCell(); + int victim = pack.ReadCell(); + float fDamage = pack.ReadFloat(); + float fHeight = pack.ReadFloat(); + delete pack; HandleHunterDP(client, victim, g_iPounceDamage[client], fDamage, fHeight); return Plugin_Continue; } -Action Event_PlayerJumped(Handle event, const char[] name, bool dontBroadcast) +void Event_PlayerJumped(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); if (IsValidInfected(client)) { int zClass = GetEntProp(client, Prop_Send, "m_zombieClass"); if (zClass != ZC_JOCKEY) - return Plugin_Continue; + return; + // where did jockey jump from? GetClientAbsOrigin(client, g_fPouncePosition[client]); } @@ -679,11 +668,9 @@ Action Event_PlayerJumped(Handle event, const char[] name, bool dontBroadcast) CreateTimer(HOP_CHECK_TIME, Timer_CheckHop, client, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); } } - - return Plugin_Continue; } -Action Timer_CheckHop(Handle timer, any client) +Action Timer_CheckHop(Handle timer, int client) { // player back to ground = end of hop (streak)? @@ -701,7 +688,6 @@ Action Timer_CheckHop(Handle timer, any client) // PrintToChatAll("grounded %i: vel length: %.1f", client, GetVectorLength(fVel) ); g_bHopCheck[client] = true; - CreateTimer(HOPEND_CHECK_TIME, Timer_CheckHopStreak, client, TIMER_FLAG_NO_MAPCHANGE); return Plugin_Stop; @@ -710,7 +696,7 @@ Action Timer_CheckHop(Handle timer, any client) return Plugin_Continue; } -Action Timer_CheckHopStreak(Handle timer, any client) +Action Timer_CheckHopStreak(Handle timer, int client) { if (!IsValidClientInGame(client) || !IsPlayerAlive(client)) return Plugin_Continue; @@ -729,9 +715,9 @@ Action Timer_CheckHopStreak(Handle timer, any client) return Plugin_Continue; } -Action Event_PlayerJumpApex(Handle event, const char[] name, bool dontBroadcast) +void Event_PlayerJumpApex(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); if (g_bIsHopping[client]) { @@ -741,26 +727,25 @@ Action Event_PlayerJumpApex(Handle event, const char[] name, bool dontBroadcast) float fLength = GetVectorLength(fVel); if (fLength > g_fHopTopVelocity[client]) - { g_fHopTopVelocity[client] = fLength; - } } - return Plugin_Continue; } -Action Event_JockeyRide(Handle event, const char[] name, bool dontBroadcast) +void Event_JockeyRide(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); + int client = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); if (!IsValidInfected(client) || !IsValidSurvivor(victim)) - return Plugin_Continue; + return; + g_fPinTime[client][0] = GetGameTime(); // minimum distance travelled? // ignore if no real pounce start pos if (g_fPouncePosition[client][0] == 0.0 && g_fPouncePosition[client][1] == 0.0 && g_fPouncePosition[client][2] == 0.0) - return Plugin_Continue; + return; + float endPos[3]; GetClientAbsOrigin(client, endPos); float fHeight = g_fPouncePosition[client][2] - endPos[2]; @@ -769,23 +754,21 @@ Action Event_JockeyRide(Handle event, const char[] name, bool dontBroadcast) // (high) pounce HandleJockeyDP(client, victim, fHeight); - - return Plugin_Continue; } -Action Event_AbilityUse(Handle event, const char[] name, bool dontBroadcast) +void Event_AbilityUse(Event event, const char[] name, bool dontBroadcast) { // track hunters pouncing - int client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); char abilityName[64]; - GetEventString(event, "ability", abilityName, sizeof(abilityName)); + event.GetString("ability", abilityName, sizeof(abilityName)); if (!IsValidClientInGame(client)) - return Plugin_Continue; + return; strAbility ability; - if (!GetTrieValue(g_hTrieAbility, abilityName, ability)) - return Plugin_Continue; + if (!g_hTrieAbility.GetValue(abilityName, ability)) + return; switch (ability) { @@ -805,18 +788,16 @@ Action Event_AbilityUse(Handle event, const char[] name, bool dontBroadcast) if (g_iRocksBeingThrownCount < 9) { g_iRocksBeingThrownCount++; } } } - - return Plugin_Continue; } // charger carrying -Action Event_ChargeCarryStart(Handle event, const char[] name, bool dontBroadcast) +void Event_ChargeCarryStart(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); + int client = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); if (!IsValidInfected(client)) - return Plugin_Continue; + return; PrintDebug("Charge carry start: %i - %i -- time: %.2f", client, victim, GetGameTime()); @@ -825,7 +806,7 @@ Action Event_ChargeCarryStart(Handle event, const char[] name, bool dontBroadcas g_fPinTime[client][1] = 0.0; if (!IsValidSurvivor(victim)) - return Plugin_Continue; + return; g_iChargeVictim[client] = victim; // store who we're carrying (as long as this is set, it's not considered an impact charge flight) g_iVictimCharger[victim] = client; // store who's charging whom @@ -837,16 +818,15 @@ Action Event_ChargeCarryStart(Handle event, const char[] name, bool dontBroadcas // CreateTimer( CHARGE_CHECK_TIME, Timer_ChargeCheck, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE ); CreateTimer(CHARGE_CHECK_TIME, Timer_ChargeCheck, victim, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); - return Plugin_Continue; } -Action Event_ChargeImpact(Handle event, const char[] name, bool dontBroadcast) +void Event_ChargeImpact(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); + int client = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); if (!IsValidInfected(client) || !IsValidSurvivor(victim)) - return Plugin_Continue; + return; // remember how many people the charger bumped into, and who, and where they were GetClientAbsOrigin(victim, g_fChargeVictimPos[victim]); @@ -857,42 +837,39 @@ Action Event_ChargeImpact(Handle event, const char[] name, bool dontBroadcast) g_iVictimMapDmg[victim] = 0; CreateTimer(CHARGE_CHECK_TIME, Timer_ChargeCheck, victim, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); - return Plugin_Continue; } -Action Event_ChargePummelStart(Handle event, const char[] name, bool dontBroadcast) +void Event_ChargePummelStart(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); if (!IsValidInfected(client)) - return Plugin_Continue; + return; g_fPinTime[client][1] = GetGameTime(); - return Plugin_Continue; } -Action Event_ChargeCarryEnd(Handle event, const char[] name, bool dontBroadcast) +void Event_ChargeCarryEnd(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); if (client < 1 || client > MaxClients) - return Plugin_Continue; + return; g_fPinTime[client][1] = GetGameTime(); // delay so we can check whether charger died 'mid carry' CreateTimer(0.1, Timer_ChargeCarryEnd, client, TIMER_FLAG_NO_MAPCHANGE); - return Plugin_Continue; } -Action Timer_ChargeCarryEnd(Handle timer, any client) +Action Timer_ChargeCarryEnd(Handle timer, int client) { // set charge time to 0 to avoid deathcharge timer continuing g_iChargeVictim[client] = 0; // unset this so the repeated timer knows to stop for an ongroundcheck return Plugin_Continue; } -Action Timer_ChargeCheck(Handle timer, any client) +Action Timer_ChargeCheck(Handle timer, int client) { // if something went wrong with the survivor or it was too long ago, forget about it if (!IsValidSurvivor(client) || !g_iVictimCharger[client] || g_fChargeTime[client] == 0.0 || (GetGameTime() - g_fChargeTime[client]) > MAX_CHARGE_TIME) @@ -924,7 +901,7 @@ Action Timer_ChargeCheck(Handle timer, any client) return Plugin_Continue; } -Action Timer_DeathChargeCheck(Handle timer, any client) +Action Timer_DeathChargeCheck(Handle timer, int client) { if (!IsValidClientInGame(client)) return Plugin_Continue; @@ -984,7 +961,7 @@ public void OnEntityCreated(int entity, const char[] classname) // track infected / witches, so damage on them counts as hits strOEC classnameOEC; - if (!GetTrieValue(g_hTrieEntityCreated, classname, classnameOEC)) + if (!g_hTrieEntityCreated.GetValue(classname, classnameOEC)) return; switch (classnameOEC) @@ -1003,7 +980,7 @@ public void OnEntityCreated(int entity, const char[] classname) g_iTankRock[tank] = entity; rock_array[rckTank] = tank; } - SetTrieArray(g_hRockTrie, rock_key, rock_array, sizeof(rock_array), true); + g_hRockTrie.SetArray(rock_key, rock_array, sizeof(rock_array), true); SDKHook(entity, SDKHook_TraceAttack, TraceAttack_Rock); SDKHook(entity, SDKHook_Touch, OnTouch_Rock); @@ -1041,8 +1018,8 @@ void OnEntitySpawned_CarAlarm(int entity) char target[48]; GetEntPropString(entity, Prop_Data, "m_iName", target, sizeof(target)); - SetTrieValue(g_hCarTrie, target, entity); - SetTrieValue(g_hCarTrie, car_key, 0); // who shot the car? + g_hCarTrie.SetValue(target, entity); + g_hCarTrie.SetValue(car_key, 0); // who shot the car? HookSingleEntityOutput(entity, "OnCarAlarmStart", Hook_CarAlarmStart); } @@ -1061,22 +1038,22 @@ void OnEntitySpawned_CarAlarmGlass(int entity) int parentEntity; // find targetname in trie - if (GetTrieValue(g_hCarTrie, parent, parentEntity)) + if (g_hCarTrie.GetValue(parent, parentEntity)) { // if valid entity, save the parent entity if (IsValidEntity(parentEntity)) { - SetTrieValue(g_hCarTrie, car_key, parentEntity); + g_hCarTrie.SetValue(car_key, parentEntity); char car_key_p[10]; FormatEx(car_key_p, sizeof(car_key_p), "%x_A", parentEntity); int testEntity; - if (GetTrieValue(g_hCarTrie, car_key_p, testEntity)) + if (g_hCarTrie.GetValue(car_key_p, testEntity)) // second glass FormatEx(car_key_p, sizeof(car_key_p), "%x_B", parentEntity); - SetTrieValue(g_hCarTrie, car_key_p, entity); + g_hCarTrie.SetValue(car_key_p, entity); } } } @@ -1088,7 +1065,7 @@ public void OnEntityDestroyed(int entity) FormatEx(witch_key, sizeof(witch_key), "%x", entity); int rock_array[3]; - if (GetTrieArray(g_hRockTrie, witch_key, rock_array, sizeof(rock_array))) + if (g_hRockTrie.GetArray(witch_key, rock_array, sizeof(rock_array))) { // tank rock CreateTimer(ROCK_CHECK_TIME, Timer_CheckRockSkeet, entity); @@ -1097,7 +1074,7 @@ public void OnEntityDestroyed(int entity) } int witch_array[MAXPLAYERS + DMGARRAYEXT]; - if (GetTrieArray(g_hWitchTrie, witch_key, witch_array, sizeof(witch_array))) + if (g_hWitchTrie.GetArray(witch_key, witch_array, sizeof(witch_array))) { // witch // delayed deletion, to avoid potential problems with crowns not detecting @@ -1107,24 +1084,24 @@ public void OnEntityDestroyed(int entity) } } -Action Timer_WitchKeyDelete(Handle timer, any witch) +Action Timer_WitchKeyDelete(Handle timer, int witch) { char witch_key[10]; FormatEx(witch_key, sizeof(witch_key), "%x", witch); - RemoveFromTrie(g_hWitchTrie, witch_key); + g_hWitchTrie.Remove(witch_key); return Plugin_Continue; } -Action Timer_CheckRockSkeet(Handle timer, any rock) +Action Timer_CheckRockSkeet(Handle timer, int rock) { int rock_array[3]; char rock_key[10]; FormatEx(rock_key, sizeof(rock_key), "%x", rock); - if (!GetTrieArray(g_hRockTrie, rock_key, rock_array, sizeof(rock_array))) + if (!g_hRockTrie.GetArray(rock_key, rock_array, sizeof(rock_array))) return Plugin_Continue; - RemoveFromTrie(g_hRockTrie, rock_key); + g_hRockTrie.Remove(rock_key); // if rock didn't hit anyone / didn't touch anything, it was shot if (rock_array[rckDamage] > 0) @@ -1134,17 +1111,17 @@ Action Timer_CheckRockSkeet(Handle timer, any rock) } // boomer got somebody -Action Event_PlayerBoomed(Handle event, const char[] name, bool dontBroadcast) +void Event_PlayerBoomed(Event event, const char[] name, bool dontBroadcast) { - int attacker = GetClientOfUserId(GetEventInt(event, "attacker")); - bool byBoom = GetEventBool(event, "by_boomer"); + int attacker = GetClientOfUserId(event.GetInt("attacker")); + bool byBoom = event.GetBool("by_boomer"); if (byBoom && IsValidInfected(attacker)) { g_bBoomerHitSomebody[attacker] = true; // check if it was vomit spray - bool byExplosion = GetEventBool(event, "exploded"); + bool byExplosion = event.GetBool("exploded"); if (!byExplosion) { // count amount of booms @@ -1155,11 +1132,10 @@ Action Event_PlayerBoomed(Handle event, const char[] name, bool dontBroadcast) g_iBoomerVomitHits[attacker]++; } } - return Plugin_Continue; } // check how many booms landed -Action Timer_BoomVomitCheck(Handle timer, any client) +Action Timer_BoomVomitCheck(Handle timer, int client) { HandleVomitLanded(client, g_iBoomerVomitHits[client]); g_iBoomerVomitHits[client] = 0; @@ -1167,64 +1143,61 @@ Action Timer_BoomVomitCheck(Handle timer, any client) } // boomers that didn't bile anyone -Action Event_BoomerExploded(Handle event, const char[] name, bool dontBroadcast) +void Event_BoomerExploded(Event event, const char[] name, bool dontBroadcast) { - int client = GetClientOfUserId(GetEventInt(event, "userid")); - bool biled = GetEventBool(event, "splashedbile"); + int client = GetClientOfUserId(event.GetInt("userid")); + bool biled = event.GetBool("splashedbile"); if (!biled && !g_bBoomerHitSomebody[client]) { - int attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (IsValidSurvivor(attacker)) HandlePop(attacker, client, g_iBoomerGotShoved[client], (GetGameTime() - g_fSpawnTime[client])); } - return Plugin_Continue; } // crown tracking -Action Event_WitchSpawned(Handle event, const char[] name, bool dontBroadcast) +void Event_WitchSpawned(Event event, const char[] name, bool dontBroadcast) { - int witch = GetEventInt(event, "witchid"); + int witch = event.GetInt("witchid"); SDKHook(witch, SDKHook_OnTakeDamagePost, OnTakeDamagePost_Witch); int witch_dmg_array[MAXPLAYERS + DMGARRAYEXT]; char witch_key[10]; + FormatEx(witch_key, sizeof(witch_key), "%x", witch); witch_dmg_array[MAXPLAYERS + WTCH_HEALTH] = g_cvarWitchHealth.IntValue; - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); - return Plugin_Continue; + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); } -Action Event_WitchKilled(Handle event, const char[] name, bool dontBroadcast) +void Event_WitchKilled(Event event, const char[] name, bool dontBroadcast) { - int witch = GetEventInt(event, "witchid"); - int attacker = GetClientOfUserId(GetEventInt(event, "userid")); + int witch = event.GetInt("witchid"); + int attacker = GetClientOfUserId(event.GetInt("userid")); SDKUnhook(witch, SDKHook_OnTakeDamagePost, OnTakeDamagePost_Witch); if (!IsValidSurvivor(attacker)) - return Plugin_Continue; + return; - bool bOneShot = GetEventBool(event, "oneshot"); + bool bOneShot = event.GetBool("oneshot"); // is it a crown / drawcrown? - Handle pack = CreateDataPack(); - WritePackCell(pack, attacker); - WritePackCell(pack, witch); - WritePackCell(pack, (bOneShot) ? 1 : 0); + DataPack pack = new DataPack(); + pack.WriteCell(attacker); + pack.WriteCell(witch); + pack.WriteCell((bOneShot) ? 1 : 0); CreateTimer(WITCH_CHECK_TIME, Timer_CheckWitchCrown, pack); - - return Plugin_Continue; } -Action Event_WitchHarasserSet(Handle event, const char[] name, bool dontBroadcast) +void Event_WitchHarasserSet(Event event, const char[] name, bool dontBroadcast) { - int witch = GetEventInt(event, "witchid"); + int witch = event.GetInt("witchid"); char witch_key[10]; FormatEx(witch_key, sizeof(witch_key), "%x", witch); int witch_dmg_array[MAXPLAYERS + DMGARRAYEXT]; - if (!GetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) + if (!g_hWitchTrie.GetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) { for (int i = 0; i <= MAXPLAYERS; i++) { @@ -1232,14 +1205,13 @@ Action Event_WitchHarasserSet(Handle event, const char[] name, bool dontBroadcas } witch_dmg_array[MAXPLAYERS + WTCH_HEALTH] = g_cvarWitchHealth.IntValue; witch_dmg_array[MAXPLAYERS + WTCH_STARTLED] = 1; // harasser set - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); } else { witch_dmg_array[MAXPLAYERS + WTCH_STARTLED] = 1; // harasser set - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); } - return Plugin_Continue; } Action OnTakeDamageByWitch(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) @@ -1254,7 +1226,7 @@ Action OnTakeDamageByWitch(int victim, int& attacker, int& inflictor, float& dam FormatEx(witch_key, sizeof(witch_key), "%x", attacker); int witch_dmg_array[MAXPLAYERS + DMGARRAYEXT]; - if (!GetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) + if (!g_hWitchTrie.GetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) { for (int i = 0; i <= MAXPLAYERS; i++) { @@ -1262,12 +1234,12 @@ Action OnTakeDamageByWitch(int victim, int& attacker, int& inflictor, float& dam } witch_dmg_array[MAXPLAYERS + WTCH_HEALTH] = g_cvarWitchHealth.IntValue; witch_dmg_array[MAXPLAYERS + WTCH_GOTSLASH] = 1; // failed - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); } else { witch_dmg_array[MAXPLAYERS + WTCH_GOTSLASH] = 1; // failed - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); } } } @@ -1282,14 +1254,14 @@ void OnTakeDamagePost_Witch(int victim, int attacker, int inflictor, float damag FormatEx(witch_key, sizeof(witch_key), "%x", victim); int witch_dmg_array[MAXPLAYERS + DMGARRAYEXT]; - if (!GetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) + if (!g_hWitchTrie.GetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) { for (int i = 0; i <= MAXPLAYERS; i++) { witch_dmg_array[i] = 0; } witch_dmg_array[MAXPLAYERS + WTCH_HEALTH] = g_cvarWitchHealth.IntValue; - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, false); } // store damage done to witch @@ -1311,24 +1283,24 @@ void OnTakeDamagePost_Witch(int victim, int attacker, int inflictor, float damag // continued blast, add up witch_dmg_array[MAXPLAYERS + WTCH_CROWNSHOT] += RoundToFloor(damage); - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); } else { // store all chip from other sources than survivor in [0] witch_dmg_array[0] += RoundToFloor(damage); // witch_dmg_array[MAXPLAYERS+1] -= RoundToFloor(damage); - SetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); + g_hWitchTrie.SetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT, true); } } -Action Timer_CheckWitchCrown(Handle timer, Handle pack) +Action Timer_CheckWitchCrown(Handle timer, DataPack pack) { - ResetPack(pack); - int attacker = ReadPackCell(pack); - int witch = ReadPackCell(pack); - bool bOneShot = view_as(ReadPackCell(pack)); - CloseHandle(pack); + pack.Reset(); + int attacker = pack.ReadCell(); + int witch = pack.ReadCell(); + bool bOneShot = view_as(pack.ReadCell()); + delete pack; CheckWitchCrown(witch, attacker, bOneShot); return Plugin_Continue; @@ -1339,7 +1311,7 @@ void CheckWitchCrown(int witch, int attacker, bool bOneShot = false) char witch_key[10]; FormatEx(witch_key, sizeof(witch_key), "%x", witch); int witch_dmg_array[MAXPLAYERS + DMGARRAYEXT]; - if (!GetTrieArray(g_hWitchTrie, witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) + if (!g_hWitchTrie.GetArray(witch_key, witch_dmg_array, MAXPLAYERS + DMGARRAYEXT)) { PrintDebug("Witch Crown Check: Error: Trie entry missing (entity: %i, oneshot: %i)", witch, bOneShot); return; @@ -1434,11 +1406,12 @@ Action TraceAttack_Rock(int victim, int& attacker, int& inflictor, float& damage */ char rock_key[10]; int rock_array[3]; + FormatEx(rock_key, sizeof(rock_key), "%x", victim); - GetTrieArray(g_hRockTrie, rock_key, rock_array, sizeof(rock_array)); + g_hRockTrie.GetArray(rock_key, rock_array, sizeof(rock_array)); rock_array[rckDamage] += RoundToFloor(damage); rock_array[rckSkeeter] = attacker; - SetTrieArray(g_hRockTrie, rock_key, rock_array, sizeof(rock_array), true); + g_hRockTrie.SetArray(rock_key, rock_array, sizeof(rock_array), true); } return Plugin_Continue; } @@ -1450,21 +1423,22 @@ void OnTouch_Rock(int entity) FormatEx(rock_key, sizeof(rock_key), "%x", entity); int rock_array[3]; rock_array[rckDamage] = -1; - SetTrieArray(g_hRockTrie, rock_key, rock_array, sizeof(rock_array), true); + g_hRockTrie.SetArray(rock_key, rock_array, sizeof(rock_array), true); SDKUnhook(entity, SDKHook_Touch, OnTouch_Rock); } // smoker tongue cutting & self clears -Action Event_TonguePullStopped(Handle event, const char[] name, bool dontBroadcast) +void Event_TonguePullStopped(Event event, const char[] name, bool dontBroadcast) { - int attacker = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); - int smoker = GetClientOfUserId(GetEventInt(event, "smoker")); - int reason = GetEventInt(event, "release_type"); + int attacker = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); + int smoker = GetClientOfUserId(event.GetInt("smoker")); + int reason = event.GetInt("release_type"); if (!IsValidSurvivor(attacker) || !IsValidInfected(smoker)) - return Plugin_Continue; + return; + // clear check - if the smoker itself was not shoved, handle the clear HandleClear(attacker, smoker, victim, ZC_SMOKER, @@ -1473,7 +1447,7 @@ Action Event_TonguePullStopped(Handle event, const char[] name, bool dontBroadca view_as(reason != CUT_SLASH && reason != CUT_KILL)); if (attacker != victim) - return Plugin_Continue; + return; if (reason == CUT_KILL) g_bSmokerClearCheck[smoker] = true; @@ -1489,14 +1463,12 @@ Action Event_TonguePullStopped(Handle event, const char[] name, bool dontBroadca if (StrEqual(weapon, "weapon_melee", false)) HandleTongueCut(attacker, smoker); } - - return Plugin_Continue; } -Action Event_TongueGrab(Handle event, const char[] name, bool dontBroadcast) +void Event_TongueGrab(Event event, const char[] name, bool dontBroadcast) { - int attacker = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); + int attacker = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); if (IsValidInfected(attacker) && IsValidSurvivor(victim)) { @@ -1508,28 +1480,25 @@ Action Event_TongueGrab(Handle event, const char[] name, bool dontBroadcast) g_fPinTime[attacker][0] = GetGameTime(); g_fPinTime[attacker][1] = 0.0; } - - return Plugin_Continue; } -Action Event_ChokeStart(Handle event, const char[] name, bool dontBroadcast) +void Event_ChokeStart(Event event, const char[] name, bool dontBroadcast) { - int attacker = GetClientOfUserId(GetEventInt(event, "userid")); + int attacker = GetClientOfUserId(event.GetInt("userid")); if (g_fPinTime[attacker][0] == 0.0) { g_fPinTime[attacker][0] = GetGameTime(); } g_fPinTime[attacker][1] = GetGameTime(); - return Plugin_Continue; } -Action Event_ChokeStop(Handle event, const char[] name, bool dontBroadcast) +void Event_ChokeStop(Event event, const char[] name, bool dontBroadcast) { - int attacker = GetClientOfUserId(GetEventInt(event, "userid")); - int victim = GetClientOfUserId(GetEventInt(event, "victim")); - int smoker = GetClientOfUserId(GetEventInt(event, "smoker")); - int reason = GetEventInt(event, "release_type"); + int attacker = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); + int smoker = GetClientOfUserId(event.GetInt("smoker")); + int reason = event.GetInt("release_type"); if (!IsValidSurvivor(attacker) || !IsValidInfected(smoker)) - return Plugin_Continue; + return; // if the smoker itself was not shoved, handle the clear HandleClear(attacker, smoker, victim, @@ -1537,7 +1506,6 @@ Action Event_ChokeStop(Handle event, const char[] name, bool dontBroadcast) (g_fPinTime[smoker][1] > 0.0) ? (GetGameTime() - g_fPinTime[smoker][1]) : -1.0, (GetGameTime() - g_fPinTime[smoker][0]), view_as(reason != CUT_SLASH && reason != CUT_KILL)); - return Plugin_Continue; } // car alarm handling @@ -1549,10 +1517,9 @@ void Hook_CarAlarmStart(const char[] output, int caller, int activator, float de PrintDebug("calarm trigger: caller %i / activator %i / delay: %.2f", caller, activator, delay); } -Action Event_CarAlarmGoesOff(Handle event, const char[] name, bool dontBroadcast) +void Event_CarAlarmGoesOff(Event event, const char[] name, bool dontBroadcast) { g_fLastCarAlarm = GetGameTime(); - return Plugin_Continue; } Action OnTakeDamage_Car(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) @@ -1573,7 +1540,7 @@ Action OnTakeDamage_Car(int victim, int& attacker, int& inflictor, float& damage char car_key[10]; FormatEx(car_key, sizeof(car_key), "%x", victim); - SetTrieValue(g_hCarTrie, car_key, attacker); + g_hCarTrie.SetValue(car_key, attacker); if (damagetype & DMG_BLAST) { @@ -1602,7 +1569,7 @@ void OnTouch_Car(int entity, int client) char car_key[10]; FormatEx(car_key, sizeof(car_key), "%x", entity); - SetTrieValue(g_hCarTrie, car_key, client); + g_hCarTrie.SetValue(car_key, client); g_iLastCarAlarmReason[client] = CALARM_TOUCHED; @@ -1619,12 +1586,12 @@ Action OnTakeDamage_CarGlass(int victim, int& attacker, int& inflictor, float& d FormatEx(car_key, sizeof(car_key), "%x", victim); int parentEntity; - if (GetTrieValue(g_hCarTrie, car_key, parentEntity)) + if (g_hCarTrie.GetValue(car_key, parentEntity)) { CreateTimer(0.01, Timer_CheckAlarm, parentEntity, TIMER_FLAG_NO_MAPCHANGE); FormatEx(car_key, sizeof(car_key), "%x", parentEntity); - SetTrieValue(g_hCarTrie, car_key, attacker); + g_hCarTrie.SetValue(car_key, attacker); if (damagetype & DMG_BLAST) { @@ -1653,12 +1620,12 @@ void OnTouch_CarGlass(int entity, int client) FormatEx(car_key, sizeof(car_key), "%x", entity); int parentEntity; - if (GetTrieValue(g_hCarTrie, car_key, parentEntity)) + if (g_hCarTrie.GetValue(car_key, parentEntity)) { CreateTimer(0.01, Timer_CheckAlarm, parentEntity, TIMER_FLAG_NO_MAPCHANGE); FormatEx(car_key, sizeof(car_key), "%x", parentEntity); - SetTrieValue(g_hCarTrie, car_key, client); + g_hCarTrie.SetValue(car_key, client); g_iLastCarAlarmReason[client] = CALARM_TOUCHED; } @@ -1666,7 +1633,7 @@ void OnTouch_CarGlass(int entity, int client) return; } -Action Timer_CheckAlarm(Handle timer, any entity) +Action Timer_CheckAlarm(Handle timer, int entity) { // PrintToChatAll( "checking alarm: time: %.3f", GetGameTime() - g_fLastCarAlarm ); @@ -1679,25 +1646,25 @@ Action Timer_CheckAlarm(Handle timer, any entity) // remove car glass FormatEx(car_key, sizeof(car_key), "%x_A", entity); - if (GetTrieValue(g_hCarTrie, car_key, testEntity)) + if (g_hCarTrie.GetValue(car_key, testEntity)) { - RemoveFromTrie(g_hCarTrie, car_key); + g_hCarTrie.Remove(car_key); SDKUnhook(testEntity, SDKHook_OnTakeDamage, OnTakeDamage_CarGlass); SDKUnhook(testEntity, SDKHook_Touch, OnTouch_CarGlass); } FormatEx(car_key, sizeof(car_key), "%x_B", entity); - if (GetTrieValue(g_hCarTrie, car_key, testEntity)) + if (g_hCarTrie.GetValue(car_key, testEntity)) { - RemoveFromTrie(g_hCarTrie, car_key); + g_hCarTrie.Remove(car_key); SDKUnhook(testEntity, SDKHook_OnTakeDamage, OnTakeDamage_CarGlass); SDKUnhook(testEntity, SDKHook_Touch, OnTouch_CarGlass); } // remove car FormatEx(car_key, sizeof(car_key), "%x", entity); - if (GetTrieValue(g_hCarTrie, car_key, survivor)) + if (g_hCarTrie.GetValue(car_key, survivor)) { - RemoveFromTrie(g_hCarTrie, car_key); + g_hCarTrie.Remove(car_key); SDKUnhook(entity, SDKHook_OnTakeDamage, OnTakeDamage_Car); SDKUnhook(entity, SDKHook_Touch, OnTouch_Car); } diff --git a/addons/sourcemod/scripting/l4d2_stats.sp b/addons/sourcemod/scripting/l4d2_stats.sp index ee4076d60..dd5c3560f 100644 --- a/addons/sourcemod/scripting/l4d2_stats.sp +++ b/addons/sourcemod/scripting/l4d2_stats.sp @@ -423,42 +423,56 @@ void Event_PlayerDeath(Event hEvent, const char[] sEventName, bool bDontBroadcas char buf[MAX_NAME_LENGTH + 8]; int assist_shots = g_iShotsDealt[victim][assisters[0][0]]; - // Construct assisters string - Format(assister_string, sizeof(assister_string), "%N (%d/%d shot%s)", - assisters[0][0], assisters[0][1], g_iShotsDealt[victim][assisters[0][0]], assist_shots == 1 ? "" : "s"); - - for (i = 1; i < assister_count; i++) + for (int x = 0; x < MaxClients; x++) { - assist_shots = g_iShotsDealt[victim][assisters[i][0]]; - Format(buf, sizeof(buf), ", %N (%d/%d shot%s)", assisters[i][0], assisters[i][1], assist_shots, assist_shots == 1 ? "" : "s"); - - StrCat(assister_string, sizeof(assister_string), buf); - } - - /* - // Print to assisters - for (i = 0; i < assister_count; i++) { - CPrintToChat(assisters[i][0], "{green}★ {olive}%N {default}teamskeeted {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ - attacker, victim, damage, shots, plural, assister_string); - } - - // Print to victim - CPrintToChat(victim, "{green}★ {default}You were teamskeeted by {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ + if (x > 0 && IsClientInGame(x) && !IsFakeClient(x)) + { + // Plural problem + char sPlural[8]; + Format(sPlural, sizeof(sPlural), "%T", "Plural", x); + + // details + char sWord[32]; + Format(sWord, sizeof(sWord), "%T", "Shot", x); + + // Construct assisters string + Format(assister_string, sizeof(assister_string), "%N (%d/%d %s%s)", + assisters[0][0], assisters[0][1], g_iShotsDealt[victim][assisters[0][0]], sWord, assist_shots == 1 ? "" : sPlural); + + for (i = 1; i < assister_count; i++) + { + assist_shots = g_iShotsDealt[victim][assisters[i][0]]; + Format(buf, sizeof(buf), ", %N (%d/%d %s%s)", assisters[i][0], assisters[i][1], assist_shots, sWord, assist_shots == 1 ? "" : sPlural); + + StrCat(assister_string, sizeof(assister_string), buf); + } + + /* + // Print to assisters + for (i = 0; i < assister_count; i++) { + CPrintToChat(assisters[i][0], "{green}★ {olive}%N {default}teamskeeted {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ + attacker, victim, damage, shots, plural, assister_string); + } + + // Print to victim + CPrintToChat(victim, "{green}★ {default}You were teamskeeted by {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ attacker, damage, shots, plural, assister_string); - // Finally print to attacker - CPrintToChat(attacker, "{green}★ {default}You teamskeeted {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ - victim, damage, shots, plural, assister_string); + // Finally print to attacker + CPrintToChat(attacker, "{green}★ {default}You teamskeeted {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ + victim, damage, shots, plural, assister_string); - //Print to Specs! - for (int b = 1; b <= MaxClients; b++) { - if (IsClientInGame(b) && GetClientTeam(b) == TEAM_SPECTATOR) { - CPrintToChat(b, "{green}★ {olive}%N {default}teamskeeted {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ - attacker, victim, damage, shots, plural, assister_string); - } - }*/ + //Print to Specs! + for (int b = 1; b <= MaxClients; b++) { + if (IsClientInGame(b) && GetClientTeam(b) == TEAM_SPECTATOR) { + CPrintToChat(b, "{green}★ {olive}%N {default}teamskeeted {olive}%N {default}for {blue}%d damage {default}in {blue}%d shot%c{default}. Assisted by: {olive}%s", \ + attacker, victim, damage, shots, plural, assister_string); + } + }*/ - CPrintToChatAll("%t %t", "Tag+" , "TeamSkeeted", attacker, victim, damage, shots, shots == 1 ? "" : "s", assister_string); + CPrintToChat(x, "%t %t", "Tag+" , "TeamSkeeted", attacker, victim, damage, shots, shots == 1 ? "" : sPlural, assister_string); + } + } } else { /*CPrintToChat(victim, "{green}★ {default}You were skeeted by {olive}%N {default}in {blue}%d shot%c", attacker, shots, plural); @@ -472,7 +486,18 @@ void Event_PlayerDeath(Event hEvent, const char[] sEventName, bool bDontBroadcas } }*/ - CPrintToChatAll("%t %t", "Tag+", "Skeeted", attacker, victim, shots, shots == 1 ? "" : "s"); + for (int x = 1; x < MaxClients; x++) + { + if (IsClientInGame(x) && !IsFakeClient(x)) + { + // Plural problem + char sPlural[8]; + Format(sPlural, sizeof(sPlural), "%T", "Plural", x); + + CPrintToChat(x, "%t %t", "Tag+", "Skeeted", attacker, victim, shots, shots == 1 ? "" : sPlural); + } + } + } } } diff --git a/addons/sourcemod/translations/chi/1v1.phrases.txt b/addons/sourcemod/translations/chi/1v1.phrases.txt new file mode 100644 index 000000000..f708d9f98 --- /dev/null +++ b/addons/sourcemod/translations/chi/1v1.phrases.txt @@ -0,0 +1,20 @@ +"Phrases" +{ + "Tag" + { + "chi" "[{olive}1v1{default}]" + } + "HealthRemaining" + { + "#format" "{1:s},{2:s},{3:d}" // 1:sName 2:L4D2_InfectedNames[iZclass] 3:iRemainingHealth + "chi" "{red}{1}{default} ({green}{2}{default}) 还剩下 {olive}{3}{default} 点血量!" + } + "AI" + { + "chi" "AI" + } + "UMad" + { + "chi" "大可不必急了..." + } +} diff --git a/addons/sourcemod/translations/chi/1v1_skeetstats.phrases.txt b/addons/sourcemod/translations/chi/1v1_skeetstats.phrases.txt new file mode 100644 index 000000000..eef167c43 --- /dev/null +++ b/addons/sourcemod/translations/chi/1v1_skeetstats.phrases.txt @@ -0,0 +1,58 @@ +"Phrases" +{ + "TagKills" + { + "chi" "[{olive}1v1统计{default}] {green}击杀数{default}:" + } + "TagSkeet" + { + "chi" "[{olive}1v1统计{default}] {green}空爆数{default}:" + } + "TagAcc" + { + "chi" "[{olive}1v1统计{default}] {green}准确率{default}:" + } + // 1. SI damage & SI kills + "SI_DMG_CI" + { + "#format" "{1:d},{2:d},{3:d}" // 1:iDidDamageAll[iClientPlaying] 2:iGotKills[iClientPlaying] 3:iGotCommon[iClientPlaying] + "chi" "{olive}{1}{default} 伤害 | {olive}{2}{default} 击杀 | {olive}{3}{default} 小丧尸\n" + } + "SI_DMG" + { + "#format" "{1:d},{2:d}" // 1:iDidDamageAll[iClientPlaying] 2:iGotKills[iClientPlaying] + "chi" "{olive}{1}{default} 伤害 | {olive}{2}{default} 击杀\n" + } + "SI_CI" + { + "#format" "{1:d},{2:d}" // 1:iGotKills[iClientPlaying] 2:iGotCommon[iClientPlaying] + "chi" "{olive}{1}{default} 击杀 | {olive}{2}{default} 小丧尸\n" + } + "SI" + { + "chi" "{olive}%d{default} 击杀\n" + } + // 2. skeets + "SKEET" + { + "#format" "{1:d},{2:d},{3:d}" // 1:iHuntSkeets[iClientPlaying] 2:iHuntSkeetsInj[iClientPlaying] 3:iDeadStops[iClientPlaying] + "chi" "{olive}{1}{default} 正常空爆 | {olive}{2}{default} 受伤击杀 | {olive}{3}{default} 空推\n" + } + // 3. accuracy + "ACC_AllShots" + { + "chi" "射击击中率 ({blue}%.0f%%{default})" + } + "ACC_BuckShot" + { + "chi" " | 铅弹命中率 ({blue}%.0f%%{default})" + } + "ACC_Melee" + { + "chi" " | 近战命中率 ({blue}%.0f%%{default})" + } + "ACC_NoShotsFired" + { + "chi" "没有开火\n" + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/8ball.phrases.txt b/addons/sourcemod/translations/chi/8ball.phrases.txt new file mode 100644 index 000000000..00436d838 --- /dev/null +++ b/addons/sourcemod/translations/chi/8ball.phrases.txt @@ -0,0 +1,39 @@ +"Phrases" +{ + "Tag" + { + "chi" "{default}[{green}8球游戏{default}]" + } + "Usage" + { + "chi" "用法: !8ball <问题>" + } + "Asked" + { + "chi" "{teamcolor}%N{default} 发起问题: {olive}%s{default}" + } + "WithYes" + { + "chi" "我跟一个 {olive}同意{default}!" + } + "WithNo" + { + "chi" "我跟一个 {red}否定{default}!" + } + "Yikes" + { + "chi" "我靠. {red}才不要{default}!" + } + "Sure" + { + "chi" "呃... {olive}还行{default}?" + } + "AbsolutelyNot" + { + "chi" "LOL {red}绝对不可能{default}!" + } + "Yeah" + { + "chi" "你要我说? {olive}肯定可以{default}!" + } +} diff --git a/addons/sourcemod/translations/chi/annoyance_exploit_fixes.phrases.txt b/addons/sourcemod/translations/chi/annoyance_exploit_fixes.phrases.txt new file mode 100644 index 000000000..fd91ccb83 --- /dev/null +++ b/addons/sourcemod/translations/chi/annoyance_exploit_fixes.phrases.txt @@ -0,0 +1,11 @@ +"Phrases" +{ + "Tag" + { + "chi" "[SM]" + } + "TryAgain" + { + "chi" "现在还不能进行投票, 请 %i 秒后再试!" + } +} diff --git a/addons/sourcemod/translations/chi/checkpoint-rage-control.phrases.txt b/addons/sourcemod/translations/chi/checkpoint-rage-control.phrases.txt new file mode 100644 index 000000000..cd7f9887b --- /dev/null +++ b/addons/sourcemod/translations/chi/checkpoint-rage-control.phrases.txt @@ -0,0 +1,15 @@ +"Phrases" +{ + "Tag" + { + "chi" "[{green}!{default}]" + } + "LoseFrustration" + { + "chi" "当生还者都处在{olive}安全屋{default}时, {red}Tank{default}将{green}仍然会{default}失去控制权." + } + "KeepFrustration" + { + "chi" "当生还者都处在{olive}安全屋{default}时, {red}Tank{default}将{green}不会{default}失去控制权." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/current.phrases.txt b/addons/sourcemod/translations/chi/current.phrases.txt new file mode 100644 index 000000000..e7f636ef2 --- /dev/null +++ b/addons/sourcemod/translations/chi/current.phrases.txt @@ -0,0 +1,11 @@ +"Phrases" +{ + "Tag" + { + "chi" "<{olive}当前进度{default}>" + } + "Current" + { + "chi" "{green}%d%%{default}" + } +} diff --git a/addons/sourcemod/translations/chi/l4d2_horde_equaliser.phrases.txt b/addons/sourcemod/translations/chi/l4d2_horde_equaliser.phrases.txt new file mode 100644 index 000000000..ab41953fc --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_horde_equaliser.phrases.txt @@ -0,0 +1,19 @@ +"Phrases" +{ + "Tag" + { + "chi" "<{olive}尸潮事件{default}>" + } + "NoCommonRemaining" + { + "chi" "{red}没有{default}剩余的小丧尸!" + } + "CommonRemaining" + { + "chi" "还剩 {red}%i {default}个小丧尸.." + } + "FiniteEventStarted" + { + "chi" "一个拥有 {olive}%i{default} 个小丧尸的 {blue}有限的尸潮事件{default} 已经开始! 推进或防守, 决定权在你们!" + } +} diff --git a/addons/sourcemod/translations/chi/l4d2_skill_detect.phrases.txt b/addons/sourcemod/translations/chi/l4d2_skill_detect.phrases.txt new file mode 100644 index 000000000..2cba367aa --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_skill_detect.phrases.txt @@ -0,0 +1,285 @@ +"Phrases" +{ + "Tag+" + { + "chi" "{green}★{default}" + } + "Tag++" + { + "chi" "{green}★★{default}" + } + "Tag+++" + { + "chi" "{green}★★★{default}" + } + "Tag++++" + { + "chi" "{green}★★★★{default}" + } + // boomer pop + "Popped" + { + "#format" "{1:N},{2:N}" // 1:attacker 2:victim + "chi" "{olive}{1}{default} 打爆了 {olive}{2}{default}." + } + "PoppedBot" + { + "chi" "{olive}%N{default} 打爆了一个 boomer." + } + // charger level + "Leveled" + { + "#format" "{1:N},{2:N}" // 1:attacker, 2:victim + "chi" "{olive}{1}{default} {blue}一刀{default} 击倒了 {olive}{2}{default}" + } + "LeveledBot" + { + "chi" "{olive}%N{default} {blue}一刀{default} 击倒了一个{olive} charger{default}" + } + // charger level hurt + "LeveledHurt" + { + "#format" "{1:N},{2:N},{3:i}" // 1:attacker 2:victim 3:damage + "chi" "{olive}{1}{default} {blue}一刀{default} 击倒了残血的{olive}{2}{default} ({blue}{3} 伤害{default})" + } + "LeveledHurtBot" + { + "#format" "{1:N},{2:i}" // 1:attacker 2:damage + "chi" "{olive}{1}{default} {blue}一刀{default} 击倒了一个残血的charger ({blue}{2} 伤害{default})" + } + // deadstops + "Deadstopped" + { + "#format" "{1:N},{2:N}" // 1:attacker 2:victim + "chi" "{olive}{1}{default} {blue}空推了{default} {olive}{2}{default}" + } + "DeadstoppedBot" + { + "chi" "{olive}%N{default} {blue}空推了{default} 一个 {olive}hunter{default}" + } + // shove + "Shoved" + { + "#format" "{1:N},{2:N}" // 1:attacker 2:victim + "chi" "{olive}{1}{default} {blue}推开了{default} {olive}{2}{default}." + } + "ShovedBot" + { + "chi" "{olive}%N{default} {blue}推开了{default} 一个 {olive}特感{default}." + } + // real skeet + "TeamSkeeted" + { + "chi" "{olive}%N{default} 被 {blue}团队空爆了{default}." + } + "TeamSkeetedBot" + { + "chi" "一个 {olive}hunter{default} 被 {blue}团队空爆了{default}." + } + "Skeeted" + { + "#format" "{1:N},{2:s},{3:N}" // 1:attacker 2:(bMelee) ? "melee-": ((bSniper) ? "headshot-" : ((bGL) ? "grenade-" : "") ) 3:victim + "chi" "{olive}{1}{default} {blue}{2}空爆了{default} {olive}{3}{default}." + } + "SkeetedBot" + { + "#format" "{1:N},{2:s}" // 1:attacker 2:(bMelee) ? "melee-": ((bSniper) ? "headshot-" : ((bGL) ? "grenade-" : "") ) + "chi" "{olive}{1}{default} {blue}{2}空爆了{default} 一个 {olive}hunter{default}." + } + "Melee" + { + "chi" "使用近战" + } + "HeadShot" + { + "chi" "爆头" + } + "Grenade" + { + "chi" "使用榴弹" + } + // hurt skeet / non-skeet + "HurtSkeet" + { + "#format" "{1:N},{2:i},{3:s}" // 1:victim 2:damage 3:(bOverKill) ? buffer : "" + "chi" "{olive}{1}{default} {green}没有被{default} 空爆掉 ({blue}{2}{default} 伤害).{3}" + } + "HurtSkeetBot" + { + "#format" "{1:i},{2:s}" // 1:damage 2:(bOverKill) ? buffer : "" + "chi" "{olive}Hunter{default} {green}没有被{default} 空爆掉 ({blue}{1}{default} 伤害).{2}" + } + "Unchipped" + { + "chi" "(如果先前Hunter没有被击中过, 那么他有可能会被空爆掉!)" + } + // crown + "CrownedWitch" + { + "#format" "{1:N},{2:i}" // 1:attacker 2:damage + "chi" "{olive}{1}{default} 秒杀了一个 witch ({blue}{2}{default} 伤害)." + } + "CrownedWitch2" + { + "chi" "一个 Witch {blue}被秒杀了{default}." + } + // drawcrown + "DrawCrowned" + { + "#format" "{1:N},{2:i},{3:i}" // 1:attacker 2:damage 3:chipdamage + "chi" "{olive}{1}{default} 引秒了一个 witch ({blue}{2}{default} 伤害, {olive}{3}{default} 引诱伤害)." + } + "DrawCrowned2" + { + "#format" "{1:i},{2:i}" // 1:damage 2:chipdamage + "chi" "一个 witch 被引秒了 ({blue}{1}{default} 伤害, {olive}{2}{default} 引诱伤害)." + } + // smoker clears + "CutTongue" + { + "#format" "{1:N},{2:N}" // 1:attacker 2:victim + "chi" "{olive}{1}{default} {blue}砍断了{default} {olive}{2}{default} 的舌头" + } + "CutTongueBot" + { + "chi" "{olive}%N{default} {blue}砍断了{default} smoker 的舌头" + } + "SelfClearedTongue" + { + "#format" "{1:N},{2:N},{3:s}" // 1:attacker 2:victim 3:(withShove) ? Buffer : "" + "chi" "{olive}{1}{default} 成功地从 {olive}{2}{default} 的舌头中{blue}{3}自救了{default}" + } + "SelfClearedTongueBot" + { + "#format" "{1:N},{2:s}" // 1:attacker 2:(withShove) ? Buffer : "" + "chi" "{olive}{1}{default} 成功地从 smoker 的舌头中{blue}{3}自救了{default}" + } + "Shoving" + { + "chi" "使用推开" + } + // rocks + "SkeetedRock" + { + "#format" "{1:N},{2:N}" // 1:attacker 2:victim + "chi" "{olive}{1}{default} {blue}空爆了{default} {olive}{2}{default} 的石头." + } + "SkeetedRockBot" + { + "chi" "{olive}%N{default} {blue}空爆了{default} 一块tank的石头" + } + // highpounces + "HunterHP" + { + "#format" "{1:N},{2:N},{3:i},{4:i}" // 1:attacker 2:victim 3:RoundFloat(calculatedDamage) 4:RoundFloat(height) + "chi" "{olive}{1}{default} {red}高扑了{default} {olive}{2}{default} ({red}{3}{default} 伤害, 高度: {red}{4}{default})" + } + "HunterHPBot" + { + "#format" "{1:N},{2:i},{3:i}" // 1:victim 2:RoundFloat(calculatedDamage) 3:RoundFloat(height) + "chi" "一个 {olive}hunter{default} {red}高扑了{default} {olive}{1}{default} ({red}{2}{default} 伤害, 高度: {red}{3}{default})" + } + "JockeyHP" + { + "#format" "{1:N},{2:N},{3:i}" // 1:attacker 2:victim 3:RoundFloat(height) + "chi" "{olive}{1}{default} {red}高扑了{default} {olive}{2}{default} ({red}高度{default}: {red}{3}{default})" + } + "JockeyHPBot" + { + "#format" "{1:N},{2:i}" // 1:victim 2:RoundFloat(height) + "chi" "一个 {olive}jockey{default} {red}高扑了{default} {olive}{1}{default} ({red}高度{default}: {red}{2}{default})" + } + // deathcharges + "DeathCharged" + { + "#format" "{1:N},{2:N},{3:s},{4:i}" // 1:attacker 2:victim 3:(bCarried) ? "" : Buffer 4:RoundFloat(height) + "chi" "{olive}{1}{default} {red}冲锋秒杀了{default} {3}{olive}{2}{default} ({red}高度{default}: {red}{4}{default})" + } + "DeathChargedBot" + { + "#format" "{1:N},{2:s},{3:i}" // 1:victim 2:(bCarried) ? "" : Buffer 3:RoundFloat(height) + "chi" "一个 {olive}charger{default} {red}冲锋秒杀了{default} {2}{olive}{1}{default} ({red}高度{default}: {red}{3}{default})" + } + "Bowling" + { + "chi" "被撞飞的" + } + // SI clears (cleartimeA = pummel/pounce/ride/choke, cleartimeB = tongue drag, charger carry) + "SIClear" + { + "#format" "{1:N},{2:N},{3:N},{4:s},{5:.2f}" // 1:attacker 2:pinVictim 3:victim 4:g_csSIClassName[zombieClass] 5:fClearTime + "chi" "{olive}{1}{default} 从 {olive}{3}{default}的 {4} 里 {blue}速救了{default} {olive}{2}{default} ({blue}{5} {default}秒)" + } + "SIClearTeammate" + { + "#format" "{1:N},{2:N},{3:s},{4:.2f}" // 1:attacker 2:victim 3:g_csSIClassName[zombieClass] 4:fClearTime + "chi" "{olive}{1}{default} 从 {olive}{2}{default}的 {3} 里 {blue}速救了{default}{olive}一名队友{default} ({blue}{4} {default}秒)" + } + "SIClearBot" + { + "#format" "{1:N},{2:N},{3:s},{4:.2f}" // 1:attacker 2:pinVictim 3:g_csSIClassName[zombieClass] 4:fClearTime + "chi" "{olive}{1}{default} 从一个 {3} 里 {blue}速救了{default} {olive}{2}{default} ({blue}{4} {default}秒)" + } + "SIClearTeammateBot" + { + "#format" "{1:N},{2:s},{3:.2f}" // 1:attacker 2:g_csSIClassName[zombieClass] 3:fClearTime) + "chi" "{olive}{1}{default} 从一个 {2} 里 {blue}速救了{default} {olive}一名队友{default} ({blue}{3} {default}秒)" + } + // bhaps + "BunnyHop" + { + "#format" "{1:i},{2:s},{3:.1f}" // 1:streak 2:(streak > 1) ? "s" : "" 3:maxVelocity + "chi" "{olive}你{default}一次性连跳了{2}{blue}{1}{default} 下 ({blue}最高速度{default}: {olive}{3}{default})" + } + "PluralCount" + { + "chi" " " // no 's' in chinese! + } + // car alarms + "CalarmHit" + { + "chi" "{olive}%N{default} 击打了警报车." + } + "CalarmTouched" + { + "#format" "{1:N},{2:N}" // 1:infected 2:survivor + "chi" "{olive}{1}{default} 使 {olive}{2}{default} 触发了警报车." + } + "CalarmTouchedHunter" + { + "chi" "一个 {olive}hunter{default} 使 {olive}%N{default} 触发了警报车." + } + "CalarmTouchedJockey" + { + "chi" "一个 {olive}jockey{default} 使 {olive}%N{default} 触发了警报车." + } + "CalarmTouchedCharger" + { + "chi" "一个 {olive}charger{default} 使 {olive}%N{default} 触发了警报车." + } + "CalarmTouchedInfected" + { + "chi" "一个 {olive}bot感染者{default} 使 {olive}%N{default} 触发了警报车." + } + "CalarmTouchedBot" + { + "chi" "{olive}%N{default} 触碰了警报车." + } + "CalarmExplosion" + { + "chi" "{olive}%N{default} 使用爆炸触发了警报车." + } + "CalarmBoomer" + { + "#format" "{1:N},{2:N}" // 1:survivor 2:infected + "chi" "{olive}{1}{default} 因击杀了 boommer {olive}{2}{default} 而触发了警报车." + } + "CalarmBoomerBot" + { + "chi" "{olive}%N{default} 因射杀了 {olive}boomer{default} 而触发了警报车." + } + "Calarm" + { + "chi" "{olive}%N{default} 触发了警报车." + } +} diff --git a/addons/sourcemod/translations/chi/l4d2_stats.phrases.txt b/addons/sourcemod/translations/chi/l4d2_stats.phrases.txt new file mode 100644 index 000000000..c054ffbc6 --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_stats.phrases.txt @@ -0,0 +1,54 @@ +"Phrases" +{ + "Tag+" + { + "chi" "{green}★{default}" + } + "Tag++" + { + "chi" "{green}★★{default}" + } + "Tag+++" + { + "chi" "{green}★★★{default}" + } + "MeleeSkeeted" + { + "#format" "{1:N},{2:N}" // 1:victim 2:attacker + "chi" "{olive}{1}{default} 被 {olive}{2}{default} 使用 {blue}近战{default}空爆{default}" + } + "Headshotted" + { + "#format" "{1:N},{2:N}" // 1:victim 2:attacker + "chi" "{olive}{1}{default} 被 {olive}{2}{default} {blue}爆头击杀{default}" + } + "TeamSkeeted" + { + "#format" "{1:N},{2:N},{3:d},{4:d},{5:s},{6:s}" // 1:attacker 2:victim 3:damage 4:shots 5:shots == 1 ? "" : "s" 6:assister_string + "chi" "{olive}{1}{default} 以 {blue}{4}{default} 发{5}造成了 {blue}{3} 点伤害{default}团队空爆了 {olive}{2}{default}. 协助者: {olive}{6}{default}" + } + "Skeeted" + { + "#format" "{1:N},{2:N},{3:d},{4:s}" // 1:attacker 2:victim 3:shots 4:shots == 1 ? "" : "s" + "chi" "{olive}{1}{default} 以 {blue}{3}{default} 发子弹{4}空爆了 {olive}{2}{default}" + } + "ShutBoomer" + { + "#format" "{1:N},{2:s},{3:.1f}" // 1:g_iBoomerKiller 2:Boomer 3:BoomerKillTime + "chi" "{olive}{1}{default} 在 {blue}{3}{default} 秒内速爆了 {olive}{2}{default} 的Boomer" + } + "AlarmedCar" + { + "chi" "{olive}%N{default} 触发了 {olive}警报车{default}" + } + "Plural" + { + "chi" " " // no plural word in chinese. + } + "Shot" + { + "chi" "发" // based on content. + } +} + + diff --git a/addons/sourcemod/translations/chi/l4d2_tank_announce.phrases.txt b/addons/sourcemod/translations/chi/l4d2_tank_announce.phrases.txt new file mode 100644 index 000000000..1d6f81e6e --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_tank_announce.phrases.txt @@ -0,0 +1,15 @@ +"Phrases" +{ + "Tag" + { + "chi" "{red}[{default}!{red}]" + } + "Spawned" + { + "chi" "{olive}Tank {default}({red}控制人: %s{default}) 已生成!" + } + "Spawned2" + { + "chi" "{olive}Tank {default}({red}控制人: %N{default}) 已生成!" + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/l4d2_tank_attack_control.phrases.txt b/addons/sourcemod/translations/chi/l4d2_tank_attack_control.phrases.txt new file mode 100644 index 000000000..b574a8552 --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_tank_attack_control.phrases.txt @@ -0,0 +1,20 @@ +"Phrases" +{ + "Title" + { + "chi" "{blue}[{default}Tank 扔石选择器{blue}]" + } + // 译者注: R键, E键, 鼠标右键均为习惯性描述. 其实际对应的是客户端自己设定的对应换弹, 使用和鼠标右键的键位. + "Reload" + { + "chi" "{olive}R键{default} = {blue}双手举头石{default}" + } + "Use" + { + "chi" "{olive}E键{default} = {blue}低抛石{default}" + } + "M2" + { + "chi" "{olive}鼠标右键{default} = {blue}一手举头石{default}" + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/l4d2_tank_horde_monitor.phrases.txt b/addons/sourcemod/translations/chi/l4d2_tank_horde_monitor.phrases.txt new file mode 100644 index 000000000..243c51f4b --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_tank_horde_monitor.phrases.txt @@ -0,0 +1,27 @@ +"Phrases" +{ + "Tag" + { + "chi" "<{olive}尸潮事件{default}>" + } + "TankPlay" + { + "chi" "尸潮事件因Tank生成而{blue}暂停{default}! 继续推进 {blue}%0.1f%%{default} 将会重启尸潮." + } + "UntilHordeStarts" + { + "chi" "还剩 {blue}%0.1f%%{default} 重启尸潮..." + } + "HordeResumed" + { + "chi" "尸潮事件已以 {green}%i%% 的强度{default}{blue}重启{default}, 继续推进将提升尸潮强度." + } + "HordeStrength" + { + "chi" "当前尸潮强度为{green} %i%% {default}..." + } + "HordeVeryStrength" + { + "chi" "{red}生还者已经推进得太远{default}, 尸潮强度已达到{green}100%%{default}!" + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/l4d2_tank_rage.phrases.txt b/addons/sourcemod/translations/chi/l4d2_tank_rage.phrases.txt new file mode 100644 index 000000000..f557e6651 --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d2_tank_rage.phrases.txt @@ -0,0 +1,11 @@ +"Phrases" +{ + "Tag" + { + "chi" "{red}[{default}Tank 控制权{red}]{default}" + } + "SurvivorsRunBack" + { + "chi" "每当生还者回退进度 {olive}%i{green}%% {default}, Tank将会获得 {olive}%0.1f {green}秒{default} 的控制权失去冷却." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/l4d_boss_percent.phrases.txt b/addons/sourcemod/translations/chi/l4d_boss_percent.phrases.txt new file mode 100644 index 000000000..af0993d08 --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d_boss_percent.phrases.txt @@ -0,0 +1,55 @@ +"Phrases" +{ + "TagTank" + { + "chi" "<{olive}Tank{default}>" + } + "TagWitch" + { + "chi" "<{olive}Witch{default}>" + } + "TankOn" + { + "chi" "Tank: %d%%" + } + "WitchOn" + { + "chi" "Witch: %d%%" + } + "Disabled" + { + "chi" "禁止生成" + } + "StaticSpawn" + { + "chi" "固定位置生成" + } + "None" + { + "chi" "无" + } + "TankDisabled" + { + "chi" "Tank: 禁止生成" + } + "TankStatic" + { + "chi" "Tank: 固定位置生成" + } + "TankNone" + { + "chi" "Tank: 无" + } + "WitchDisabled" + { + "chi" "Witch: 禁止生成" + } + "WitchStatic" + { + "chi" "Witch: 固定位置生成" + } + "WitchNone" + { + "chi" "Witch: 无" + } +} diff --git a/addons/sourcemod/translations/chi/l4d_boss_vote.phrases.txt b/addons/sourcemod/translations/chi/l4d_boss_vote.phrases.txt new file mode 100644 index 000000000..92c1b7522 --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d_boss_vote.phrases.txt @@ -0,0 +1,142 @@ +"Phrases" +{ + "Tag" + { + "chi" "{blue}<{green}Boss投票{blue}>{default}" + } + // RunVoteChecks + "NotAvailable" + { + "chi" "Boss投票不能在这张地图进行." + } + "Available" + { + "chi" "Boss投票只能在准备阶段 (ready up) 进行." + } + "FirstRound" + { + "chi" "Boss投票只能在本地图的第一轮进行." + } + "NotAvailableForSpec" + { + "chi" "旁观者不能进行Boss投票." + } + "CannotBeCalled" + { + "chi" "现在还不能发起Boss投票..." + } + // VoteBossCmd + "Usage" + { + "chi" "用法: !voteboss {olive}<{default}tank{olive}> <{default}witch{olive}>{default}." + } + "Usage2" + { + "chi" "用 {default}\"{blue}0{default}\" 代表 {olive}禁止生成{default}, \"{blue}-1{default}\" 代表 {olive}忽略本次投票." + } + "Invalid" + { + "chi" "{olive}无效的{default}进度数字." + } + "TankStatic" + { + "chi" "Tank在当前地图为固定位置生成, 无法进行投票." + } + "WitchStatic" + { + "chi" "Witch在当前地图为固定位置生成, 无法进行投票." + } + "TankBanned" + { + "chi" "该Tank进度数字已被{blue}禁止{default}." + } + "WitchBanned" + { + "chi" "该Witch进度数字已被{blue}禁止{default}." + } + "SetBosses" + { + "chi" "设置Tank进度为: %s 以及Witch进度为: %s?" + } + "SetTank" + { + "chi" "设置Tank进度为: %s 以及Witch进度为: 禁止生成?" + } + "SetOnlyTank" + { + "chi" "设置Tank进度为: %s?" + } + "SetWitch" + { + "chi" "设置Tank进度为: 禁止生成 以及Witch进度为: %s?" + } + "SetOnlyWitch" + { + "chi" "设置Witch进度为: %s?" + } + "SetBossesDisabled" + { + "chi" "设置Bosses进度为: 禁止生成?" + } + "SetTankDisabled" + { + "chi" "设置Tank进度为: 禁止生成?" + } + "SetWitchDisabled" + { + "chi" "设置Witch进度为: 禁止生成?" + } + // BossVoteResultHandler + "OnlyReadyUp" + { + "chi" "投票只能在准备阶段 (ready up) 进行." + } + "SettingBoss" + { + "chi" "正在设置Boss生成进度..." + } + "SettingTank" + { + "chi" "正在设置Tank生成进度..." + } + "SettingWitch" + { + "chi" "正在设置Witch生成进度..." + } + "SettingBossDisabled" + { + "chi" "正在设置Boss生成进度..." + } + // ForceTankCommand + "CommandNotAvailable" + { + "chi" "该指令不适用于本地图." + } + "TankSpawnStatic" + { + "chi" "Tank在当前地图为固定位置生成, 无法进行修改." + } + "PercentageInvalid" + { + "chi" "{blue}无效的{default}进度数字." + } + "Percentagebanned" + { + "chi" "该进度数字已被{blue}禁止{default}." + } + "TankSpawnAdmin" + { + "#format" "{1:i},{2:s}" // 1:p_iRequestedPercent 2:clientName + "chi" "Tank生成进度由管理员 {blue}{2}{default} 设置为 {olive}{1}%{default}." + } + // ForceWitchCommand + "WitchSpawnStatic" + { + "chi" "Witch在当前地图为固定位置生成, 无法进行修改." + } + "WitchSpawnAdmin" + { + "#format" "{1:i},{2:s}" // 1:p_iRequestedPercent 2:clientName + "chi" "Witch生成进度由管理员 {blue}{2}{default} 设置为 {olive}{1}%{default}." + } +} diff --git a/addons/sourcemod/translations/chi/l4d_tank_control_eq.phrases.txt b/addons/sourcemod/translations/chi/l4d_tank_control_eq.phrases.txt new file mode 100644 index 000000000..5b5dce977 --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d_tank_control_eq.phrases.txt @@ -0,0 +1,46 @@ +"Phrases" +{ + "TagRage" + { + "chi" "{red}<{default}Tank控制权{red}>" + } + "Refilled" + { + "chi" "{default}({green}%N{default}) 的{olive}控制权{red}重新回满" + } + "RefilledBot" + { + "chi" "{olive}控制权{red}重新回满" + } + + "TagSelection" + { + "chi" "{red}<{default}Tank轮换{red}>" + } + "YouBecomeTank" + { + "chi" "{green}你 {default}将会成为 {red}Tank{default}!" + } + "BecomeTank" + { + "chi" "{olive}%N {default}将会成为 {red}Tank!" + } + + "TagControl" + { + "chi" "{green}[{olive}Tank控制人{green}]" + } + "InvalidTarget" + { + "chi" "{default}无效的目标. 无法给予Tank" + } + "NoInfected" + { + "chi" "{olive}%N {default}不在感染者阵营, 无法给予Tank" + } + + "HintText" + { + "chi" "控制权重新回满" + } +} diff --git a/addons/sourcemod/translations/chi/l4d_weapon_limits.phrases.txt b/addons/sourcemod/translations/chi/l4d_weapon_limits.phrases.txt new file mode 100644 index 000000000..74c93539a --- /dev/null +++ b/addons/sourcemod/translations/chi/l4d_weapon_limits.phrases.txt @@ -0,0 +1,11 @@ +"Phrases" +{ + "Tag" + { + "chi" "{default}[{olive}武器数量限制{default}]" + } + "Full" + { + "chi" "这一类武器的拥有数量已经达到限制: {green}%d{default}!" + } +} diff --git a/addons/sourcemod/translations/chi/match_vote.phrases.txt b/addons/sourcemod/translations/chi/match_vote.phrases.txt new file mode 100644 index 000000000..9faa51069 --- /dev/null +++ b/addons/sourcemod/translations/chi/match_vote.phrases.txt @@ -0,0 +1,83 @@ +"Phrases" +{ + "Tag" + { + "chi" "[{olive}!{default}]" + } + "Disabled" + { + "chi" "插件{red}未启用{default}" + } + "NoConsole" + { + "chi" "该指令不能从控制台输入." + } + "ConfoglNotAvailable" + { + "chi" "Confogl {red}未启用{default}." + } + "CedaGame" + { + "chi" "不允许在{red}cedapug 比赛中使用该指令{default}" + } + "Title_Match" + { + "chi" "选择比赛模式:" + } + "Title_Config" + { + "chi" "选择类型 %s:" + } + "ConfigNotFound" + { + "chi" "未找到相关模式的配置文件." + } + "NoSpec" + { + "chi" "旁观者不允许进行投票." + } + "MatchLoaded" + { + "chi" "比赛模式已加载!" + } + "NotEnoughPlayers" + { + "chi" "不能发起投票. {red}玩家人数不足{default} ({red}%d{default}/{green}%d{default})." + } + "Title_LoadConfig" + { + "chi" "加载 confogl '%s' 配置?" + } + "VoteInProgress" + { + "chi" "{red}投票进行中{default}, 请等待 {green}%d{default} 秒." + } + "VotePass_Loading" + { + "chi" "加载比赛模式..." + } + "MatchNotLoaded" + { + "chi" "{red}没有比赛模式{default} 加载." + } + "PlayersConnecting" + { + "chi" "不能发起投票. 玩家们正在连接." + } + "Title_OffConfogl" + { + "chi" "卸载 Confogl?" + } + "VotePass_Unloading" + { + "chi" "Confogl 正在卸载..." + } + "Title_ChangeConfogl" + { + "chi" "更改 confogl 配置为 '%s'?" + } + "VotePass_Changed" + { + "chi" "比赛模式已更改..." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/nodeathcamskip.phrases.txt b/addons/sourcemod/translations/chi/nodeathcamskip.phrases.txt index 12f32d692..02e17f664 100644 --- a/addons/sourcemod/translations/chi/nodeathcamskip.phrases.txt +++ b/addons/sourcemod/translations/chi/nodeathcamskip.phrases.txt @@ -3,6 +3,6 @@ "WarnExploiting" { "#format" "{1:N}" - "en" "{red}[{default}Exploit{red}] {olive}{1} {default}tried skipping the Death Timer." + "chi" "{red}[{default}Exploit{red}] {olive}{1} {default}尝试跳过死亡时间." // didn't come out a translation for 'Exploit'. so be it. } } \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/pause.phrases.txt b/addons/sourcemod/translations/chi/pause.phrases.txt new file mode 100644 index 000000000..bdb95ef4c --- /dev/null +++ b/addons/sourcemod/translations/chi/pause.phrases.txt @@ -0,0 +1,185 @@ +"Phrases" +{ + "Tag" + { + "chi" "{default}[{green}!{default}]" + } + "ClientFullyLoaded" + { + "chi" "{olive}%N {default}已完全连接" + } + "PauseCommand" + { + "chi" "{olive}%N {blue}提出暂停{default}." + } + // PauseDelay_Timer + "PauseAction" + { + "chi" "{red}暂停" + } + "PauseDelay" + { + "chi" "{blue}即将暂停{default}: {olive}%d" + } + // ForcePause_Cmd + "Crashed" + { + "chi" "{olive}游戏 {default}因一位玩家 {blue}游戏崩溃{default} 被 {green}强制暂停{default}." + } + "ForcePause" + { + "chi" "{blue}管理员 {default}({olive}%N{default}) 发起了一个{green}强制暂停 {default}" + } + // Unpause_Cmd + "UnpauseSurvivors" + { + "chi" "{olive}%N %s{default}示意 {blue}%s {default}已准备好." + } + "UnpauseInfected" + { + "chi" "{olive}%N %s{default}示意 {red}%s {default}已准备好." + } + "UnpauseInitiator" + { + "chi" "{olive}%N {default}示意 {green}发起者 {default}已准备好." + } + "UnpauseAdminConfirm" + { + "chi" "{olive}双方团队 {default}已准备好. 等待 {blue}管理员 {default}{green}确认{default}." + } + // Unready_Cmd + "UnreadySurvivors" + { + "chi" "{olive}%N %s{default}示意 {blue}%s {default}未准备好." + } + "UnreadyInfected" + { + "chi" "{olive}%N %s{default}示意 {red}%s {default}未准备好." + } + "UnreadyInitiator" + { + "chi" "{olive}%N {default}示意 {green}发起者 {default}未准备好." + } + // void AsInitiator() + "AsInitiator" + { + "chi" "{default}作为 {green}发起者 " + } + // ForceUnpause_Cmd + "ForceUnpause" + { + "chi" "{blue}管理员 {default}({olive}%N{default}) 发起了 {green}强制解除暂停{default}" + } + // AddPauseCount + "PauseLimit" + { + "chi" "你已达到你的暂停限制." + } + // AttemptPause + "PauseDeferred" + { + "chi" "{red}暂停因一个救人过程正在进行而推迟!" + } + // Pause + "PausePreventSpawn" + { + "chi" "{default}你的 {red}特感重生 {default}因暂停而被阻止" + } + // Show_Cmd + "PanelShow" + { + "chi" "面板现已 {blue}开{default}." + } + "PanelHide" + { + "chi" "面板现已 {red}关{default}." + } + // UpdatePanel + "PanelSlots" + { + "chi" "▸ 服务器: %s\n▸ 位数: %d/%d" + } + "PanelDate" + { + "chi" "▸ %m/%d/%Y - %I:%M%p" + } + "PanelTitle" + { + "chi" "▸ 准备状态" + } + "RequireAdmin" + { + "chi" "->0. 需要管理员解除暂停" + } + "SurvivorUnPaused" + { + "chi" "->1. 生还者: [√]" + } + "SurvivorPaused" + { + "chi" "->1. 生还者: [X]" + } + "InfectedUnPaused" + { + "chi" "->2. 感染者: [√]" + } + "InfectedPaused" + { + "chi" "->2. 感染者: [X]" + } + "InitiatorUnPaused" + { + "chi" "->0. 发起者: [√]" + } + "InitiatorPaused" + { + "chi" "->0. 发起者: [X]" + } + "AutoPauseCrash" + { + "chi" "▸ 强制自动暂停 -> 游戏崩溃" + } + "ForcePauseAdmin" + { + "chi" "▸ 强制暂停 -> %s (管理员)" + } + "InitiatorPause" + { + "chi" "▸ 发起者 -> %s (%s)" + } + "DurationPause" + { + "chi" "▸ 时长: %02d:%02d" + } + // InitiateLiveCountdown + "CountdownCancelNotify" + { + "chi" "输入 {olive}!unready {default}来取消" + } + "GameisLive" + { + "chi" "游戏继续!" + } + "CountdownReadyDelay" + { + "chi" "{blue}解除暂停{default}: {olive}%d{default}..." + } + // CancelFullReady + "CountdownCancelled" + { + "chi" "{olive}%N {default}取消了倒计时!" + } + // Callvote_Callback + "CallvoteNoSpec" + { + "chi" "你不能作为一个旁观者发起投票." + } + "CallvoteNoExploit" + { + "chi" "你刚刚切换了队伍, 你不能在几秒内发起投票." + } + "CallvoteCannotTargetAdmin" + { + "chi" "你不能踢出管理员." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/playermanagement.phrases.txt b/addons/sourcemod/translations/chi/playermanagement.phrases.txt new file mode 100644 index 000000000..b0b7e1539 --- /dev/null +++ b/addons/sourcemod/translations/chi/playermanagement.phrases.txt @@ -0,0 +1,39 @@ +"Phrases" +{ + "Tag" + { + "chi" "[{olive}!{default}]" + } + "Usage" + { + "chi" "{blue}用法{default}" + } + "NoSnoop" + { + "chi" "你不能旁观{red}偷窥{default}Tank!" + } + "BecomeSpectator" + { + "chi" "{teamcolor}%N{default} 变成了旁观者!" + } + "WhileCapped" + { + "chi" "倒地时{red}不允许旁观{default}!" + } + "FixBot" + { + "chi" "{teamcolor}%N{default} 在尝试修复bot数量" + } + "FixBotConsole" + { + "chi" "控制台在尝试{red}修复bot数量{default}" + } + "ValidTeams" + { + "chi" "有效队伍: %d = 旁观者, %d = 生还者, %d = 感染者" + } + "CouldNotSwitched" + { + "chi" "{teamcolor}%N{default} 不能切换队伍, 因为目标团队人员已满或没有bot接管." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/si_class_announce.phrases.txt b/addons/sourcemod/translations/chi/si_class_announce.phrases.txt new file mode 100644 index 000000000..f24db2a91 --- /dev/null +++ b/addons/sourcemod/translations/chi/si_class_announce.phrases.txt @@ -0,0 +1,11 @@ +"Phrases" +{ + "SI" + { + "chi" "特感: " + } + "SpecialInfected" + { + "chi" "特殊感染者: " + } +} diff --git a/addons/sourcemod/translations/chi/slots_vote.phrases.txt b/addons/sourcemod/translations/chi/slots_vote.phrases.txt new file mode 100644 index 000000000..60d9ad0e2 --- /dev/null +++ b/addons/sourcemod/translations/chi/slots_vote.phrases.txt @@ -0,0 +1,44 @@ +"Phrases" +{ + "Tag" + { + "chi" "{blue}[{default}位数{blue}]{default}" + } + "NotConsoleVote" + { + "chi" "[位数] 你必须在游戏内." + } + "LimitSlotsAbove" + { + "chi" "你不能在这个服务器中限制超过 {olive}%i{default} 以上的位数." + } + "LimitedSlotsTo" + { + "#format" "{1:s},{2:i}" // 1:sName 2:Int + "chi" "{olive}{1}{default} 已将位数限制为 {blue}{2}{default}" + } + "RequiredPlayers" + { + "chi" "你不能将位数限制为低于已有玩家的数量." + } + "SlotsUsage" + { + "chi" "用法: {olive}!slots{default} <{olive}数字{default}> {blue}|{default} 例如: {olive}!slots 8{default}" + } + "Spectators" + { + "chi" "旁观者不允许投票." + } + "LimitSlots" + { + "chi" "限制位数为 '%s'?" + } + "CannotBeStarted" + { + "chi" "现在不能发起投票." + } + "LimitingSlots" + { + "chi" "正在限制位数..." + } +} diff --git a/addons/sourcemod/translations/chi/tank_rush.phrases.txt b/addons/sourcemod/translations/chi/tank_rush.phrases.txt new file mode 100644 index 000000000..917e99358 --- /dev/null +++ b/addons/sourcemod/translations/chi/tank_rush.phrases.txt @@ -0,0 +1,19 @@ +"Phrases" +{ + "Tag" + { + "chi" "{red}[{default}克局封锁{red}]" + } + "freeze" + { + "chi" "{red}Tank {default}已生成. {olive}冻结 {default}路程分!" + } + "unfreeze" + { + "chi" "{red}Tank {default}已死亡. {olive}解冻 {default}路程分!" + } + "saferoom" + { + "chi" "{red}生还者 {default}成功到达了安全屋. {olive}解冻 {default}路程分!" + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/chi/tpsblock.phrases.txt b/addons/sourcemod/translations/chi/tpsblock.phrases.txt new file mode 100644 index 000000000..839e95314 --- /dev/null +++ b/addons/sourcemod/translations/chi/tpsblock.phrases.txt @@ -0,0 +1,23 @@ +"Phrases" +{ + "Tag" + { + "chi" "[{green}!{default}]" + } + "Cvar_Invalid" + { + "chi" "指令 {olive}c_thirdpersonshoulder{default} 无效或被保护." + } + "Cvar_Value1" + { + "chi" "进入游戏需在你的控制台里输入 {olive}c_thirdpersonshoulder 0{default}." + } + "Cvar_Invalid_Nocolor" + { + "chi" "指令 c_thirdpersonshoulder 无效或被保护." + } + "Cvar_Value1_Nocolor" + { + "chi" "进入游戏需在你的控制台里输入 c_thirdpersonshoulder 0." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/es/l4d2_stats.phrases.txt b/addons/sourcemod/translations/es/l4d2_stats.phrases.txt index a01f3fff0..9c0c4e623 100644 --- a/addons/sourcemod/translations/es/l4d2_stats.phrases.txt +++ b/addons/sourcemod/translations/es/l4d2_stats.phrases.txt @@ -41,6 +41,14 @@ { "es" "{olive}%N{default} activó un {olive}Automóvil con alarma{default}" } + "Plural" + { + "es" "s" + } + "Shot" + { + "es" "disparo" + } } diff --git a/addons/sourcemod/translations/l4d2_skill_detect.phrases.txt b/addons/sourcemod/translations/l4d2_skill_detect.phrases.txt index 946f475d3..55db4e648 100644 --- a/addons/sourcemod/translations/l4d2_skill_detect.phrases.txt +++ b/addons/sourcemod/translations/l4d2_skill_detect.phrases.txt @@ -271,7 +271,7 @@ } "CalarmBoomer" { - "#format" "{1:N},{2:N}" // 1:infected 2:survivor + "#format" "{1:N},{2:N}" // 1:survivor 2:infected "en" "{olive}{1}{default} triggered an alarm by killing a boomer {olive}{2}{default}." } "CalarmBoomerBot" diff --git a/addons/sourcemod/translations/l4d2_stats.phrases.txt b/addons/sourcemod/translations/l4d2_stats.phrases.txt index c64e32a0a..a879563f7 100644 --- a/addons/sourcemod/translations/l4d2_stats.phrases.txt +++ b/addons/sourcemod/translations/l4d2_stats.phrases.txt @@ -41,6 +41,14 @@ { "en" "{olive}%N{default} triggered an {olive}Alarmed Car{default}" } + "Plural" + { + "en" "s" + } + "Shot" + { + "en" "shot" + } }