From 45395e51eb4927a0cb73afc5ebed7f242a74429c Mon Sep 17 00:00:00 2001 From: cy115 <1157804552@qq.com> Date: Sat, 9 May 2026 18:56:25 +0800 Subject: [PATCH 1/2] Try new socremod --- .../optional/l4d2_new_generation_scoremod.smx | Bin 0 -> 18177 bytes .../include/l4d2_new_generation_scoremod.inc | 47 ++ .../scripting/l4d2_new_generation_scoremod.sp | 761 ++++++++++++++++++ 3 files changed, 808 insertions(+) create mode 100644 addons/sourcemod/plugins/optional/l4d2_new_generation_scoremod.smx create mode 100644 addons/sourcemod/scripting/include/l4d2_new_generation_scoremod.inc create mode 100644 addons/sourcemod/scripting/l4d2_new_generation_scoremod.sp diff --git a/addons/sourcemod/plugins/optional/l4d2_new_generation_scoremod.smx b/addons/sourcemod/plugins/optional/l4d2_new_generation_scoremod.smx new file mode 100644 index 0000000000000000000000000000000000000000..c7951a08855623365461f3ea08a01199ac2ccc46 GIT binary patch literal 18177 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 lZV +#include +#include +#include +#include +#undef REQUIRE_PLUGIN +#include + +/*---------------------------------------------- +------------------- Variables ------------------ +----------------------------------------------*/ + +int + g_iTeamSize, + g_iMapDistance, + g_iMapMaxDistance, + g_iPillsBonus, + g_iPillWorth; + +float + // variables of bonus + g_fMapBonus, // TotalBonus + // permanent health bonus + g_fPermHealthBonus, + g_fPermHealthBonusRate, + // damage health bonus + g_fDamageBonus, + g_fDamageBonusRate, + // skill bonus + g_fSkillBonus, + g_fSkillBonusRate, + // pills bonus + g_fPillsBonusRate, + // Condition bonus + g_fConditionBonus, + g_fConditionBonusRate, + // skill bonus percent + g_f5Percent, + g_f10Percent, + g_f20Percent; + +bool + g_bLateLoad, + g_bRoundOver; + +// Game Cvars +ConVar + g_hCvarValveTieBreaker, + g_hCvarValveDefibPenalty, + g_hCvarValveSurvivalBonus; + +enum struct Team { + int iLostDamageBonus; // damage bonus lose per round + int iSiDamage; // damage bonus rest + + float fSkillGainBonus; // skill bonus gain per rond + float fSurvivorBonus; + float fSurvivorMainBonus; + float fSurvivorSkillBonus; + + bool bTiebreakerEligibility; // tier breaker + + char sSurvivorState[32]; + + void Reset() { + this.iLostDamageBonus = 0; + this.fSkillGainBonus = 0.0; + this.iSiDamage = 0; + this.bTiebreakerEligibility = false; + } +} +Team g_esTeam[2]; + +/*---------------------------------------------- +-------------------- Marcos -------------------- +----------------------------------------------*/ + +#define PERCENT_5 0.05 +#define PERCENT_10 0.10 +#define PERCENT_20 0.20 + +public Plugin myinfo = +{ + name = "L4D2 New Generation ScoreMod", + author = "Hitomi", + description = "New Generation ScoreMod for Versus", + version = "1.3", + url = "https://github.com/cy115/" +}; + +/*---------------------------------------------- +-------------------- Natives ------------------- +----------------------------------------------*/ + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + CreateNative("NGSM_GetRestBonus", Native_GetRestBonus); + CreateNative("NGSM_GetPermHealthBonus", Native_GetPermHealthBonus); + CreateNative("NGSM_GetDamageBonus", Native_GetDamageBonus); + CreateNative("NGSM_GetSkillBonus", Native_GetSkillBonus); + CreateNative("NGSM_GetPillsBonus", Native_GetPillsBonus); + CreateNative("NGSM_GetConditionBonus", Native_GetConditionBonus); + //=====================================================// + CreateNative("NGSM_GetMaxChapterBonus", Native_GetMaxChapterBonus); + CreateNative("NGSM_GetMaxPermHealthBonus", Native_GetMaxPermHealthBonus); + CreateNative("NGSM_GetMaxDamageBonus", Native_GetMaxDamageBonus); + CreateNative("NGSM_GetMaxSkillBonus", Native_GetMaxSkillBonus); + CreateNative("NGSM_GetMaxPillsBonus", Native_GetMaxPillsBonus); + CreateNative("NGSM_GetMaxConditionBonus", Native_GetMaxConditionBonus); + //===========================================================// + RegPluginLibrary("l4d2_new_generation_scoremod"); + g_bLateLoad = late; + + return APLRes_Success; +} + +int Native_GetRestBonus(Handle plugin, int numParams) { + return (RoundToFloor(g_fPermHealthBonus) + RoundToFloor(g_fDamageBonus) + RoundToFloor(g_fSkillBonus) + g_iPillsBonus + RoundToFloor(g_fConditionBonus)) - + (RoundToFloor(GetSurvivorPermHealthBonus()) + RoundToFloor(GetSurvivorDamageBonus()) + RoundToFloor(GetSurvivorSkillBonus()) + RoundToFloor(GetSurvivorPillsBonus()) + RoundToFloor(GetSurvivorConditionBonus())); +} + +int Native_GetPermHealthBonus(Handle plugin, int numParams) { + return RoundToFloor(GetSurvivorPermHealthBonus()); +} + +int Native_GetDamageBonus(Handle plugin, int numParams) { + return RoundToFloor(GetSurvivorDamageBonus()); +} + +int Native_GetSkillBonus(Handle plugin, int numParams) { + return RoundToFloor(GetSurvivorSkillBonus()); +} + +int Native_GetPillsBonus(Handle plugin, int numParams) { + return RoundToFloor(GetSurvivorPillsBonus()); +} + +int Native_GetConditionBonus(Handle plugin, int numParams) { + return RoundToFloor(GetSurvivorConditionBonus()); +} + +int Native_GetMaxChapterBonus(Handle plugin, int numParams) { + return RoundToFloor(g_fPermHealthBonus) + RoundToFloor(g_fDamageBonus) + RoundToFloor(g_fSkillBonus) + g_iPillsBonus + RoundToFloor(g_fConditionBonus); +} + +int Native_GetMaxPermHealthBonus(Handle plugin, int numParams) { + return RoundToFloor(g_fPermHealthBonus); +} + +int Native_GetMaxDamageBonus(Handle plugin, int numParams) { + return RoundToFloor(g_fDamageBonus); +} + +int Native_GetMaxSkillBonus(Handle plugin, int numParams) { + return RoundToFloor(g_fSkillBonus); +} + +int Native_GetMaxPillsBonus(Handle plugin, int numParams) { + return g_iPillsBonus; +} + +int Native_GetMaxConditionBonus(Handle plugin, int numParams) { + return RoundToFloor(g_fConditionBonus); +} + +/*---------------------------------------------- +--------------------- Main --------------------- +----------------------------------------------*/ + +public void OnPluginStart() +{ + // Get Game Cvars + g_hCvarValveTieBreaker = FindConVar("vs_tiebreak_bonus"); + g_hCvarValveDefibPenalty = FindConVar("vs_defib_penalty"); + g_hCvarValveSurvivalBonus = FindConVar("vs_survival_bonus"); + + // Regist Plugin Convars + CreateConVarHook("l4d2_NGSM_Perm", "1.2", "Permanent health bonus ratio[maxMapDistance * thisRatio].", _, true, 0.0, false, 0.0, OnPHBChange); + CreateConVarHook("l4d2_NGSM_Incap", "0.8", "Damage bonus ratio[maxMapDistance * thisRatio].", _, true, 0.0, false, 0.0, OnIBRChange); + CreateConVarHook("l4d2_NGSM_Skill", "0.5", "Skill bonus ratio[maxMapDistance * thisRatio].", _, true, 0.0, false, 0.0, OnSBRChange); + CreateConVarHook("l4d2_NGSM_Pills", "0.2", "Pill bonus ratio[maxMapDistance * thisRatio].", _, true, 0.0, false, 0.0, OnPBRChange); + CreateConVarHook("l4d2_NGSM_Condition", "0.4", "Condition bonus ratio[maxMapDistance * thisRatio].", _, true, 0.0, false, 0.0, OnCBRChange); + + // Hook Evnets + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); + HookEvent("player_incapacitated", Event_PlayerIncapacitated); + HookEvent("player_death", Event_PlayerDeath); + + // Commands + RegConsoleCmd("sm_health", Cmd_Bonus, "Print bonus."); + RegConsoleCmd("sm_bonus", Cmd_Bonus, "Print bonus."); + RegConsoleCmd("sm_mapinfo", Cmd_MapInfo, "Print Map bonus info."); + + // late load + if (g_bLateLoad) { + for (int i = 1; i <= MaxClients; i++) { + if (!IsClientInGame(i)) { + continue; + } + + OnClientPutInServer(i); + } + } +} + +public void OnPluginEnd() +{ + g_hCvarValveTieBreaker.RestoreDefault(); + g_hCvarValveDefibPenalty.RestoreDefault(); + g_hCvarValveSurvivalBonus.RestoreDefault(); +} + +public void OnConfigsExecuted() +{ + // Initialize survivor count and bonus values + g_iTeamSize = FindConVar("survivor_limit").IntValue; + g_hCvarValveTieBreaker.SetInt(0); + g_hCvarValveDefibPenalty.SetInt(0); + g_hCvarValveSurvivalBonus.SetInt(0); + // Initialize map distance (bonus) + g_iMapMaxDistance = L4D2_GetMapValueInt("max_distance", L4D_GetVersusMaxCompletionScore()); + L4D_SetVersusMaxCompletionScore(g_iMapMaxDistance); + g_iMapDistance = (g_iMapMaxDistance / 4) * g_iTeamSize; + + g_fMapBonus = g_iMapDistance * (g_fPermHealthBonusRate + g_fDamageBonusRate + g_fSkillBonusRate + g_fPillsBonusRate + g_fConditionBonusRate); // 地图总分 + g_fPermHealthBonus = g_iMapDistance * g_fPermHealthBonusRate; // Total health bonus + g_fDamageBonus = g_iMapDistance * g_fDamageBonusRate; // Total damage bonus + g_fSkillBonus = g_iMapDistance * g_fSkillBonusRate; // Total skill bonus + g_iPillsBonus = RoundToNearest(g_iMapDistance * g_fPillsBonusRate); // Total pills bonus + g_fConditionBonus = g_iMapDistance * g_fConditionBonusRate; // Total conditionBonus + g_iPillWorth = g_iPillsBonus / g_iTeamSize; // Bonus of per pain_pill + + // Skill bonus thresholds + g_f5Percent = g_fSkillBonus * 0.05; + g_f10Percent = g_fSkillBonus * 0.1; + g_f20Percent = g_fSkillBonus * 0.2; +} + +public void OnMapStart() +{ + OnConfigsExecuted(); + + g_esTeam[0].Reset(); + g_esTeam[1].Reset(); +} + +public Action L4D2_OnEndVersusModeRound(bool countSurvivors) +{ + if (g_bRoundOver) { + return Plugin_Continue; + } + + int + team = InSecondHalfOfRound(), + iSurvivalMultiplier = countSurvivors ? GetAliveSurvivorCount() : 0; + + g_esTeam[team].fSurvivorSkillBonus = GetSurvivorSkillBonus(); + g_esTeam[team].fSurvivorSkillBonus = float(RoundToFloor(g_esTeam[team].fSurvivorSkillBonus / g_iTeamSize) * g_iTeamSize); + + g_esTeam[team].fSurvivorMainBonus = GetSurvivorPermHealthBonus() + GetSurvivorDamageBonus() + GetSurvivorPillsBonus() +GetSurvivorConditionBonus(); + g_esTeam[team].fSurvivorMainBonus = float(RoundToFloor(g_esTeam[team].fSurvivorMainBonus / g_iTeamSize) *g_iTeamSize); + + g_esTeam[team].fSurvivorBonus = g_esTeam[team].fSurvivorMainBonus + g_esTeam[team].fSurvivorSkillBonus; + if (iSurvivalMultiplier > 0 && RoundToFloor(g_esTeam[team].fSurvivorBonus / iSurvivalMultiplier) >= g_iTeamSize) { + g_hCvarValveSurvivalBonus.SetInt(RoundToFloor(g_esTeam[team].fSurvivorMainBonus / iSurvivalMultiplier)); + g_esTeam[team].fSurvivorMainBonus = float(g_hCvarValveSurvivalBonus.IntValue * iSurvivalMultiplier); + FormatEx(g_esTeam[team].sSurvivorState, sizeof(Team::sSurvivorState), "%s%i\x01/\x05%i\x01", (iSurvivalMultiplier == g_iTeamSize ? "\x05" : "\x04"), iSurvivalMultiplier, g_iTeamSize); + } else { + g_esTeam[team].fSurvivorBonus = 0.0; + g_hCvarValveSurvivalBonus.SetInt(0); + g_hCvarValveDefibPenalty.SetInt(0); + g_esTeam[team].bTiebreakerEligibility = (iSurvivalMultiplier == g_iTeamSize); + FormatEx(g_esTeam[team].sSurvivorState, sizeof(Team::sSurvivorState), "\x04%s\x01", (iSurvivalMultiplier == 0 ? "wiped out" : "bonus depleted")); + } + + g_hCvarValveDefibPenalty.SetInt(-RoundToFloor(g_esTeam[team].fSurvivorSkillBonus)); + GameRules_SetProp("m_iVersusDefibsUsed", (RoundToFloor(g_esTeam[team].fSurvivorSkillBonus) == 0) ? 0 : 1, 4, GameRules_GetProp("m_bAreTeamsFlipped", 4, 0)); + + if (team > 0 && g_esTeam[0].bTiebreakerEligibility && g_esTeam[1].bTiebreakerEligibility) { + GameRules_SetProp("m_iChapterDamage", g_esTeam[0].iSiDamage, _, 0, true); + GameRules_SetProp("m_iChapterDamage", g_esTeam[1].iSiDamage, _, 1, true); + if (g_esTeam[0].iSiDamage != g_esTeam[1].iSiDamage) { + g_hCvarValveTieBreaker.SetInt(g_iPillWorth); + } + } + + // 打印 + CreateTimer(3.0, Timer_PrintRoundEndBonus, _, TIMER_FLAG_NO_MAPCHANGE); + g_bRoundOver = true; + + return Plugin_Continue; +} + +public void OnClientPutInServer(int client) +{ + SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); +} + +public void OnClientDisconnect(int client) +{ + SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage); +} + +Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype) +{ + if (!IsSurvivor(victim) || IsPlayerIncap(victim)) { + return Plugin_Continue; + } + + if (!IsAnyInfected(attacker)) { + g_esTeam[InSecondHalfOfRound()].iSiDamage += (damage <= 100.0 ? RoundFloat(damage) : 100); + } + + return Plugin_Continue; +} + +/*---------------------------------------------- +-------------------- Events -------------------- +----------------------------------------------*/ + +void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) +{ + g_bRoundOver = false; +} + +void Event_PlayerIncapacitated(Event event, const char[] name, bool dontBroadcast) +{ + if (g_bRoundOver) { + return; + } + + int sur = GetClientOfUserId(event.GetInt("userid")); + if (IsSurvivor(sur) && !IsPlayerLedged(sur)) { + g_esTeam[InSecondHalfOfRound()].iLostDamageBonus += + RoundToFloor(g_fDamageBonus * (GetEntProp(sur, Prop_Send, "m_currentReviveCount") + 1) * 0.1); + } +} + +void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) +{ + if (g_bRoundOver) { + return; + } + + int sur = GetClientOfUserId(event.GetInt("userid")); + if (IsSurvivor(sur) && !GetEntProp(sur, Prop_Send, "m_currentReviveCount")) { + g_esTeam[InSecondHalfOfRound()].iLostDamageBonus += + RoundToFloor(g_fDamageBonus * 0.25); + } +} + +/*---------------------------------------------- +------------------- Commands ------------------- +----------------------------------------------*/ + +Action Cmd_Bonus(int client, int args) +{ + if (g_bRoundOver || !client) { + return Plugin_Handled; + } + + float + fPermHealthBonus = GetSurvivorPermHealthBonus(), + fDamageBonus = GetSurvivorDamageBonus(), + fSkillBonus = GetSurvivorSkillBonus(), + fPillsBonus = GetSurvivorPillsBonus(), + fConditionBonus = GetSurvivorConditionBonus(); + + int + team = InSecondHalfOfRound(), + totalBonus = RoundToFloor(fPermHealthBonus + fDamageBonus + fSkillBonus + fPillsBonus + fConditionBonus); + // Second Round + if (team) { + CPrintToChat(client, "{red}R\x01#\x051 \x01Bonus: {red}%d \x01<{red}%.1f%%\x01> [%s]", + RoundToFloor(g_esTeam[0].fSurvivorMainBonus + g_esTeam[0].fSurvivorSkillBonus), + CalculateBonusPercent(g_esTeam[0].fSurvivorMainBonus + g_esTeam[0].fSurvivorSkillBonus), + g_esTeam[0].sSurvivorState); + } + + CPrintToChat(client, "{blue}R\x01#\x05%i \x01Bonus: {blue}%d \x01<{blue}%.1f%%\x01>", + team + 1, totalBonus, + CalculateBonusPercent(fPermHealthBonus + fDamageBonus + fSkillBonus + fPillsBonus + fConditionBonus, g_fMapBonus)); + CPrintToChat(client, "\x01[ {blue}HB\x01: \x05%.0f%% \x01| {blue}DB\x01: \x05%.0f%% \x01| {blue}SB\x01: \x05%.0f%% \x01| {blue}PB\x01: \x05%.0f%% \x01| {blue}CB\x01: \x05%.0f%% \x01]", + CalculateBonusPercent(fPermHealthBonus, g_fPermHealthBonus), CalculateBonusPercent(fDamageBonus, g_fDamageBonus), + CalculateBonusPercent(g_esTeam[team].fSkillGainBonus, g_fSkillBonus), CalculateBonusPercent(fPillsBonus, float(g_iPillsBonus)), + CalculateBonusPercent(fConditionBonus, g_fConditionBonus)); + // R#1 Bonus: 1145 <81%> + // [HB: 20% | DB: 50% | SB: 56% | PB: 75% | CB: 50%] + + return Plugin_Handled; +} + +Action Cmd_MapInfo(int client, int args) +{ + if (!client) { + return Plugin_Handled; + } + + CPrintToChat(client, "\x01[{lightgreen}NGSM \x01:: {lightgreen}%i\x01v{lightgreen}%i\x01] \x05Map Info", g_iTeamSize, g_iTeamSize); + CPrintToChat(client, "{blue}Distance\x01: [\x05%d\x01]\n{blue}MaxBonus\x01: [\x05%d\x01]", g_iMapDistance, RoundToFloor(g_fMapBonus)); + CPrintToChat(client, "{blue}PermBonus\x01: [\x05%d\x01]\n{blue}DamageBonus\x01: [\x05%d\x01]", RoundToFloor(g_fPermHealthBonus), RoundToFloor(g_fDamageBonus)); + CPrintToChat(client, "{blue}SkillBonus\x01: [\x05%d\x01]\n{blue}PillsBonus\x01: [\x05%d\x01]", RoundToFloor(g_fSkillBonus), g_iPillsBonus); + CPrintToChat(client, "{blue}ConditionBonus\x01: [\x05%d\x01]\n{blue}TieBreaker\x01: [\x05%d\x01]", RoundToFloor(g_fConditionBonus), g_iPillWorth); + + // [NGSM :: 4v4] Map Info + // Distance: [400] + // MaxBonus: [920] + // PermBonus: [600] + // DamageBonus: [200] + // SkillBonus: [30] + // PillsBonus: [30] + // ConditionBonus: [30] + // TieBreaker: [30] + + return Plugin_Handled; +} + +// Functions of Others +Action Timer_PrintRoundEndBonus(Handle timer) +{ + int team = InSecondHalfOfRound(); + for (int i = 0; i <= team; i++) { + CPrintToChatAll("{lightgreen}R\x01#\x05%i \x01Bonus: {lightgreen}%d\x01/{lightgreen}%d \x01<{lightgreen}%.1f%%\x01> [%s]", + i + 1, RoundToFloor(g_esTeam[team].fSurvivorMainBonus), + RoundToFloor(g_fMapBonus), + CalculateBonusPercent(g_esTeam[team].fSurvivorMainBonus), + g_esTeam[team].sSurvivorState); + } + + if (team && g_esTeam[0].bTiebreakerEligibility && g_esTeam[1].bTiebreakerEligibility) { + CPrintToChatAll("{red}TIEBREAKER\x01: Team {red}#1\x01 - {red}%i\x01, Team {blue}#2\x01 - {blue}%i", g_esTeam[0].iSiDamage, g_esTeam[1].iSiDamage); + if (g_esTeam[0].iSiDamage == g_esTeam[1].iSiDamage) { + CPrintToChatAll("{red}Teams have performed absolutely equal\x01! Impossible to decide a clear round winner"); + } + } + + return Plugin_Continue; +} + +// Functions of GetBouns +float GetSurvivorPermHealthBonus() +{ + float fPermHealthBonus; + int survivorCount, survivalMultiplier; + for (int i = 1; i <= MaxClients && survivorCount < g_iTeamSize; i++) { + if (IsSurvivor(i)) { + survivorCount++; + if (IsPlayerAlive(i) && !IsPlayerIncap(i) && !IsPlayerLedged(i)) { + survivalMultiplier++; + if (GetEntProp(i, Prop_Send, "m_currentReviveCount") != 0) { + continue; + } + + fPermHealthBonus += GetSurvivorPermanentHealth(i) * ((g_fPermHealthBonus / g_iTeamSize) / 100); + } + } + } + + return (fPermHealthBonus / g_iTeamSize * survivalMultiplier); +} + +float GetSurvivorDamageBonus() +{ + int team = InSecondHalfOfRound(); + float LostDamage = float(g_esTeam[team].iLostDamageBonus); + + return (g_fDamageBonus >= LostDamage) ? g_fDamageBonus - LostDamage : 0.0; +} + +float GetSurvivorSkillBonus() +{ + return g_esTeam[InSecondHalfOfRound()].fSkillGainBonus; +} + +float GetSurvivorPillsBonus() +{ + int pillsBonus; + for (int i = 1; i <= MaxClients; i++) { + if (IsSurvivor(i)) { + if (IsPlayerAlive(i) && !IsPlayerIncap(i) && HasPills(i)) { + pillsBonus += g_iPillWorth; + } + } + } + + return float(pillsBonus); +} + +float GetSurvivorConditionBonus() +{ + int + iSurvivorCount = 0, + iGreenSurvivorCount = 0, + iYellowSurvivorCount = 0, + iRedSurvivorCount = 0, + iTotalHealth = 0; + + float + fGreenWorth = g_fConditionBonus / 4, + fYellowWorth = g_fConditionBonus / 10, + fRedWorth = g_fConditionBonus / 20; + + for (int i = 1; i <= MaxClients && iSurvivorCount < g_iTeamSize; i++) { + if (IsSurvivor(i)) { + iSurvivorCount++; + if (IsPlayerAlive(i) && !IsPlayerIncap(i) && !IsPlayerLedged(i)) { + if (GetEntProp(i, Prop_Send, "m_currentReviveCount") == 0) { + iTotalHealth = GetEntProp(i, Prop_Send, "m_iHealth") + GetSurvivorTemporaryHealth(i); + } + else { + iTotalHealth = GetSurvivorTemporaryHealth(i) + 1; + } + + if (iTotalHealth >= 40) {iGreenSurvivorCount++;} + else if (iTotalHealth >= 25) {iYellowSurvivorCount++;} + else {iRedSurvivorCount++;} + } + } + } + + return iGreenSurvivorCount * fGreenWorth + iYellowSurvivorCount * fYellowWorth + iRedSurvivorCount * fRedWorth; +} + +/*---------------------------------------------- +--------------------- Tools -------------------- +----------------------------------------------*/ +stock int InSecondHalfOfRound() +{ + return GameRules_GetProp("m_bInSecondHalfOfRound"); +} + +stock int GetAliveSurvivorCount() +{ + int iAliveCount, iSurvivorCount; + for (int i = 1; i <= MaxClients && iSurvivorCount < g_iTeamSize; i++) { + if (IsSurvivor(i)) { + iSurvivorCount++; + if (IsPlayerAlive(i)) { + iAliveCount++; + } + } + } + + return iAliveCount; +} + +stock int GetSurvivorPermanentHealth(int client) +{ + return GetEntProp(client, Prop_Send, "m_currentReviveCount") > 0 ? 0 : (GetEntProp(client, Prop_Send, "m_iHealth") > 0 ? GetEntProp(client, Prop_Send, "m_iHealth") : 0); +} + +stock int GetSurvivorTemporaryHealth(int client) +{ + int temphp = RoundToCeil(GetEntPropFloat(client, Prop_Send, "m_healthBuffer") - ((GetGameTime() - GetEntPropFloat(client, Prop_Send, "m_healthBufferTime")) * FindConVar("pain_pills_decay_rate").FloatValue)) - 1; + return (temphp > 0 ? temphp : 0); +} + +stock float CalculateBonusPercent(float score, float maxbonus = -1.0) +{ + return score / (maxbonus == -1.0 ? g_fMapBonus : maxbonus) * 100; +} + +stock bool HasPills(int client) +{ + int item = GetPlayerWeaponSlot(client, 4); + if (IsValidEdict(item)) { + char buffer[32]; + GetEdictClassname(item, buffer, sizeof(buffer)); + return StrEqual(buffer, "weapon_pain_pills"); + } + + return false; +} + +stock bool IsSurvivor(int client) +{ + return client > 0 && client <= MaxClients && IsClientInGame(client) && GetClientTeam(client) == 2; +} + +stock bool IsPlayerIncap(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_isIncapacitated")); +} + +stock bool IsPlayerLedged(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge")|GetEntProp(client, Prop_Send, "m_isFallingFromLedge")); +} + +/*---------------------------------------------- +------------------ Skill Detect ---------------- +----------------------------------------------*/ + +public void OnSpecialClear(int clearer, int pinner, int pinvictim, int zombieClass, float timeA, float timeB, bool withShove) +{ + int team = InSecondHalfOfRound(); + if (timeA <= 0.2 || timeB <= 0.2) { + if (g_esTeam[team].fSkillGainBonus < g_fSkillBonus) { + g_esTeam[team].fSkillGainBonus = g_esTeam[team].fSkillGainBonus + g_f5Percent >= g_fSkillBonus ? g_fSkillBonus : g_esTeam[team].fSkillGainBonus + g_f5Percent; + } + } +} + +public void OnHunterSkeet(int survivor, int hunter) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (g_esTeam[team].fSkillGainBonus < g_fSkillBonus){ + g_esTeam[team].fSkillGainBonus = g_esTeam[team].fSkillGainBonus + g_f5Percent >= g_fSkillBonus ? g_fSkillBonus : g_esTeam[team].fSkillGainBonus + g_f5Percent; + } +} + +public void OnChargerLevelHurt(int survivor, int charger, int damage) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (g_esTeam[team].fSkillGainBonus < g_fSkillBonus) { + g_esTeam[team].fSkillGainBonus = g_esTeam[team].fSkillGainBonus + g_f5Percent >= g_fSkillBonus ? g_fSkillBonus : g_esTeam[team].fSkillGainBonus + g_f5Percent; + } +} + +public void OnWitchCrown(int survivor, int damage) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (g_esTeam[team].fSkillGainBonus < g_fSkillBonus) { + g_esTeam[team].fSkillGainBonus = g_esTeam[team].fSkillGainBonus + g_f10Percent >= g_fSkillBonus ? g_fSkillBonus : g_esTeam[team].fSkillGainBonus + g_f10Percent; + } +} + +public void OnWitchCrownHurt(int survivor, int damage, int chipdamage) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (g_esTeam[team].fSkillGainBonus < g_fSkillBonus) { + g_esTeam[team].fSkillGainBonus = g_esTeam[team].fSkillGainBonus + g_f10Percent >= g_fSkillBonus ? g_fSkillBonus : g_esTeam[team].fSkillGainBonus + g_f10Percent; + } +} + +public void OnTongueCut(int survivor, int smoker) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (g_esTeam[team].fSkillGainBonus < g_fSkillBonus) { + g_esTeam[team].fSkillGainBonus = g_esTeam[team].fSkillGainBonus + g_f5Percent >= g_fSkillBonus ? g_fSkillBonus : g_esTeam[team].fSkillGainBonus + g_f5Percent; + } +} + +public void OnHunterHighPounce(int hunter, int survivor, int actualDamage, float calculatedDamage, float height, bool reportedHigh) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (actualDamage > 19) { + if (g_esTeam[team].fSkillGainBonus >= g_f10Percent) { + g_esTeam[team].fSkillGainBonus -= g_f10Percent; + } else { + g_esTeam[team].fSkillGainBonus = 0.0; + } + } +} + +public void OnDeathCharge(int charger, int survivor, float height, float distance, bool wasCarried) +{ + if (g_bRoundOver) { + return; + } + + int team = InSecondHalfOfRound(); + if (g_esTeam[team].fSkillGainBonus >= g_f20Percent) { + g_esTeam[team].fSkillGainBonus -= g_f20Percent; + } else { + g_esTeam[team].fSkillGainBonus = 0.0; + } +} + +stock bool IsAnyInfected(int entity) +{ + if (entity > 0 && entity <= MaxClients) { + return IsClientInGame(entity) && GetClientTeam(entity) == 3; + } else if (entity > MaxClients) { + char classname[64]; + GetEdictClassname(entity, classname, sizeof(classname)); + if (StrEqual(classname, "infected") || StrEqual(classname, "witch")) { + return true; + } + } + + return false; +} + +/*---------------------------------------------- +-------------------- ConVars ------------------- +----------------------------------------------*/ +ConVar CreateConVarHook(const char[] name, const char[] defaultValue, const char[] description = "", + int flags = 0, bool hasMin = false, float min = 0.0, bool hasMax = false, float max = 0.0, ConVarChanged callback) { + ConVar cv = CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); + + Call_StartFunction(INVALID_HANDLE, callback); + Call_PushCell(cv); + Call_PushNullString(); + Call_PushNullString(); + Call_Finish(); + + cv.AddChangeHook(callback); + + return cv; +} + +void OnPHBChange(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_fPermHealthBonusRate = convar.FloatValue; +} + +void OnIBRChange(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_fDamageBonusRate = convar.FloatValue; +} + +void OnSBRChange(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_fSkillBonusRate = convar.FloatValue; +} + +void OnPBRChange(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_fPillsBonusRate = convar.FloatValue; +} + +void OnCBRChange(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_fConditionBonusRate = convar.FloatValue; +} \ No newline at end of file From f5920a9deb4e65e4a1cb94a05fdff298f6d5e868 Mon Sep 17 00:00:00 2001 From: cy115 <1157804552@qq.com> Date: Sat, 9 May 2026 18:58:03 +0800 Subject: [PATCH 2/2] Try new socremod --- cfg/cfgogl/zonemod/shared_plugins.cfg | 2 +- cfg/cfgogl/zonemod/shared_settings.cfg | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cfg/cfgogl/zonemod/shared_plugins.cfg b/cfg/cfgogl/zonemod/shared_plugins.cfg index 62a9f4d76..11938b3c2 100644 --- a/cfg/cfgogl/zonemod/shared_plugins.cfg +++ b/cfg/cfgogl/zonemod/shared_plugins.cfg @@ -86,7 +86,7 @@ sm plugins load optional/boomer_horde_equalizer_refactored.smx sm plugins load optional/l4d2_bw_rock_hit.smx sm plugins load optional/l4d2_tank_damage_cvars.smx sm plugins load optional/l4d2_getup_slide_fix.smx -sm plugins load optional/l4d2_hybrid_scoremod_zone.smx +sm plugins load optional/l4d2_new_generation_scoremod.smx sm plugins load optional/l4d2_uncommon_blocker.smx sm plugins load optional/fix_engine.smx sm plugins load optional/l4d2_collision_adjustments.smx diff --git a/cfg/cfgogl/zonemod/shared_settings.cfg b/cfg/cfgogl/zonemod/shared_settings.cfg index eea14f96b..051546ca0 100644 --- a/cfg/cfgogl/zonemod/shared_settings.cfg +++ b/cfg/cfgogl/zonemod/shared_settings.cfg @@ -286,12 +286,6 @@ confogl_addcvar sm_max_lerp 0.067 // [starting_items.smx] confogl_addcvar starting_item_flags 4 -// [l4d2_hybrid_scoremod.smx] -confogl_addcvar sm2_bonus_per_survivor_multiplier 0.5 -confogl_addcvar sm2_permament_health_proportion 0.75 -confogl_addcvar sm2_pills_hp_factor 4.0 -confogl_addcvar sm2_pills_max_bonus 100 - // [l4d2_tank_horde_monitor.smx] confogl_addcvar l4d2_tank_bypass_extra_flow 1500