This commit is contained in:
Jackzie 2024-01-05 19:48:05 -06:00
parent 206cebac14
commit 34dda38547
8 changed files with 60 additions and 146 deletions

View file

@ -22,17 +22,6 @@ char PRECACHE_SOUNDS[PRECACHE_SOUNDS_COUNT][] = {
#include <multicolors>
#include "l4d_survivor_identity_fix.inc"
char ReserveLevels[4][] = {
"Public", "Watch", "Admin-Only", "Private"
};
enum ReserveMode {
Reserve_None = 0,
Reserve_Watch,
Reserve_AdminOnly,
Reserve_Private
}
char MODELS[8][] = {
"models/survivors/survivor_gambler.mdl",
"models/survivors/survivor_producer.mdl",
@ -58,7 +47,6 @@ enum L4DModelId {
static ArrayList LasersUsed;
static ConVar hLaserNotice, hFinaleTimer, hFFNotice, hPingDropThres, hForceSurvivorSet, hPlayerLimit, hSVMaxPlayers, hHideMotd, hGamemode;
static int iFinaleStartTime, botDropMeleeWeapon[MAXPLAYERS+1], iHighPingCount[MAXPLAYERS+1];
ReserveMode reserveMode;
static bool isHighPingIdle[MAXPLAYERS+1], isL4D1Survivors;
static Handle hGoAwayFromKeyboard;
static StringMap SteamIDs;
@ -114,7 +102,6 @@ public void OnPluginStart() {
hSVMaxPlayers.IntValue = hPlayerLimit.IntValue;
}
hFFNotice.AddChangeHook(CVC_FFNotice);
if(hFFNotice.IntValue > 0) {
HookEvent("player_hurt", Event_PlayerHurt);
@ -160,9 +147,6 @@ public void OnPluginStart() {
RegAdminCmd("sm_playsound", Command_PlaySound, ADMFLAG_KICK, "Plays a gamesound for player");
RegAdminCmd("sm_stopsound", Command_StopSound, ADMFLAG_GENERIC, "Stops the last played gamesound for player");
RegAdminCmd("sm_swap", Command_SwapPlayer, ADMFLAG_KICK, "Swarms two player's locations");
RegAdminCmd("sm_perm", Command_SetServerPermissions, ADMFLAG_KICK, "Sets the server's permissions.");
RegAdminCmd("sm_perms", Command_SetServerPermissions, ADMFLAG_KICK, "Sets the server's permissions.");
RegAdminCmd("sm_permissions", Command_SetServerPermissions, ADMFLAG_KICK, "Sets the server's permissions.");
RegConsoleCmd("sm_pmodels", Command_ListClientModels, "Lists all player's models");
RegAdminCmd("sm_skipoutro", Command_SkipOutro, ADMFLAG_KICK, "Skips the outro");
@ -179,82 +163,6 @@ void Event_PlayerLimitChange(ConVar cvar, const char[] oldValue, const char[] ne
}
}
public void OnClientConnected(int client) {
if(!IsFakeClient(client) && reserveMode == Reserve_Watch) {
PrintChatToAdmins("%N is connecting", client);
}
}
// Returns -1 if not allowed, or their previous index
int GetAllowedPlayerIndex(const char[] authid2) {
int index;
return SteamIDs.GetValue(authid2, index) ? index : -1;
}
public void OnClientPostAdminCheck(int client) {
if(!IsFakeClient(client)) {
if(reserveMode == Reserve_AdminOnly && GetUserAdmin(client) == INVALID_ADMIN_ID) {
char auth[32];
GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth));
if(GetAllowedPlayerIndex(auth) == -1) {
KickClient(client, "Sorry, server is reserved");
return;
}
}
}
}
public void OnClientAuthorized(int client, const char[] auth) {
if(IsFakeClient(client)) return;
if(reserveMode == Reserve_Private) {
if(GetAllowedPlayerIndex(auth) == -1) {
KickClient(client, "Sorry, server is reserved");
}
}
// Don't insert id here if admin only, let admin check do that
if(reserveMode != Reserve_AdminOnly) {
SteamIDs.SetValue(auth, client);
}
}
Action Command_SetServerPermissions(int client, int args) {
if(args > 0) {
char arg1[32];
GetCmdArg(1, arg1, sizeof(arg1));
if(StrEqual(arg1, "public", false)) {
reserveMode = Reserve_None;
} else if(StrContains(arg1, "noti", false) > -1 || StrContains(arg1, "watch", false) > -1) {
reserveMode = Reserve_Watch;
} else if(StrContains(arg1, "admin", false) > -1) {
reserveMode = Reserve_AdminOnly;
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i)) {
GetClientAuthId(i, AuthId_Steam2, arg1, sizeof(arg1));
SteamIDs.SetValue(arg1, i);
}
}
} else if(StrEqual(arg1, "private", false)) {
reserveMode = Reserve_Private;
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i)) {
GetClientAuthId(i, AuthId_Steam2, arg1, sizeof(arg1));
SteamIDs.SetValue(arg1, i);
}
}
} else {
ReplyToCommand(client, "Usage: sm_reserve [public/notify/admin/private] or no arguments to view current reservation.");
return Plugin_Handled;
}
PrintChatToAdmins("Server access changed to %s", ReserveLevels[reserveMode]);
} else {
ReplyToCommand(client, "Server access level is currently %s", ReserveLevels[reserveMode]);
}
return Plugin_Handled;
}
Action Timer_CheckPlayerPings(Handle timer) {
if(StrEqual(gamemode, "hideandseek")) return Plugin_Continue;
if(hPingDropThres.IntValue != 0) {

View file

@ -106,7 +106,7 @@ void Director_OnMapEnd() {
}
void Cvar_SpecialSpawningChange(ConVar convar, const char[] oldValue, const char[] newValue) {
if(convar.IntValue & 2 && IsEPIActive()) {
if(convar.IntValue & 2) {
if(witchSpawnTimer == null)
witchSpawnTimer = CreateTimer(DIRECTOR_WITCH_CHECK_TIME, Timer_DirectorWitch, _, TIMER_REPEAT);
} else {
@ -165,6 +165,8 @@ void OnTankBotSpawn(int client) {
if(g_finaleStage == Stage_Active) {
// 1st tank spawned
PrintDebug(DEBUG_SPAWNLOGIC, "OnTankBotSpawn: [FINALE] 1st tank spawned");
int health = CalculateExtraTankHealth(client);
SetEntProp(client, Prop_Send, "m_iHealth", health);
g_finaleStage = Stage_FirstTankSpawned;
return;
} else if(g_realSurvivorCount < 6 && g_finaleStage == Stage_FirstTankSpawned) {
@ -173,6 +175,8 @@ void OnTankBotSpawn(int client) {
float duration = GetRandomFloat(EXTRA_TANK_MIN_SEC, EXTRA_TANK_MAX_SEC);
// Pass it 0, which doesnt make it a split tank, has default health
CreateTimer(duration, Timer_SpawnSplitTank, 0);
int health = CalculateExtraTankHealth(client);
SetEntProp(client, Prop_Send, "m_iHealth", health);
g_finaleStage = Stage_SecondTankSpawned;
return;
}
@ -186,9 +190,7 @@ void OnTankBotSpawn(int client) {
}
// This should not run on active finales (different than finale maps, such as swamp fever's, where finale isnt full map)
// Normal tank (not stage 2 / not secondary tank) spawned. Set its health and spawn split tank
int health = GetEntProp(client, Prop_Send, "m_iHealth");
float additionalHealth = float(g_survivorCount - 4) * cvEPITankHealth.FloatValue;
health += RoundFloat(additionalHealth);
int health = CalculateExtraTankHealth(client);
/* Split tank can only spawn if:
(1) not finale
@ -207,7 +209,13 @@ void OnTankBotSpawn(int client) {
PrintDebug(DEBUG_SPAWNLOGIC, "OnTankBotSpawn: Setting tank health to %d", health);
SetEntProp(client, Prop_Send, "m_iHealth", health);
}
}
int CalculateExtraTankHealth(int client) {
int health = GetEntProp(client, Prop_Send, "m_iHealth");
float additionalHealth = float(g_survivorCount - 4) * cvEPITankHealth.FloatValue;
health += RoundFloat(additionalHealth);
return health;
}
Action Timer_SpawnSplitTank(Handle h, int health) {
@ -283,6 +291,9 @@ void InitExtraWitches() {
void Director_PrintDebug(int client) {
PrintToConsole(client, "State: %s(%d)", DIRECTOR_STATE[g_lastState], g_lastState);
float eCount = float(g_survivorCount - 3);
float chance = (eCount - float(g_infectedCount)) / eCount;
PrintToConsole(client, "Player Scale Chance: %f%%", chance * 100.0);
PrintToConsole(client, "Map Bounds: [%f, %f]", FLOW_CUTOFF, L4D2Direct_GetMapMaxFlowDistance() - (FLOW_CUTOFF*2.0));
PrintToConsole(client, "Total Witches Spawned: %d | Target: %d", g_spawnCount[Special_Witch], g_extraWitchCount);
for(int i = 0; i < g_extraWitchCount && i < DIRECTOR_WITCH_MAX_WITCHES; i++) {
@ -435,6 +446,7 @@ Action Timer_Director(Handle h) {
Action Timer_DirectorWitch(Handle h) {
// TODO: instead of +1, do it when director spawned a witch
if(!IsEPIActive()) return Plugin_Continue;
if(g_spawnCount[Special_Witch] < g_extraWitchCount + 1) { //&& time - g_lastSpawnTimes.witch > DIRECTOR_WITCH_MIN_TIME
for(int i = 0; i <= g_extraWitchCount; i++) {
if(g_extraWitchFlowPositions[i] > 0.0 && g_highestFlowAchieved >= g_extraWitchFlowPositions[i]) {
@ -443,12 +455,13 @@ Action Timer_DirectorWitch(Handle h) {
int target = L4D_GetHighestFlowSurvivor();
if(!target) return Plugin_Continue;
DirectorSpawn(Special_Witch, target);
break;
}
}
}
return Plugin_Continue;
}
}
}
witchSpawnTimer = null;
return Plugin_Stop;
}
// UTIL functions
void DirectorSpawn(specialType special, int player = -1) {

View file

@ -145,19 +145,19 @@ void OnPortalTouch(const char[] output, int caller, int activator, float delay)
#endif
}
stock int StartPropCreate(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
stock int StartPropCreate(const char[] entClass, const char[] model, const float pos[3], const float ang[3] = NULL_VECTOR, const float vel[3] = NULL_VECTOR) {
int entity = CreateEntityByName(entClass);
if(entity == -1) return -1;
DispatchKeyValue(entity, "model", model);
DispatchKeyValue(entity, "solid", "6");
DispatchKeyValue(entity, "targetname", ENT_PROP_NAME);
DispatchKeyValue(entity, "disableshadows", "1");
TeleportEntity(entity, pos, ang, NULL_VECTOR);
TeleportEntity(entity, pos, ang, vel);
return entity;
}
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3]) {
int entity = StartPropCreate(entClass, model, pos, ang);
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3] = NULL_VECTOR, const float vel[3] = NULL_VECTOR) {
int entity = StartPropCreate(entClass, model, pos, ang, vel);
if(DispatchSpawn(entity)) {
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn prop %.1f %.1f %.1f model %s", pos[0], pos[1], pos[2], model[7]);

View file

@ -377,7 +377,10 @@ Action Command_DoAHat(int client, int args) {
PrintToConsole(client, "[Hats] Selected a child entity, selecting parent (child %d -> parent %d)", entity, parent);
entity = parent;
} else if(entity <= MaxClients) { // Checks for hatting a player entity
if(GetClientTeam(entity) != 2 && ~cvar_sm_hats_flags.IntValue & view_as<int>(HatConfig_InfectedHats)) {
if(IsFakeClient(entity)) {
PrintToChat(client, "[Hats] Cannot hat bots");
return Plugin_Handled;
} else if(GetClientTeam(entity) != 2 && ~cvar_sm_hats_flags.IntValue & view_as<int>(HatConfig_InfectedHats)) {
PrintToChat(client, "[Hats] Cannot make enemy a hat... it's dangerous");
return Plugin_Handled;
} else if(entity == EntRefToEntIndex(WallBuilder[client].entity)) {

View file

@ -340,7 +340,7 @@ Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, float& dam
else if(pData[victim].underAttack) return Plugin_Continue;
// Is damage not caused by fire or pipebombs?
bool isDamageDirect = true; //(damagetype & DMG_BURN) == 0;
bool isDamageDirect = (~damagetype & DMG_BURN) != 0;
// Forgive player teamkill based on threshold, resetting accumlated damage
if(time - pData[attacker].lastFFTime > hForgivenessTime.IntValue) {
@ -587,10 +587,10 @@ Action Command_IgnorePlayer(int client, int args) {
if (flags & Immune_TK) {
if (pData[target].immunityFlags & Immune_TK) {
LogAction(client, target, "\"%L\" re-enabled teamkiller detection for \"%L\"", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N has re-enabled teamkiller detection for {olive}%N", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N{default} has re-enabled teamkiller detection for {olive}%N", client, target);
} else {
LogAction(client, target, "\"%L\" ignored teamkiller detection for \"%L\"", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N has ignored teamkiller detection for {olive}%N", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N{default} has ignored teamkiller detection for {olive}%N", client, target);
}
pData[target].immunityFlags ^= Immune_TK;
}
@ -598,9 +598,10 @@ Action Command_IgnorePlayer(int client, int args) {
if (flags & Immune_RFF) {
if (pData[target].immunityFlags & Immune_RFF) {
LogAction(client, target, "\"%L\" re-enabled auto reverse friendly-fire for \"%L\"", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N{default} has enabled auto reverse friendly-fire for {olive}%N", client, target);
} else {
LogAction(client, target, "\"%L\" disabled auto reverse friendly-fire for \"%L\"", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N has disabled auto reverse friendly-fire for {olive}%N", client, target);
CShowActivity2(client, "[FTT] ", "{yellow}%N{default} has disabled auto reverse friendly-fire for {olive}%N", client, target);
pData[target].autoRFFScaleFactor = 0.0;
}
pData[target].immunityFlags ^= Immune_RFF;

View file

@ -305,7 +305,7 @@ public void OnPluginStart() {
hEPIHudState = CreateConVar("epi_hudstate", "1", "Controls when the hud displays.\n0 -> OFF, 1 = When 5+ players, 2 = ALWAYS", FCVAR_NONE, true, 0.0, true, 3.0);
hExtraFinaleTank = CreateConVar("epi_extra_tanks", "3", "Add bits together. 0 = Normal tank spawning, 1 = 50% tank split on non-finale (half health), 2 = Tank split (full health) on finale ", FCVAR_NONE, true, 0.0, true, 3.0);
hExtraTankThreshold = CreateConVar("epi_extra_tanks_min_players", "6", "The minimum number of players for extra tanks to spawn. When disabled, normal 5+ tank health applies", FCVAR_NONE, true, 0.0);
hSplitTankChance = CreateConVar("epi_splittank_chance", "0.75", "The % chance of a split tank occurring in non-finales", FCVAR_NONE, true, 0.0, true, 1.0);
hSplitTankChance = CreateConVar("epi_splittank_chance", "0.65", "The % chance of a split tank occurring in non-finales", FCVAR_NONE, true, 0.0, true, 1.0);
cvDropDisconnectTime = CreateConVar("epi_disconnect_time", "120.0", "The amount of seconds after a player has actually disconnected, where their character slot will be void. 0 to disable", FCVAR_NONE, true, 0.0);
cvFFDecreaseRate = CreateConVar("epi_ff_decrease_rate", "0.3", "The friendly fire factor is subtracted from the formula (playerCount-4) * this rate. Effectively reduces ff penalty when more players. 0.0 to subtract none", FCVAR_NONE, true, 0.0);
cvEPIHudFlags = CreateConVar("epi_hud_flags", "3", "Add together.\n1 = Scrolling hud, 2 = Show ping", FCVAR_NONE, true, 0.0);
@ -1181,20 +1181,36 @@ int SpawnItem(const char[] itemName, float pos[3], float ang[3] = NULL_VECTOR) {
return spawner;
}
void IncreaseKits() {
void IncreaseKits(bool inFinale) {
float pos[3];
int entity = FindEntityByClassname(-1, "weapon_first_aid_kit_spawn");
if(entity == INVALID_ENT_REFERENCE) {
PrintToServer("[EPI] Warn: No kit spawns (weapon_first_aid_kit_spawn) found");
PrintToServer("[EPI] Warn: No kit spawns (weapon_first_aid_kit_spawn) found (inFinale=%b)", inFinale);
return;
}
int count = 0;
while(g_extraKitsAmount > 0) {
GetEntPropVector(entity, Prop_Data, "m_vecOrigin", pos);
if(L4D_IsPositionInLastCheckpoint(pos)) {
bool result = false;
if(inFinale) {
// Finale
Address address = L4D_GetNearestNavArea(pos);
if(address != Address_Null) {
int attributes = L4D_GetNavArea_SpawnAttributes(address);
if(attributes & NAV_SPAWN_FINALE) {
result = true;
}
}
} else {
// Checkpoint
result = L4D_IsPositionInLastCheckpoint(pos);
}
if(result) {
count++;
// Give it a little chance to nudge itself
pos[2] += 0.3;
pos[0] += GetRandomFloat(-8.0, 8.0);
pos[1] += GetRandomFloat(-8.0, 8.0);
pos[2] += 0.4;
SpawnItem("first_aid_kit", pos);
g_extraKitsAmount--;
}
@ -1204,41 +1220,13 @@ void IncreaseKits() {
entity = -1;
// If we did not find any suitable kits, stop here.
if(count == 0) {
PrintToServer("[EPI] Warn: No valid kit spawns (weapon_first_aid_kit_spawn) found (inFinale=%b)", inFinale);
break;
}
}
}
}
void IncreaseFinaleKits() {
float pos[3];
int entity = -1;
int spawnCount = g_survivorCount - 4;
int count = 0;
PrintDebug(DEBUG_SPAWNLOGIC, "Spawning %d finale kits", spawnCount);
while(spawnCount > 0) {
GetEntPropVector(entity, Prop_Data, "m_vecOrigin", pos);
Address address = L4D_GetNearestNavArea(pos);
if(address != Address_Null) {
int attributes = L4D_GetNavArea_SpawnAttributes(address);
if(attributes & NAV_SPAWN_FINALE) {
count++;
pos[2] += 0.3;
SpawnItem("first_aid_kit", pos);
spawnCount--;
}
}
entity = FindEntityByClassname(entity, "weapon_first_aid_kit_spawn");
// Loop around
if(entity == INVALID_ENT_REFERENCE) {
entity = -1;
// If we did not find any suitable kits, stop here.
if(count == 0) {
break;
}
}
}
}
char NAV_SPAWN_NAMES[32][] = {
"EMPTY",
@ -1303,7 +1291,7 @@ public void OnMapStart() {
}
if(L4D_IsMissionFinalMap()) {
IncreaseFinaleKits();
IncreaseKits(true);
// Disable tank split on hard rain finale
g_extraFinaleTankEnabled = true;
if(StrEqual(map, "c4m5_milltown_escape")) {
@ -1394,7 +1382,7 @@ public void EntityOutput_OnStartTouchSaferoom(const char[] output, int caller, i
UpdateSurvivorCount();
if(IsEPIActive()) {
SetExtraKits(g_survivorCount);
IncreaseKits();
IncreaseKits(false);
PrintToServer("[EPI] Player entered saferoom. Extra Kits: %d", g_extraKitsAmount);
}
}

View file

@ -413,9 +413,10 @@ public void OnClientDisconnect(int client) {
}
public Action OnTakeDamageAlive(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) {
// TODO: see if DMG_ENERGYBEAM
if(attacker > MaxClients && attacker < 2048 && turretIsActiveLaser[attacker] && GetClientTeam(victim) != 3) {
int health = L4D_GetPlayerTempHealth(victim);
L4D_SetPlayerTempHealth(victim, health);
L4D_SetPlayerTempHealth(victim, health + 1.0);
damage = 0.0;
return Plugin_Stop;
}

View file

@ -140,7 +140,7 @@ float g_fBenchAvg;
float g_iBenchTicks;
#endif
#define CVAR_FLAGS FCVAR_NOTIFY
#define CVAR_FLAGS FCVAR_NONE
#define MINIMUM_RANGE 1500.0 // Minimum range for last and lead cvars.
#define EVENTS_CONFIG "data/l4d_anti_rush.cfg"