mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-07 16:53:21 +00:00
update
This commit is contained in:
parent
3c88c010ad
commit
3a26dffd7a
10 changed files with 214 additions and 141 deletions
|
@ -74,15 +74,24 @@ public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroa
|
|||
}
|
||||
public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0 && g_iAttackerTarget[client] > 0) {
|
||||
int target = GetClientOfUserId(g_iAttackerTarget[client]);
|
||||
gInstaSpecialMagnet[target]--;
|
||||
if(gInstaSpecialMagnet[target] == 0) {
|
||||
PrintToServer("[FTT] gInstaSpecialMagnet dropped below 0");
|
||||
gInstaSpecialMagnet[target] = 0;
|
||||
if(client > 0) {
|
||||
if(g_iAttackerTarget[client] > 0) {
|
||||
int target = GetClientOfUserId(g_iAttackerTarget[client]);
|
||||
gInstaSpecialMagnet[target]--;
|
||||
if(gInstaSpecialMagnet[target] == 0) {
|
||||
PrintToServer("[FTT] gInstaSpecialMagnet dropped below 0");
|
||||
gInstaSpecialMagnet[target] = 0;
|
||||
}
|
||||
g_iAttackerTarget[client] = 0;
|
||||
} else {
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(g_iAttackerTarget[i] == client) {
|
||||
g_iAttackerTarget[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_iAttackerTarget[client] = 0;
|
||||
}
|
||||
public Action Event_WeaponReload(int weapon) {
|
||||
int client = GetEntPropEnt(weapon, Prop_Send, "m_hOwner");
|
||||
|
@ -136,7 +145,7 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
|||
} else if(class == L4D2Infected_Tank && (!IsPlayerIncapped(existingTarget) || hMagnetTargetMode.IntValue & 2) && WillMagnetRun(Trolls[tankMagnetID], existingTarget)) {
|
||||
curTarget = existingTarget;
|
||||
return Plugin_Changed;
|
||||
}else if((!IsPlayerIncapped(existingTarget) || hMagnetTargetMode.IntValue & 1) && WillMagnetRun(Trolls[spMagnetID], existingTarget)) {
|
||||
}else if(class != L4D2Infected_Tank && (!IsPlayerIncapped(existingTarget) || hMagnetTargetMode.IntValue & 1) && WillMagnetRun(Trolls[spMagnetID], existingTarget)) {
|
||||
curTarget = existingTarget;
|
||||
return Plugin_Changed;
|
||||
}
|
||||
|
@ -148,16 +157,13 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
|||
int closestClient = -1;
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) {
|
||||
//Ignore incapped players if turned on:
|
||||
|
||||
|
||||
if(class == L4D2Infected_Tank && Trolls[tankMagnetID].IsActive(i) || (class != L4D2Infected_Tank && Trolls[spMagnetID].IsActive(i))) {
|
||||
if(class == L4D2Infected_Tank) {
|
||||
if(!WillMagnetRun(Trolls[tankMagnetID], i)) return Plugin_Continue;
|
||||
} else if(!WillMagnetRun(Trolls[spMagnetID], i)) return Plugin_Continue;
|
||||
if(!WillMagnetRun(Trolls[tankMagnetID], i)) continue;
|
||||
} else if(!WillMagnetRun(Trolls[spMagnetID], i)) continue;
|
||||
|
||||
if(IsPlayerIncapped(i)) {
|
||||
if((class == L4D2Infected_Tank && hMagnetTargetMode.IntValue & 2) || (class != L4D2Infected_Tank && hMagnetTargetMode.IntValue & 1)) continue;
|
||||
if((class == L4D2Infected_Tank && hMagnetTargetMode.IntValue & 2 == 0) || (class != L4D2Infected_Tank && hMagnetTargetMode.IntValue & 1 == 0)) continue;
|
||||
}
|
||||
|
||||
GetClientAbsOrigin(i, survPos);
|
||||
|
@ -173,6 +179,7 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
|||
if(closestClient > 0) {
|
||||
g_iAttackerTarget[attacker] = GetClientUserId(closestClient);
|
||||
curTarget = closestClient;
|
||||
PrintToConsoleAll("[FTT] New target for %d: %N", attacker, curTarget);
|
||||
return Plugin_Changed;
|
||||
}
|
||||
return Plugin_Continue;
|
||||
|
@ -475,7 +482,7 @@ public Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float&
|
|||
//Stop FF from marked:
|
||||
static int reverseFF;
|
||||
if(reverseFF == 0) reverseFF = GetTrollID("Reverse FF");
|
||||
if(GetClientTeam(attacker) == 4 && IsFakeClient(attacker)) return Plugin_Stop;
|
||||
if(attacker > 0 && attacker <= MaxClients && GetClientTeam(attacker) == 4 && IsFakeClient(attacker)) return Plugin_Stop;
|
||||
if(attacker > 0 && victim <= MaxClients && attacker <= MaxClients && IsClientInGame(attacker) && IsPlayerAlive(attacker)) {
|
||||
if(shootAtTarget[attacker] == victim) return Plugin_Continue;
|
||||
if(g_PendingBanTroll[attacker] > 0 && GetClientTeam(attacker) == 2 && GetClientTeam(victim) == 2) {
|
||||
|
|
|
@ -51,9 +51,9 @@ public void OnPluginStart() {
|
|||
hSuicideAction = CreateConVar("l4d2_suicide_action", "3", "How should a suicider be punished?\n0 = No action (No message), 1 = Kick, 2 = Instant Ban, 3 = Ban on disconnect", FCVAR_NONE, true, 0.0, true, 3.0);
|
||||
hSuicideLimit = CreateConVar("l4d2_suicide_limit", "1", "How many attempts does a new joined player have until action is taken for suiciding?", FCVAR_NONE, true, 0.0);
|
||||
// Reverse FF Auto Scale
|
||||
hFFAutoScaleAmount = CreateConVar("l4d2_tk_auto_ff_rate", "0.01", "The rate at which auto reverse-ff is scaled by.", FCVAR_NONE, true, 0.0);
|
||||
hFFAutoScaleAmount = CreateConVar("l4d2_tk_auto_ff_rate", "0.02", "The rate at which auto reverse-ff is scaled by.", FCVAR_NONE, true, 0.0);
|
||||
hFFAutoScaleMaxRatio = CreateConVar("l4d2_tk_auto_ff_max_ratio", "5.0", "The maximum amount that the reverse ff can go. 0.0 for unlimited", FCVAR_NONE, true, 0.0);
|
||||
hFFAutoScaleForgivenessAmount = CreateConVar("l4d2_tk_auto_ff_forgive_rate", "0.02", "This amount times amount of minutes since last ff is removed from ff rate", FCVAR_NONE, true, 0.0);
|
||||
hFFAutoScaleForgivenessAmount = CreateConVar("l4d2_tk_auto_ff_forgive_rate", "0.03", "This amount times amount of minutes since last ff is removed from ff rate", FCVAR_NONE, true, 0.0);
|
||||
hFFAutoScaleIgnoreAdmins = CreateConVar("l4d2_tk_auto_ff_ignore_admins", "1", "Should automatic reverse ff ignore admins? 0 = Admins are subjected\n1 = Admins are excempt", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
|
||||
AutoExecConfig(true, "l4d2_tkstopper");
|
||||
|
@ -186,7 +186,7 @@ public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroa
|
|||
public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, float& damage, int& damagetype, int& weapon, float damageForce[3], float damagePosition[3]) {
|
||||
if(damage > 0.0 && victim <= MaxClients && attacker <= MaxClients && attacker > 0 && victim > 0 && attacker != victim) {
|
||||
if(GetClientTeam(victim) != GetClientTeam(attacker) || attacker == victim) return Plugin_Continue;
|
||||
else if(damagetype & DMG_BURN && IsFakeClient(attacker)) {
|
||||
else if(damagetype & DMG_BURN && IsFakeClient(attacker) && GetClientTeam(attacker) == 2) {
|
||||
// Ignore damage from fire caused by bots (players who left after causing fire)
|
||||
damage = 0.0;
|
||||
return Plugin_Changed;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define DEBUG_LEVEL DEBUG_GENERIC
|
||||
#define EXTRA_PLAYER_HUD_UPDATE_INTERVAL 0.8
|
||||
//Sets abmExtraCount to this value if set
|
||||
// #define DEBUG_FORCE_PLAYERS 5
|
||||
// #define DEBUG_FORCE_PLAYERS 7
|
||||
|
||||
#define PLUGIN_VERSION "1.0"
|
||||
|
||||
|
@ -71,15 +71,21 @@ public Plugin myinfo =
|
|||
url = ""
|
||||
};
|
||||
|
||||
static ConVar hExtraItemBasePercentage, hAddExtraKits, hMinPlayers, hUpdateMinPlayers, hMinPlayersSaferoomDoor, hSaferoomDoorWaitSeconds, hSaferoomDoorAutoOpen, hEPIHudState, hExtraFinaleTank;
|
||||
static ConVar hExtraItemBasePercentage, hAddExtraKits, hMinPlayers, hUpdateMinPlayers, hMinPlayersSaferoomDoor, hSaferoomDoorWaitSeconds, hSaferoomDoorAutoOpen, hEPIHudState, hExtraFinaleTank, cvDropDisconnectTime;
|
||||
static int extraKitsAmount, extraKitsStarted, abmExtraCount, firstSaferoomDoorEntity, playersLoadedIn, playerstoWaitFor;
|
||||
static int isBeingGivenKit[MAXPLAYERS+1];
|
||||
static int finaleStage;
|
||||
static bool isCheckpointReached, isLateLoaded, firstGiven, isFailureRound;
|
||||
static ArrayList ammoPacks;
|
||||
static Handle updateHudTimer;
|
||||
static char gamemode[32];
|
||||
|
||||
enum struct PlayerData {
|
||||
bool itemGiven; //Is player being given an item (such that the next pickup event is ignored)
|
||||
bool isUnderAttack; //Is the player under attack (by any special)
|
||||
bool active;
|
||||
}
|
||||
|
||||
PlayerData playerData[MAXPLAYERS+1];
|
||||
|
||||
static StringMap weaponMaxClipSizes;
|
||||
|
||||
static char HUD_SCRIPT[] = "ExtraPlayerHUD <- { Fields = { players = { slot = g_ModeScript.HUD_RIGHT_BOT, dataval = \"%s\", flags = g_ModeScript.HUD_FLAG_ALIGN_LEFT | g_ModeScript.HUD_FLAG_TEAM_SURVIVORS | g_ModeScript.HUD_FLAG_NOBG } } }; HUDSetLayout( ExtraPlayerHUD ); HUDPlace( g_ModeScript.HUD_RIGHT_BOT, 0.72, 0.78, 0.3, 0.3 ); g_ModeScript";
|
||||
|
@ -89,9 +95,10 @@ enum struct Cabinet {
|
|||
int id;
|
||||
int items[CABINET_ITEM_BLOCKS];
|
||||
}
|
||||
|
||||
static Cabinet cabinets[10]; //Store 10 cabinets
|
||||
|
||||
//// Definitions complete
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) {
|
||||
if(late) isLateLoaded = true;
|
||||
return APLRes_Success;
|
||||
|
@ -118,6 +125,24 @@ public void OnPluginStart() {
|
|||
HookEvent("round_freeze_end", Event_RoundFreezeEnd);
|
||||
HookEvent("tank_spawn", Event_TankSpawn);
|
||||
|
||||
//Special Event Tracking
|
||||
HookEvent("player_disconnect", Event_PlayerDisconnect);
|
||||
|
||||
HookEvent("charger_carry_start", Event_ChargerCarry);
|
||||
HookEvent("charger_carry_end", Event_ChargerCarry);
|
||||
|
||||
HookEvent("lunge_pounce", Event_HunterPounce);
|
||||
HookEvent("pounce_end", Event_HunterPounce);
|
||||
HookEvent("pounce_stopped", Event_HunterPounce);
|
||||
|
||||
HookEvent("choke_start", Event_SmokerChoke);
|
||||
HookEvent("choke_end", Event_SmokerChoke);
|
||||
HookEvent("choke_stopped", Event_SmokerChoke);
|
||||
|
||||
HookEvent("jockey_ride", Event_JockeyRide);
|
||||
HookEvent("jockey_ride_end", Event_JockeyRide);
|
||||
|
||||
|
||||
hExtraItemBasePercentage = CreateConVar("l4d2_extraitems_chance", "0.056", "The base chance (multiplied by player count) of an extra item being spawned.", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
hAddExtraKits = CreateConVar("l4d2_extraitems_kitmode", "0", "Decides how extra kits should be added.\n0 -> Overwrites previous extra kits, 1 -> Adds onto previous extra kits", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
hUpdateMinPlayers = CreateConVar("l4d2_extraitems_updateminplayers", "1", "Should the plugin update abm\'s cvar min_players convar to the player count?\n 0 -> NO, 1 -> YES", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
|
@ -126,6 +151,7 @@ public void OnPluginStart() {
|
|||
hSaferoomDoorAutoOpen = CreateConVar("l4d2_extraitems_doorunlock_open", "0", "Controls when the door automatically opens after unlocked. Add bits together.\n0 = Never, 1 = When timer expires, 2 = When all players loaded in", FCVAR_NONE, true, 0.0);
|
||||
hEPIHudState = CreateConVar("l4d2_extraitems_hudstate", "1", "Controls when the hud displays.\n0 -> OFF, 1 = When 5+ players, 2 = ALWAYS", FCVAR_NONE, true, 0.0, true, 2.0);
|
||||
hExtraFinaleTank = CreateConVar("l4d2_extraitems_extra_finale_tank", "1", "0 = Normal tank spawning, 1 = Two tanks spawn on second stage (half health)", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
cvDropDisconnectTime = CreateConVar("l4d2_extraitems_disconnect_time", "120", "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);
|
||||
|
||||
hEPIHudState.AddChangeHook(Cvar_HudStateChange);
|
||||
|
||||
|
@ -172,6 +198,40 @@ public void OnPluginStart() {
|
|||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Special Infected Events
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
public Action Event_ChargerCarry(Event event, const char[] name, bool dontBroadcast) {
|
||||
int victim = GetClientOfUserId(event.GetInt("victim"));
|
||||
if(victim) {
|
||||
playerData[victim].isUnderAttack = StrEqual(name, "charger_carry_start");
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Event_HunterPounce(Event event, const char[] name, bool dontBroadcast) {
|
||||
int victim = GetClientOfUserId(event.GetInt("victim"));
|
||||
if(victim) {
|
||||
playerData[victim].isUnderAttack = StrEqual(name, "lunge_pounce");
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public Action Event_SmokerChoke(Event event, const char[] name, bool dontBroadcast) {
|
||||
int victim = GetClientOfUserId(event.GetInt("victim"));
|
||||
if(victim) {
|
||||
playerData[victim].isUnderAttack = StrEqual(name, "choke_start");
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
public Action Event_JockeyRide(Event event, const char[] name, bool dontBroadcast) {
|
||||
int victim = GetClientOfUserId(event.GetInt("victim"));
|
||||
if(victim) {
|
||||
playerData[victim].isUnderAttack = StrEqual(name, "jockey_ride");
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[] newValue) {
|
||||
cvar.GetString(gamemode, sizeof(gamemode));
|
||||
}
|
||||
|
@ -275,55 +335,85 @@ public Action Command_RunExtraItems(int client, int args) {
|
|||
#define FINALE_HORDE 7
|
||||
#define FINALE_WAIT 10
|
||||
|
||||
enum FinaleStage {
|
||||
Stage_Inactive = 0,
|
||||
Stage_FinaleActive = 1,
|
||||
Stage_FinaleTank1 = 2,
|
||||
Stage_FinaleTank2 = 3,
|
||||
Stage_FinaleDuplicatePending = 4,
|
||||
Stage_TankSplit = 5,
|
||||
Stage_InactiveFinale = -1
|
||||
}
|
||||
int extraTankHP;
|
||||
FinaleStage finaleStage;
|
||||
|
||||
public Action L4D2_OnChangeFinaleStage(int &finaleType, const char[] arg) {
|
||||
if(finaleType == FINALE_STARTED && abmExtraCount > 4 && hExtraFinaleTank.BoolValue) {
|
||||
finaleStage = 1;
|
||||
finaleStage = Stage_FinaleActive;
|
||||
PrintToConsoleAll("[EPI] Finale started and over threshold");
|
||||
} else if(finaleType == FINALE_TANK) {
|
||||
if(finaleStage == 1) {
|
||||
finaleStage = 2;
|
||||
if(finaleStage == Stage_FinaleActive) {
|
||||
finaleStage = Stage_FinaleTank1;
|
||||
PrintToConsoleAll("[EPI] First tank stage has started");
|
||||
} else if(finaleStage == 2) {
|
||||
finaleStage = 3;
|
||||
} else if(finaleStage == Stage_FinaleTank1) {
|
||||
finaleStage = Stage_FinaleTank2;
|
||||
PrintToConsoleAll("[EPI] Second stage started, waiting for tank");
|
||||
} else {
|
||||
PrintToConsoleAll("invalid");
|
||||
}
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void Event_TankSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||
int user = GetEventInt(event, "userid");
|
||||
int user = event.GetInt("userid");
|
||||
int tank = GetClientOfUserId(user);
|
||||
if(finaleStage == 3) {
|
||||
PrintToConsoleAll("[EPI] Second tank spawned, setting health.");
|
||||
if(tank > 0 && IsFakeClient(tank)) {
|
||||
if(tank > 0 && IsFakeClient(tank) && abmExtraCount > 4 && hExtraFinaleTank.BoolValue) {
|
||||
if(finaleStage == Stage_FinaleTank2) {
|
||||
PrintToConsoleAll("[EPI] Second tank spawned, setting health.");
|
||||
// Sets health in half, sets finaleStage to health
|
||||
CreateTimer(5.0, Timer_SplitTank, user);
|
||||
CreateTimer(5.0, Timer_SpawnFinaleTank, user);
|
||||
} else if(finaleStage == Stage_FinaleDuplicatePending) {
|
||||
PrintToConsoleAll("[EPI] Third & final tank spawned");
|
||||
RequestFrame(Frame_SetExtraTankHealth, user);
|
||||
} else if(finaleStage == Stage_Inactive && GetSurvivorsCount() > 6) {
|
||||
PrintToConsoleAll("[EPI] Creating a split tank");
|
||||
finaleStage = Stage_TankSplit;
|
||||
// Half their HP, assign half to self and for next tank
|
||||
int hp = GetEntProp(tank, Prop_Send, "m_iHealth") / 2;
|
||||
SetEntProp(tank, Prop_Send, "m_iHealth", hp);
|
||||
extraTankHP = hp;
|
||||
CreateTimer(11.0, Timer_SplitTank, user);
|
||||
// Then, summon the next tank
|
||||
} else if(finaleStage == Stage_TankSplit) {
|
||||
|
||||
}
|
||||
} else if(finaleStage > 3) {
|
||||
PrintToConsoleAll("[EPI] Third & final tank spawned, setting health.");
|
||||
RequestFrame(Frame_SetExtraTankHealth, user);
|
||||
}
|
||||
}
|
||||
public Action Timer_SpawnFinaleTank(Handle t, int user) {
|
||||
if(finaleStage == Stage_TankSplit) {
|
||||
ServerCommand("sm_forcespecial tank");
|
||||
finaleStage = Stage_Inactive;
|
||||
}
|
||||
}
|
||||
public Action Timer_SplitTank(Handle t, int user) {
|
||||
int tank = GetClientOfUserId(user);
|
||||
if(tank > 0) {
|
||||
if(tank > 0 && finaleStage == Stage_Inactive) {
|
||||
finaleStage = Stage_TankSplit;
|
||||
// Half their HP, assign half to self and for next tank
|
||||
int hp = GetEntProp(tank, Prop_Send, "m_iHealth") / 2;
|
||||
SetEntProp(tank, Prop_Send, "m_iHealth", hp);
|
||||
finaleStage = hp;
|
||||
extraTankHP = hp;
|
||||
// Then, summon the next tank
|
||||
ServerCommand("sm_forcespecial tank");
|
||||
} else {
|
||||
finaleStage = Stage_Inactive;
|
||||
}
|
||||
}
|
||||
|
||||
public void Frame_SetExtraTankHealth(int user) {
|
||||
int tank = GetClientOfUserId(user);
|
||||
if(tank > 0) {
|
||||
SetEntProp(tank, Prop_Send, "m_iHealth", finaleStage);
|
||||
finaleStage = 0;
|
||||
if(tank > 0 && finaleStage == Stage_FinaleDuplicatePending) {
|
||||
SetEntProp(tank, Prop_Send, "m_iHealth", extraTankHP);
|
||||
finaleStage = Stage_InactiveFinale;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,6 +426,10 @@ public void OnGetWeaponsInfo(int pThis, const char[] classname) {
|
|||
weaponMaxClipSizes.SetValue(classname, maxClipSize);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//// PLAYER STATE MANAGEMENT
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
//Called on the first spawn in a mission.
|
||||
public Action Event_GameStart(Event event, const char[] name, bool dontBroadcast) {
|
||||
firstGiven = false;
|
||||
|
@ -349,35 +443,40 @@ public Action Event_GameStart(Event event, const char[] name, bool dontBroadcast
|
|||
|
||||
public Action Event_PlayerFirstSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(GetClientTeam(client) == 2 && !IsFakeClient(client)) {
|
||||
if(L4D_IsFirstMapInScenario() && !firstGiven) {
|
||||
//Check if all clients are ready, and survivor count is > 4.
|
||||
if(AreAllClientsReady()) {
|
||||
abmExtraCount = GetRealSurvivorsCount();
|
||||
if(abmExtraCount > 4) {
|
||||
firstGiven = true;
|
||||
//Set the initial value ofhMinPlayers
|
||||
if(hUpdateMinPlayers.BoolValue && hMinPlayers != null) {
|
||||
hMinPlayers.IntValue = abmExtraCount;
|
||||
if(GetClientTeam(client) == 2) {
|
||||
CreateTimer(1.5, Timer_RemoveInvincibility, client);
|
||||
SDKHook(client, SDKHook_OnTakeDamage, OnInvincibleDamageTaken);
|
||||
if(!IsFakeClient(client)) {
|
||||
playerData[client].active = true;
|
||||
if(L4D_IsFirstMapInScenario() && !firstGiven) {
|
||||
//Check if all clients are ready, and survivor count is > 4.
|
||||
if(AreAllClientsReady()) {
|
||||
abmExtraCount = GetRealSurvivorsCount();
|
||||
if(abmExtraCount > 4) {
|
||||
firstGiven = true;
|
||||
//Set the initial value ofhMinPlayers
|
||||
if(hUpdateMinPlayers.BoolValue && hMinPlayers != null) {
|
||||
hMinPlayers.IntValue = abmExtraCount;
|
||||
}
|
||||
PopulateItems();
|
||||
CreateTimer(1.0, Timer_GiveKits);
|
||||
}
|
||||
if(firstSaferoomDoorEntity > 0 && IsValidEntity(firstSaferoomDoorEntity)) {
|
||||
UnlockDoor(firstSaferoomDoorEntity, 2);
|
||||
}
|
||||
PopulateItems();
|
||||
CreateTimer(1.0, Timer_GiveKits);
|
||||
}
|
||||
if(firstSaferoomDoorEntity > 0 && IsValidEntity(firstSaferoomDoorEntity)) {
|
||||
UnlockDoor(firstSaferoomDoorEntity, 2);
|
||||
} else {
|
||||
// New client has connected, not on first map.
|
||||
// TODO: Check if Timer_UpdateMinPlayers is needed, or if this works:
|
||||
// Never decrease abmExtraCount
|
||||
int newCount = GetRealSurvivorsCount();
|
||||
if(newCount > abmExtraCount) {
|
||||
abmExtraCount = newCount;
|
||||
}
|
||||
// If 5 survivors, then set them up, TP them.
|
||||
if(abmExtraCount > 4) {
|
||||
RequestFrame(Frame_SetupNewClient, client);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// New client has connected, not on first map.
|
||||
// TODO: Check if Timer_UpdateMinPlayers is needed, or if this works:
|
||||
// Never decrease abmExtraCount
|
||||
int newCount = GetRealSurvivorsCount();
|
||||
if(newCount > abmExtraCount) {
|
||||
abmExtraCount = newCount;
|
||||
}
|
||||
// If 5 survivors, then set them up, TP them.
|
||||
if(abmExtraCount > 4) {
|
||||
RequestFrame(Frame_SetupNewClient, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,6 +516,32 @@ public Action Event_PlayerSpawn(Event event, const char[] name, bool dontBroadca
|
|||
|
||||
}
|
||||
|
||||
public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
|
||||
int userid = event.GetInt("userid");
|
||||
int client = GetClientOfUserId(userid);
|
||||
if(client > 0 && !IsFakeClient(client)) {
|
||||
DataPack pack = new DataPack();
|
||||
pack.WriteCell(userid);
|
||||
pack.WriteCell(client);
|
||||
CreateDataTimer(cvDropDisconnectTime.FloatValue, Timer_DropSurvivor, pack);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Timer_DropSurvivor(Handle h, DataPack pack) {
|
||||
int userid = pack.ReadCell();
|
||||
int client = GetClientOfUserId(userid);
|
||||
// Check if player is not connected, if not, drop their existing status
|
||||
if(client == 0) {
|
||||
client = pack.ReadCell();
|
||||
if(client == 0) //In the case that someone took their client index, don't inactivate them:
|
||||
playerData[client].active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
/////// Events
|
||||
/////////////////////////////////////////
|
||||
|
||||
public Action Event_ItemPickup(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0) {
|
||||
|
@ -440,12 +565,10 @@ public void Frame_SetupNewClient(int client) {
|
|||
int item = GivePlayerItem(client, "weapon_first_aid_kit");
|
||||
EquipPlayerWeapon(client, item);
|
||||
}
|
||||
static float spawnPos[3];
|
||||
// TODO: Fix null
|
||||
if(GetIdealPositionInSurvivorFlow(client, spawnPos))
|
||||
TeleportEntity(client, spawnPos, NULL_VECTOR, NULL_VECTOR);
|
||||
CreateTimer(1.5, Timer_RemoveInvincibility, client);
|
||||
SDKHook(client, SDKHook_OnTakeDamage, OnInvincibleDamageTaken);
|
||||
|
||||
// static float spawnPos[3];
|
||||
// if(GetIdealPositionInSurvivorFlow(client, spawnPos))
|
||||
// TeleportEntity(client, spawnPos, NULL_VECTOR, NULL_VECTOR);
|
||||
}
|
||||
public Action Timer_RemoveInvincibility(Handle h, int client) {
|
||||
SDKUnhook(client, SDKHook_OnTakeDamage, OnInvincibleDamageTaken);
|
||||
|
@ -530,7 +653,7 @@ public void OnMapStart() {
|
|||
HookEntityOutput("trigger_changelevel", "OnStartTouch", EntityOutput_OnStartTouchSaferoom);
|
||||
|
||||
playersLoadedIn = 0;
|
||||
finaleStage = 0;
|
||||
finaleStage = Stage_Inactive;
|
||||
}
|
||||
|
||||
|
||||
|
@ -605,7 +728,7 @@ public Action Event_Pickup(int client, int weapon) {
|
|||
static char name[32];
|
||||
GetEntityClassname(weapon, name, sizeof(name));
|
||||
if(StrEqual(name, "weapon_first_aid_kit", true)) {
|
||||
if(isBeingGivenKit[client]) return Plugin_Continue;
|
||||
if(playerData[client].itemGiven) return Plugin_Continue;
|
||||
if((L4D_IsInFirstCheckpoint(client) || L4D_IsInLastCheckpoint(client)) && UseExtraKit(client)) {
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
@ -625,62 +748,6 @@ public void OnEntityCreated(int entity, const char[] classname) {
|
|||
}
|
||||
}
|
||||
|
||||
int tankChooseVictimTicks[MAXPLAYERS+1]; //Per tank
|
||||
int totalTankDamage[MAXPLAYERS+1]; //Per survivor
|
||||
|
||||
public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
||||
if(abmExtraCount <= 4) return Plugin_Continue;
|
||||
int class = GetEntProp(attacker, Prop_Send, "m_zombieClass");
|
||||
if(class != TANK_CLASS_ID) return Plugin_Continue;
|
||||
|
||||
//Find a new victim
|
||||
if(++tankChooseVictimTicks[attacker] > 200) {
|
||||
tankChooseVictimTicks[attacker] = 0;
|
||||
ArrayList clients = new ArrayList(2);
|
||||
float tankPos[3], clientPos[3];
|
||||
GetClientAbsOrigin(attacker, tankPos);
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i)) {
|
||||
//If a player does less than 50 damage, and has green health add them to list
|
||||
if(totalTankDamage[i] < 100 && GetClientHealth(i) > 40) {
|
||||
GetClientAbsOrigin(i, clientPos);
|
||||
float dist = GetVectorDistance(clientPos, tankPos);
|
||||
// Only add targets who are far enough away from tank
|
||||
if(dist > 5000) {
|
||||
PrintDebug(DEBUG_ANY, "Adding player %N to possible victim list. Dist=%f, Dmg=%d", i, dist, totalTankDamage[i]);
|
||||
int index = clients.Push(i);
|
||||
clients.Set(index, dist, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(clients.Length == 0) return Plugin_Continue;
|
||||
|
||||
clients.SortCustom(Sort_TankTargetter);
|
||||
/*curTarget = clients.Get(0);*/
|
||||
PrintDebug(DEBUG_ANY, "Player Selected to target: %N", curTarget);
|
||||
//TODO: Possibly clear totalTankDamage
|
||||
delete clients;
|
||||
//return Plugin_Changed;
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
int Sort_TankTargetter(int index1, int index2, Handle array, Handle hndl) {
|
||||
int client1 = GetArrayCell(array, index1);
|
||||
int client2 =GetArrayCell(array, index2);
|
||||
float distance1 = GetArrayCell(array, index2, 0);
|
||||
float distance2 = GetArrayCell(array, index2, 1);
|
||||
/*500 units away, 0 damage vs 600 units away, 0 damage
|
||||
-> target closest 500
|
||||
500 units away, 10 damage, vs 600 units away 0 damage
|
||||
500 - 10 = 450 vs 600
|
||||
*/
|
||||
return (totalTankDamage[client1] + RoundFloat(distance1)) - (totalTankDamage[client2] + RoundFloat(distance2));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hooks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -808,6 +875,7 @@ public Action Timer_OpenSaferoomDoor(Handle h) {
|
|||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
|
||||
void UnlockDoor(int entity, int flag) {
|
||||
PrintDebug(DEBUG_GENERIC, "Door unlocked, flag %d", flag);
|
||||
if(IsValidEntity(entity)) {
|
||||
|
@ -1001,10 +1069,10 @@ stock bool DoesClientHaveKit(int client) {
|
|||
|
||||
stock bool UseExtraKit(int client) {
|
||||
if(extraKitsAmount > 0) {
|
||||
isBeingGivenKit[client] = true;
|
||||
playerData[client].itemGiven = true;
|
||||
int ent = GivePlayerItem(client, "weapon_first_aid_kit");
|
||||
EquipPlayerWeapon(client, ent);
|
||||
isBeingGivenKit[client] = false;
|
||||
playerData[client].itemGiven = false;
|
||||
if(--extraKitsAmount <= 0) {
|
||||
extraKitsAmount = 0;
|
||||
}
|
||||
|
@ -1135,7 +1203,7 @@ stock void RunVScriptLong(const char[] sCode, any ...) {
|
|||
// Gets a position (from a nav area)
|
||||
stock bool GetIdealPositionInSurvivorFlow(int target, float pos[3]) {
|
||||
static float ang[3];
|
||||
int client = GetHighestFlowSurvivor(target);
|
||||
int client = GetLowestFlowSurvivor(target);
|
||||
if(client > 0) {
|
||||
GetClientAbsOrigin(client, pos);
|
||||
GetClientAbsAngles(client, ang);
|
||||
|
|
|
@ -64,7 +64,7 @@ public void OnPluginStart() {
|
|||
hAutoPunish = CreateConVar("sm_ftt_autopunish_action", "0", "Setup automatic punishment of players. Add bits together\n0=Disabled, 1=Tank magnet, 2=Special magnet, 4=Swarm, 8=InstantVomit", FCVAR_NONE, true, 0.0);
|
||||
hAutoPunishExpire = CreateConVar("sm_ftt_autopunish_expire", "0", "How many minutes of gametime until autopunish is turned off? 0 for never.", FCVAR_NONE, true, 0.0);
|
||||
hMagnetChance = CreateConVar("sm_ftt_magnet_chance", "1.0", "% of the time that the magnet will work on a player.", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
hMagnetTargetMode = CreateConVar("sm_ftt_magnet_targetting", "6", "How does the specials target players. Add bits together\n0=Incapped are ignored, 1=Specials targets incapped, 2=Tank targets incapped 4=Witch targets incapped");
|
||||
hMagnetTargetMode = CreateConVar("sm_ftt_magnet_targetting", "4", "How does the specials target players. Add bits together\n0=Incapped are ignored, 1=Specials targets incapped, 2=Tank targets incapped 4=Witch targets incapped");
|
||||
hShoveFailChance = CreateConVar("sm_ftt_shove_fail_chance", "0.65", "The % chance that a shove fails", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
hBadThrowHitSelf = CreateConVar("sm_ftt_badthrow_fail_chance", "1", "The % chance that on a throw, they will instead hit themselves. 0 to disable", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||
hBotReverseFFDefend = CreateConVar("sm_ftt_bot_defend", "1", "Should bots defend themselves?\n0 = OFF\n1 = Will retaliate against non-admins\n2 = Anyone", FCVAR_NONE, true, 0.0, true, 2.0);
|
||||
|
|
|
@ -67,17 +67,15 @@ public Action Cmd_VGag(int client, int args) {
|
|||
client,
|
||||
target_list,
|
||||
MAXPLAYERS,
|
||||
COMMAND_FILTER_ALIVE, /* Only allow alive players */
|
||||
COMMAND_FILTER_ALIVE,
|
||||
target_name,
|
||||
sizeof(target_name),
|
||||
tn_is_ml)) <= 0)
|
||||
{
|
||||
/* This function replies to the admin with a failure message */
|
||||
ReplyToTargetError(client, target_count);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
for (int i = 0; i < target_count; i++)
|
||||
{
|
||||
for (int i = 0; i < target_count; i++) {
|
||||
int playerIndex = gaggedPlayers[client].FindValue(target_list[i]);
|
||||
if(playerIndex > -1) {
|
||||
gaggedPlayers[client].Erase(playerIndex);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue