mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-06 21:33:20 +00:00
Add new trolls, fix inface targetting, fix a lot
This commit is contained in:
parent
6e323b26d2
commit
16e676d56d
11 changed files with 415 additions and 199 deletions
Binary file not shown.
|
@ -4,7 +4,7 @@
|
||||||
//Allow MAX_TROLLS to be defined elsewhere
|
//Allow MAX_TROLLS to be defined elsewhere
|
||||||
#if defined MAX_TROLLS
|
#if defined MAX_TROLLS
|
||||||
#else
|
#else
|
||||||
#define MAX_TROLLS 51
|
#define MAX_TROLLS 54
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum trollModifier {
|
enum trollModifier {
|
||||||
|
@ -26,6 +26,13 @@ enum trollFlag {
|
||||||
Flag_8 = 1 << 7,
|
Flag_8 = 1 << 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum valueType {
|
||||||
|
Value_None,
|
||||||
|
Value_Float,
|
||||||
|
Value_String,
|
||||||
|
Value_Integer
|
||||||
|
}
|
||||||
|
|
||||||
StringMap trollKV;
|
StringMap trollKV;
|
||||||
char trollIds[MAX_TROLLS+1][MAX_TROLL_NAME_LENGTH];
|
char trollIds[MAX_TROLLS+1][MAX_TROLL_NAME_LENGTH];
|
||||||
char DEFAULT_FLAG_PROMPT_MULTIPLE[] = "Enable options (Multiple)";
|
char DEFAULT_FLAG_PROMPT_MULTIPLE[] = "Enable options (Multiple)";
|
||||||
|
@ -57,6 +64,9 @@ enum struct TrollFlagPrompt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Very hacky but map a power (say 16, 32) to the index in a list
|
||||||
|
// Used to get the name of a flag (flag #16 for example) in ArrayList<string> of flag names
|
||||||
int GetIndexFromPower(int powerOfTwo) {
|
int GetIndexFromPower(int powerOfTwo) {
|
||||||
for(int i = 0; i < 16; i++) {
|
for(int i = 0; i < 16; i++) {
|
||||||
if(1 << i == powerOfTwo) {
|
if(1 << i == powerOfTwo) {
|
||||||
|
@ -67,28 +77,30 @@ int GetIndexFromPower(int powerOfTwo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum struct Troll {
|
enum struct Troll {
|
||||||
int id;
|
int id; // The id or the index into the global Trolls[] array
|
||||||
int categoryID;
|
int categoryID; // The category this troll belongs in
|
||||||
|
|
||||||
char name[MAX_TROLL_NAME_LENGTH];
|
char name[MAX_TROLL_NAME_LENGTH];
|
||||||
char description[128];
|
char description[128];
|
||||||
bool hidden;
|
bool hidden;
|
||||||
|
|
||||||
int mods;
|
int mods; // Combination of valid modifiers. Only two are ever supported
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
int activeFlagClients[MAXPLAYERS+1];
|
int activeFlagClients[MAXPLAYERS+1];
|
||||||
char flagPrompt[MAX_TROLL_FLAG_LENGTH];
|
|
||||||
ArrayList flagNames;
|
ArrayList flagNames;
|
||||||
ArrayList flagPrompts;
|
ArrayList flagPrompts;
|
||||||
|
|
||||||
|
// Custom timer
|
||||||
Timer timerFunction;
|
Timer timerFunction;
|
||||||
Handle timerHandles[MAXPLAYERS+1];
|
Handle timerHandles[MAXPLAYERS+1];
|
||||||
float timerInterval;
|
float timerInterval;
|
||||||
|
int timerRequiredFlags;
|
||||||
|
|
||||||
void SetTimer(float interval, Timer timer) {
|
void SetTimer(float interval, Timer timer, int requiredFlags = 0) {
|
||||||
this.timerInterval = interval;
|
this.timerInterval = interval;
|
||||||
this.timerFunction = timer;
|
this.timerFunction = timer;
|
||||||
|
this.timerRequiredFlags = requiredFlags;
|
||||||
for(int i = 0; i <= MAXPLAYERS; i++) {
|
for(int i = 0; i <= MAXPLAYERS; i++) {
|
||||||
this.timerHandles[i] = null;
|
this.timerHandles[i] = null;
|
||||||
}
|
}
|
||||||
|
@ -198,14 +210,13 @@ enum struct Troll {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetFlagCount() {
|
||||||
|
return this.flagNames != null ? this.flagNames.Length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int GetClientFlags(int client) {
|
int GetClientFlags(int client) {
|
||||||
return this.activeFlagClients[client];
|
return this.activeFlagClients[client];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFlagPrompt(const char[] prompt) {
|
|
||||||
strcopy(this.flagPrompt, MAX_TROLL_FLAG_LENGTH, prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetFlagPrompt(int index, TrollFlagPrompt prompt) {
|
void GetFlagPrompt(int index, TrollFlagPrompt prompt) {
|
||||||
this.flagPrompts.GetArray(index, prompt);
|
this.flagPrompts.GetArray(index, prompt);
|
||||||
}
|
}
|
||||||
|
@ -357,15 +368,21 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isActive = Trolls[trollIndex].activeFlagClients[victim] > -1;
|
||||||
|
|
||||||
// Clear troll specific timer:
|
// Clear troll specific timer:
|
||||||
if(Trolls[trollIndex].timerInterval > 0.0) {
|
if(Trolls[trollIndex].timerInterval > 0.0) {
|
||||||
if(flags > -1)
|
PrintToServer("epi: there is timer for \"%s\", flags=%d", name, flags);
|
||||||
Trolls[trollIndex].timerHandles[victim] = CreateTimer(Trolls[trollIndex].timerInterval, Trolls[trollIndex].timerFunction, victim, TIMER_REPEAT);
|
if(!isActive) {
|
||||||
else if(Trolls[trollIndex].timerHandles[victim] != null) {
|
if(Trolls[trollIndex].timerRequiredFlags == 0 || Trolls[trollIndex].timerRequiredFlags & flags) {
|
||||||
|
Trolls[trollIndex].timerHandles[victim] = CreateTimer(Trolls[trollIndex].timerInterval, Trolls[trollIndex].timerFunction, victim, TIMER_REPEAT);
|
||||||
|
}
|
||||||
|
} else if(Trolls[trollIndex].timerHandles[victim] != null) {
|
||||||
delete Trolls[trollIndex].timerHandles[victim];
|
delete Trolls[trollIndex].timerHandles[victim];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!silent && SilentMenuSelected[activator]) silent = true;
|
if(!silent && SilentMenuSelected[activator]) silent = true;
|
||||||
|
|
||||||
static int MetaInverseTrollID;
|
static int MetaInverseTrollID;
|
||||||
|
@ -393,7 +410,6 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isActive = Trolls[trollIndex].activeFlagClients[victim] > -1;
|
|
||||||
|
|
||||||
// Toggle on flags for client, if it's not a single run.
|
// Toggle on flags for client, if it's not a single run.
|
||||||
if(modifier & TrollMod_Constant) {
|
if(modifier & TrollMod_Constant) {
|
||||||
|
|
|
@ -86,5 +86,10 @@ void SetupsTrollCombos() {
|
||||||
combo.AddTroll("Dull Melee", .flags=2);
|
combo.AddTroll("Dull Melee", .flags=2);
|
||||||
combo.AddTroll("Temp Health Quick Drain");
|
combo.AddTroll("Temp Health Quick Drain");
|
||||||
|
|
||||||
|
SetupCombo(combo, "Blindness");
|
||||||
|
combo.AddTroll("Vomit Player", 0, TrollMod_Constant);
|
||||||
|
combo.AddTroll("Shakey Camera", .flags=16);
|
||||||
|
combo.AddTroll("Randomize Angles", .flags=16);
|
||||||
|
|
||||||
PrintToServer("[FTT] Loaded %d troll combos", combos.Length);
|
PrintToServer("[FTT] Loaded %d troll combos", combos.Length);
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
public Action Command_InstaSpecial(int client, int args) {
|
Action Command_InstaSpecial(int client, int args) {
|
||||||
if(args < 1) {
|
if(args < 1) {
|
||||||
Menu menu = new Menu(Insta_PlayerHandler);
|
Menu menu = new Menu(Insta_PlayerHandler);
|
||||||
menu.SetTitle("InstaSpecial: Choose a player");
|
menu.SetTitle("InstaSpecial: Choose a player");
|
||||||
|
@ -46,7 +46,7 @@ public Action Command_InstaSpecial(int client, int args) {
|
||||||
for (int i = 0; i < target_count; i++) {
|
for (int i = 0; i < target_count; i++) {
|
||||||
int target = target_list[i];
|
int target = target_list[i];
|
||||||
if(GetClientTeam(target) == 2) {
|
if(GetClientTeam(target) == 2) {
|
||||||
if(SpawnSpecialForTarget(specialType, target)) {
|
if(SpawnSpecialForTarget(specialType, target, view_as<int>(Special_AlwaysTarget))) {
|
||||||
LogAction(client, target, "\"%L\" spawned Insta-%s™ nearby \"%L\"", client, arg2, target);
|
LogAction(client, target, "\"%L\" spawned Insta-%s™ nearby \"%L\"", client, arg2, target);
|
||||||
successes++;
|
successes++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,7 +64,7 @@ public Action Command_InstaSpecial(int client, int args) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Command_InstaSpecialFace(int client, int args) {
|
Action Command_InstaSpecialFace(int client, int args) {
|
||||||
if(args < 1) {
|
if(args < 1) {
|
||||||
Menu menu = new Menu(Insta_PlayerHandler);
|
Menu menu = new Menu(Insta_PlayerHandler);
|
||||||
menu.SetTitle("Inface: Choose a player");
|
menu.SetTitle("Inface: Choose a player");
|
||||||
|
@ -112,7 +112,7 @@ public Action Command_InstaSpecialFace(int client, int args) {
|
||||||
for (int i = 0; i < target_count; i++) {
|
for (int i = 0; i < target_count; i++) {
|
||||||
int target = target_list[i];
|
int target = target_list[i];
|
||||||
if(GetClientTeam(target) == 2) {
|
if(GetClientTeam(target) == 2) {
|
||||||
if(SpawnSpecialForTarget(specialType, target, view_as<int>(Special_OnTarget))) {
|
if(SpawnSpecialForTarget(specialType, target, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget))) {
|
||||||
LogAction(client, target, "\"%L\" spawned Insta-%s™ at player \"%L\"", client, arg2, target);
|
LogAction(client, target, "\"%L\" spawned Insta-%s™ at player \"%L\"", client, arg2, target);
|
||||||
successes++;
|
successes++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,7 +129,7 @@ public Action Command_InstaSpecialFace(int client, int args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Action Command_WitchAttack(int client, int args) {
|
Action Command_WitchAttack(int client, int args) {
|
||||||
if(args < 1) {
|
if(args < 1) {
|
||||||
ReplyToCommand(client, "Usage: sm_witch_attack <user> [# of witches or 0 for all]");
|
ReplyToCommand(client, "Usage: sm_witch_attack <user> [# of witches or 0 for all]");
|
||||||
}else{
|
}else{
|
||||||
|
@ -245,7 +245,7 @@ public Action Command_ApplyUser(int client, int args) {
|
||||||
target_name,
|
target_name,
|
||||||
sizeof(target_name),
|
sizeof(target_name),
|
||||||
tn_is_ml)) <= 0
|
tn_is_ml)) <= 0
|
||||||
&& target_list[0] > 0) {
|
&& target_list[0] == 0) {
|
||||||
/* This function replies to the admin with a failure message */
|
/* This function replies to the admin with a failure message */
|
||||||
ReplyToTargetError(client, target_count);
|
ReplyToTargetError(client, target_count);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
|
@ -624,7 +624,7 @@ public Action Command_SmartCharge(int client, int args) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Command_HealTarget(int client, int args) {
|
Action Command_HealTarget(int client, int args) {
|
||||||
if(args > 0) {
|
if(args > 0) {
|
||||||
char arg1[32], arg2[4];
|
char arg1[32], arg2[4];
|
||||||
GetCmdArg(1, arg1, sizeof(arg1));
|
GetCmdArg(1, arg1, sizeof(arg1));
|
||||||
|
@ -688,4 +688,61 @@ public Action Command_HealTarget(int client, int args) {
|
||||||
ReplyToCommand(client, "Usage: /healbots <player> [# of bots or 0 for all]");
|
ReplyToCommand(client, "Usage: /healbots <player> [# of bots or 0 for all]");
|
||||||
}
|
}
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
Action Command_SetReverseFF(int client, int args) {
|
||||||
|
if(args < 2) {
|
||||||
|
ReplyToCommand(client, "Usage: sm_rff <target> <amount> [fire/explosion]*");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
char arg[32];
|
||||||
|
GetCmdArg(1, arg, sizeof(arg));
|
||||||
|
int target = GetSinglePlayer(client, arg, COMMAND_FILTER_NO_BOTS);
|
||||||
|
if(target <= 0) {
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
GetCmdArg(1, arg, sizeof(arg));
|
||||||
|
GetCmdArg(2, arg, sizeof(arg));
|
||||||
|
int flag = -1;
|
||||||
|
if(StrEqual(arg, "0") || StrEqual(arg, "0.0")) {
|
||||||
|
flag = 8;
|
||||||
|
} else if(StrEqual(arg, "2")) {
|
||||||
|
flag = 2;
|
||||||
|
} else if(StrEqual(arg, "0.5") || StrEqual(arg, ".5")) {
|
||||||
|
flag = 4;
|
||||||
|
} else if(StrEqual(arg, "3")) {
|
||||||
|
flag = 8;
|
||||||
|
} else if(StrEqual(arg, "1")) {
|
||||||
|
flag = 1;
|
||||||
|
} else {
|
||||||
|
ReplyToCommand(client, "Unsupported amount. Possible values: 0, 2, 0.5, 3, 1");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
// args are 1-indexed so <=
|
||||||
|
for(int i = 3; i <= args; i++) {
|
||||||
|
GetCmdArg(i, arg, sizeof(arg));
|
||||||
|
if(arg[0] == 'f') {
|
||||||
|
flag |= 32;
|
||||||
|
} else if(arg[0] == 'e') {
|
||||||
|
flag |= 64;
|
||||||
|
} else {
|
||||||
|
ReplyToCommand(client, "Unknown arg: %s", arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ApplyTroll(target, "Reverse FF", client, TrollMod_Constant, flag);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
Action Command_SetMagnetShortcut(int client, int args) {
|
||||||
|
if(args < 1) {
|
||||||
|
ReplyToCommand(client, "Usage: sm_magnet <target>");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
char arg[32];
|
||||||
|
GetCmdArg(1, arg, sizeof(arg));
|
||||||
|
int target = GetSinglePlayer(client, arg, COMMAND_FILTER_NO_BOTS);
|
||||||
|
if(target <= 0) {
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
ShowTrollsForCategory(client, GetClientUserId(target), 0);
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
|
@ -35,9 +35,10 @@ public void OnClientPutInServer(int client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) {
|
public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||||
int userid = event.GetInt("userid");
|
if(spIsActive || g_iPendingSurvivorAdd) {
|
||||||
if(spIsActive)
|
int userid = event.GetInt("userid");
|
||||||
CreateTimer(0.1, Timer_CheckSpecial, userid);
|
CreateTimer(0.1, Timer_CheckSpecial, userid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ public void Event_DoorToggle(Event event, const char[] name, bool dontBroadcast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Event_SecondaryHealthUsed(Event event, const char[] name, bool dontBroadcast) {
|
void Event_SecondaryHealthUsed(Event event, const char[] name, bool dontBroadcast) {
|
||||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||||
if(client && Trolls[slipperyShoesIndex].IsActive(client) && Trolls[slipperyShoesIndex].activeFlagClients[client] & 8) {
|
if(client && Trolls[slipperyShoesIndex].IsActive(client) && Trolls[slipperyShoesIndex].activeFlagClients[client] & 8) {
|
||||||
L4D_StaggerPlayer(client, client, NULL_VECTOR);
|
L4D_StaggerPlayer(client, client, NULL_VECTOR);
|
||||||
|
@ -142,29 +143,32 @@ public void Event_SecondaryHealthUsed(Event event, const char[] name, bool dontB
|
||||||
}
|
}
|
||||||
|
|
||||||
static float SPIT_VEL[3] = { 0.0, 0.0, -1.0 };
|
static float SPIT_VEL[3] = { 0.0, 0.0, -1.0 };
|
||||||
public Action Timer_CheckSpecial(Handle h, int specialID) {
|
Action Timer_CheckSpecial(Handle h, int specialID) {
|
||||||
int special = GetClientOfUserId(specialID);
|
int special = GetClientOfUserId(specialID);
|
||||||
|
if(special == 0) return Plugin_Continue;
|
||||||
// Check if new player is the spawned special:
|
// Check if new player is the spawned special:
|
||||||
if(spIsActive && special > 0 && IsFakeClient(special)) {
|
if(g_iPendingSurvivorAdd && GetClientTeam(special) == 2 && GetEntProp(special, Prop_Send, "m_humanSpectatorUserID") == 0) {
|
||||||
|
g_iPendingSurvivorAdd = false;
|
||||||
|
isCustomSurvivor[special] = true;
|
||||||
|
PrintToServer("EPI Debug: Custom Survivor %N", special);
|
||||||
|
} else if(spIsActive && IsFakeClient(special)) {
|
||||||
//g_iPendingSurvivorAdd
|
//g_iPendingSurvivorAdd
|
||||||
if(GetClientTeam(special) == 2 && g_iPendingSurvivorAdd && GetEntProp(special, Prop_Send, "m_humanSpectatorUserID") == 0) {
|
if(GetClientTeam(special) == 3) {
|
||||||
g_iPendingSurvivorAdd = false;
|
|
||||||
isCustomSurvivor[special] = true;
|
|
||||||
} else if(GetClientTeam(special) == 3) {
|
|
||||||
SpecialType type = view_as<SpecialType>(GetEntProp(special, Prop_Send, "m_zombieClass"));
|
SpecialType type = view_as<SpecialType>(GetEntProp(special, Prop_Send, "m_zombieClass"));
|
||||||
if(type == spActiveRequest.type) {
|
if(type == spActiveRequest.type) {
|
||||||
// Ignore any fake clients with 'Bot' in name
|
// Ignore any fake clients with 'Bot' in name
|
||||||
static char buf[32];
|
static char buf[32];
|
||||||
GetClientName(special, buf, sizeof(buf));
|
GetClientName(special, buf, sizeof(buf));
|
||||||
if(StrContains(buf, "bot", false) == -1) {
|
if(StrContains(buf, "bot", false) == -1) {
|
||||||
if(spActiveRequest.targetUserId) {
|
// Set the special's target and flags
|
||||||
pdata[special].attackerTargetUid = spActiveRequest.targetUserId;
|
pdata[special].attackerTargetUid = spActiveRequest.targetUserId;
|
||||||
pdata[special].specialAttackFlags = spActiveRequest.flags;
|
pdata[special].specialAttackFlags = spActiveRequest.flags;
|
||||||
}
|
// Warp to the spawn location
|
||||||
|
|
||||||
TeleportEntity(special, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
|
TeleportEntity(special, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
|
||||||
|
// Kill on spawn if enabled
|
||||||
if(spActiveRequest.flags & view_as<int>(SPI_KillOnSpawn)) {
|
if(spActiveRequest.flags & view_as<int>(SPI_KillOnSpawn)) {
|
||||||
if(type == Special_Spitter) {
|
if(type == Special_Spitter) {
|
||||||
|
// Bug fix, spitter drops small puddle, so we spawn our own
|
||||||
float pos[3];
|
float pos[3];
|
||||||
GetClientEyePosition(special, pos);
|
GetClientEyePosition(special, pos);
|
||||||
L4D2_SpitterPrj(special, pos, SPIT_VEL);
|
L4D2_SpitterPrj(special, pos, SPIT_VEL);
|
||||||
|
@ -172,8 +176,8 @@ public Action Timer_CheckSpecial(Handle h, int specialID) {
|
||||||
RequestFrame(Frame_Boom, special);
|
RequestFrame(Frame_Boom, special);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special spawned, run the next in the queue:
|
||||||
g_iSpId++;
|
g_iSpId++;
|
||||||
|
|
||||||
ProcessSpecialQueue();
|
ProcessSpecialQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,15 +198,16 @@ public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast
|
||||||
int userid = event.GetInt("userid");
|
int userid = event.GetInt("userid");
|
||||||
int client = GetClientOfUserId(userid);
|
int client = GetClientOfUserId(userid);
|
||||||
if(client > 0) {
|
if(client > 0) {
|
||||||
pdata[client].specialAttackFlags = 0;
|
|
||||||
if(pdata[client].attackerTargetUid > 0) {
|
if(pdata[client].attackerTargetUid > 0) {
|
||||||
// If special died, clear & subtract one from counter
|
// If special died, clear & subtract one from counter
|
||||||
pdata[client].attackerTargetUid = 0;
|
pdata[client].attackerTargetUid = 0;
|
||||||
|
pdata[client].specialAttackFlags = 0;
|
||||||
} else {
|
} else {
|
||||||
// If player died, stop the targetting
|
// If player died, stop the targetting
|
||||||
for(int i = 1; i <= MaxClients; i++) {
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
if(pdata[i].attackerTargetUid == userid) {
|
if(pdata[i].attackerTargetUid == userid) {
|
||||||
pdata[i].attackerTargetUid = 0;
|
pdata[i].attackerTargetUid = 0;
|
||||||
|
pdata[i].specialAttackFlags = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,7 +315,6 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
||||||
if(spMagnetID == 0) spMagnetID = GetTrollID("Special Magnet");
|
if(spMagnetID == 0) spMagnetID = GetTrollID("Special Magnet");
|
||||||
if(tankMagnetID == 0) tankMagnetID = GetTrollID("Tank Magnet");
|
if(tankMagnetID == 0) tankMagnetID = GetTrollID("Tank Magnet");
|
||||||
|
|
||||||
if(hMagnetChance.FloatValue < GetRandomFloat()) return Plugin_Continue;
|
|
||||||
L4D2Infected class = view_as<L4D2Infected>(GetEntProp(attacker, Prop_Send, "m_zombieClass"));
|
L4D2Infected class = view_as<L4D2Infected>(GetEntProp(attacker, Prop_Send, "m_zombieClass"));
|
||||||
// Check for any existing victims
|
// Check for any existing victims
|
||||||
int existingTarget = GetClientOfUserId(pdata[attacker].attackerTargetUid);
|
int existingTarget = GetClientOfUserId(pdata[attacker].attackerTargetUid);
|
||||||
|
@ -337,6 +341,10 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
||||||
return Plugin_Changed;
|
return Plugin_Changed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if(pdata[attacker].specialAttackFlags & view_as<int>(SPI_KillOnTargetIncap)) {
|
||||||
|
ForcePlayerSuicide(attacker);
|
||||||
|
}
|
||||||
|
PrintToServer("target (%N) not alive, resetting target for %d", existingTarget, attacker)
|
||||||
pdata[attacker].attackerTargetUid = 0;
|
pdata[attacker].attackerTargetUid = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -772,6 +780,9 @@ public Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float&
|
||||||
if(damage > 0.0 && victim != attacker && Trolls[slipperyShoesIndex].IsActive(victim) && Trolls[slipperyShoesIndex].activeFlagClients[victim] & 16) {
|
if(damage > 0.0 && victim != attacker && Trolls[slipperyShoesIndex].IsActive(victim) && Trolls[slipperyShoesIndex].activeFlagClients[victim] & 16) {
|
||||||
L4D_StaggerPlayer(victim, victim, NULL_VECTOR);
|
L4D_StaggerPlayer(victim, victim, NULL_VECTOR);
|
||||||
}
|
}
|
||||||
|
if(Trolls[t_slotRouletteIndex].IsActive(victim)) {
|
||||||
|
SetSlot(victim, -1);
|
||||||
|
}
|
||||||
|
|
||||||
if(IsTrollActive(victim, "Damage Boost")) {
|
if(IsTrollActive(victim, "Damage Boost")) {
|
||||||
damage * 2;
|
damage * 2;
|
||||||
|
@ -832,6 +843,9 @@ public Action OnVocalizeCommand(int client, const char[] vocalize, int initiator
|
||||||
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", noRushingUsSpeed[client]);
|
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", noRushingUsSpeed[client]);
|
||||||
PrintToConsoleAdmins("[FTT] NoRushingUs: Dropping speed for %N (now %.1f%)", client, noRushingUsSpeed[client] * 100.0);
|
PrintToConsoleAdmins("[FTT] NoRushingUs: Dropping speed for %N (now %.1f%)", client, noRushingUsSpeed[client] * 100.0);
|
||||||
}
|
}
|
||||||
|
if(Trolls[t_slotRouletteIndex].IsActive(client)) {
|
||||||
|
SetSlot(client, -1);
|
||||||
|
}
|
||||||
if(Trolls[vocalGagID].IsActive(client)) {
|
if(Trolls[vocalGagID].IsActive(client)) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
@ -851,17 +865,17 @@ public void OnSceneStageChanged(int scene, SceneStages stage) {
|
||||||
static char sceneFile[32];
|
static char sceneFile[32];
|
||||||
GetSceneFile(scene, sceneFile, sizeof(sceneFile));
|
GetSceneFile(scene, sceneFile, sizeof(sceneFile));
|
||||||
if(StrContains(sceneFile, "warnboomer") > -1) {
|
if(StrContains(sceneFile, "warnboomer") > -1) {
|
||||||
SpawnSpecialForTarget(Special_Boomer, activator, view_as<int>(Special_OnTarget));
|
SpawnSpecialForTarget(Special_Boomer, activator, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget));
|
||||||
} else if(StrContains(sceneFile, "warnhunter") > -1) {
|
} else if(StrContains(sceneFile, "warnhunter") > -1) {
|
||||||
SpawnSpecialForTarget(Special_Hunter, activator, view_as<int>(Special_OnTarget));
|
SpawnSpecialForTarget(Special_Hunter, activator, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget));
|
||||||
} else if(StrContains(sceneFile, "warnsmoker") > -1) {
|
} else if(StrContains(sceneFile, "warnsmoker") > -1) {
|
||||||
SpawnSpecialForTarget(Special_Smoker, activator, view_as<int>(Special_OnTarget));
|
SpawnSpecialForTarget(Special_Smoker, activator, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget));
|
||||||
} else if(StrContains(sceneFile, "warnspitter") > -1) {
|
} else if(StrContains(sceneFile, "warnspitter") > -1) {
|
||||||
SpawnSpecialForTarget(Special_Spitter, activator, view_as<int>(Special_OnTarget));
|
SpawnSpecialForTarget(Special_Spitter, activator, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget));
|
||||||
} else if(StrContains(sceneFile, "warnjockey") > -1) {
|
} else if(StrContains(sceneFile, "warnjockey") > -1) {
|
||||||
SpawnSpecialForTarget(Special_Jockey, activator, view_as<int>(Special_OnTarget));
|
SpawnSpecialForTarget(Special_Jockey, activator, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget));
|
||||||
} else if(StrContains(sceneFile, "warncharger") > -1) {
|
} else if(StrContains(sceneFile, "warncharger") > -1) {
|
||||||
SpawnSpecialForTarget(Special_Charger, activator, view_as<int>(Special_OnTarget));
|
SpawnSpecialForTarget(Special_Charger, activator, view_as<int>(Special_OnTarget) | view_as<int>(Special_AlwaysTarget));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Trolls[vocalizeSpecials].activeFlagClients[activator] & 1) {
|
if(Trolls[vocalizeSpecials].activeFlagClients[activator] & 1) {
|
||||||
|
@ -889,7 +903,7 @@ public Action SoundHook(int clients[MAXPLAYERS], int& numClients, char sample[PL
|
||||||
|
|
||||||
lastCrescendoUser = lastButtonUser;
|
lastCrescendoUser = lastButtonUser;
|
||||||
if(IsPlayerFarDistance(lastButtonUser, AUTOPUNISH_FLOW_MIN_DISTANCE)) {
|
if(IsPlayerFarDistance(lastButtonUser, AUTOPUNISH_FLOW_MIN_DISTANCE)) {
|
||||||
NotifyAllAdmins("Autopunishing player %N for activation of event far from team", lastButtonUser);
|
PrintChatToAdmins("Autopunishing player %N for activation of event far from team", lastButtonUser);
|
||||||
ShowActivityEx(0, "[FTT] ", "activated autopunish for crescendo activator %N (auto)", lastButtonUser);
|
ShowActivityEx(0, "[FTT] ", "activated autopunish for crescendo activator %N (auto)", lastButtonUser);
|
||||||
LogAction(0, lastButtonUser, "\"%L\" automatic autopunish for crescendo activator \"%L\"", 0, lastButtonUser);
|
LogAction(0, lastButtonUser, "\"%L\" automatic autopunish for crescendo activator \"%L\"", 0, lastButtonUser);
|
||||||
ActivateAutoPunish(lastButtonUser);
|
ActivateAutoPunish(lastButtonUser);
|
||||||
|
@ -993,7 +1007,7 @@ public Action OnAntiRush(int client, int &type, float distance) {
|
||||||
}
|
}
|
||||||
SpecialType special = view_as<SpecialType>(GetRandomInt(1,6));
|
SpecialType special = view_as<SpecialType>(GetRandomInt(1,6));
|
||||||
fLastAntiRushEvent[client] = GetGameTime();
|
fLastAntiRushEvent[client] = GetGameTime();
|
||||||
SpawnSpecialForTarget(special, client, view_as<int>(Special_SpawnDirectOnFailure | Special_OnTarget));
|
SpawnSpecialForTarget(special, client, view_as<int>(Special_SpawnDirectOnFailure | Special_OnTarget | Special_AlwaysTarget));
|
||||||
PrintToConsoleAll("[FTT] Spawning anti-rush special on %N (dist=%f) (special=%s)", client, distance, SPECIAL_NAMES[view_as<int>(special)-1]);
|
PrintToConsoleAll("[FTT] Spawning anti-rush special on %N (dist=%f) (special=%s)", client, distance, SPECIAL_NAMES[view_as<int>(special)-1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1018,7 +1032,7 @@ public void L4D2_CInsectSwarm_CanHarm_Post(int acid, int spitter, int entity) {
|
||||||
|
|
||||||
public void Event_EnteredSpit(Event event, const char[] name, bool dontBroadcast) {
|
public void Event_EnteredSpit(Event event, const char[] name, bool dontBroadcast) {
|
||||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||||
if(Trolls[stickyGooIndex].IsActive(stickyGooIndex)) {
|
if(Trolls[stickyGooIndex].IsActive(client)) {
|
||||||
int flags = Trolls[stickyGooIndex].activeFlagClients[client];
|
int flags = Trolls[stickyGooIndex].activeFlagClients[client];
|
||||||
float movement = 0.0;
|
float movement = 0.0;
|
||||||
if(flags & 1) movement = 0.9;
|
if(flags & 1) movement = 0.9;
|
||||||
|
@ -1059,3 +1073,18 @@ void Event_HealSuccess(Event event, const char[] name, bool dontBroadcast) {
|
||||||
StopHealingBots();
|
StopHealingBots();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void L4D_OnVomitedUpon_Post(int victim, int attacker, bool boomerExplosion) {
|
||||||
|
if(Trolls[t_slotRouletteIndex].IsActive(victim)) {
|
||||||
|
SetSlot(victim, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Event_Incapped(Event event, const char[] name, bool dontBroadcast) {
|
||||||
|
int client = GetClientOfUserId(event.GetInt("subject"));
|
||||||
|
int attacker = GetClientOfUserId(event.GetInt("attacker"));
|
||||||
|
if(client > 0 && attacker > 0 && attacker <= MaxClients && IsFakeClient(attacker) && GetClientTeam(attacker) == 3) {
|
||||||
|
if(pdata[attacker].specialAttackFlags & view_as<int>(SPI_KillOnTargetIncap)) {
|
||||||
|
ForcePlayerSuicide(attacker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,14 +44,14 @@ public int Insta_SpecialHandler(Menu menu, MenuAction action, int client, int pa
|
||||||
}
|
}
|
||||||
SpecialType special = view_as<SpecialType>(specialInt);
|
SpecialType special = view_as<SpecialType>(specialInt);
|
||||||
if(inFace) {
|
if(inFace) {
|
||||||
if(SpawnSpecialForTarget(special, target, view_as<int>(Special_OnTarget | Special_SpawnDirectOnFailure))) {
|
if(SpawnSpecialForTarget(special, target, view_as<int>(Special_OnTarget) | view_as<int>(Special_SpawnDirectOnFailure) | view_as<int>(Special_AlwaysTarget))) {
|
||||||
LogAction(client, target, "\"%L\" spawned Insta-%s™ on \"%L\"", client, SPECIAL_NAMES[specialInt-1], target);
|
LogAction(client, target, "\"%L\" spawned Insta-%s™ on \"%L\"", client, SPECIAL_NAMES[specialInt-1], target);
|
||||||
CShowActivityEx(client, "[FTT] ", "spawned {olive}Insta-%s™{default} on {olive}%N", SPECIAL_NAMES[specialInt-1], target);
|
CShowActivityEx(client, "[FTT] ", "spawned {olive}Insta-%s™{default} on {olive}%N", SPECIAL_NAMES[specialInt-1], target);
|
||||||
} else {
|
} else {
|
||||||
ReplyToCommand(client, "Could not spawn special.");
|
ReplyToCommand(client, "Could not spawn special.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(SpawnSpecialForTarget(special, target)) {
|
if(SpawnSpecialForTarget(special, target, view_as<int>(Special_AlwaysTarget))) {
|
||||||
CShowActivityEx(client, "[FTT] ", "spawned {green}Insta-%s™{default} near {green}%N", SPECIAL_NAMES[specialInt-1], target);
|
CShowActivityEx(client, "[FTT] ", "spawned {green}Insta-%s™{default} near {green}%N", SPECIAL_NAMES[specialInt-1], target);
|
||||||
LogAction(client, target, "\"%L\" spawned Insta-%s™ near \"%L\"", client, SPECIAL_NAMES[specialInt-1], target);
|
LogAction(client, target, "\"%L\" spawned Insta-%s™ near \"%L\"", client, SPECIAL_NAMES[specialInt-1], target);
|
||||||
} else {
|
} else {
|
||||||
|
@ -223,7 +223,7 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
|
||||||
|
|
||||||
public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int param2) {
|
public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int param2) {
|
||||||
if (action == MenuAction_Select) {
|
if (action == MenuAction_Select) {
|
||||||
static char info[8];
|
char info[32];
|
||||||
menu.GetItem(param2, info, sizeof(info));
|
menu.GetItem(param2, info, sizeof(info));
|
||||||
static char str[2][8];
|
static char str[2][8];
|
||||||
ExplodeString(info, "|", str, 2, 8, false);
|
ExplodeString(info, "|", str, 2, 8, false);
|
||||||
|
@ -240,13 +240,14 @@ public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int
|
||||||
} else if(slot == -2) {
|
} else if(slot == -2) {
|
||||||
ShowThrowItAllMenu(param1, userid);
|
ShowThrowItAllMenu(param1, userid);
|
||||||
} else {
|
} else {
|
||||||
|
if(!GetClientWeaponNameSmart(client, slot, info, sizeof(info))) {
|
||||||
|
strcopy(info, sizeof(info), "-unk-");
|
||||||
|
}
|
||||||
|
CShowActivityEx(param1, "[FTT] ", "activated troll {yellow}Throw It All{default} ({olive}%s|%d{default}) for \"%N\"", info, slot, client);
|
||||||
|
LogAction(param1, client, "\"%L\" activated troll \"Throw It All\" (%s) for \"%L\". ", param1, info, client);
|
||||||
ThrowItemToPlayer(client, param1, slot);
|
ThrowItemToPlayer(client, param1, slot);
|
||||||
}
|
}
|
||||||
if(slot != -2) {
|
|
||||||
LogAction(param1, client, "\"%L\" activated troll \"Throw It all\" slot=%d for \"%L\"", param1, slot, client);
|
|
||||||
ShowActivityEx(param1, "[FTT] ", "activated troll \"Throw It All\" for %N. ", client);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowThrowItAllMenu(param1, userid);
|
ShowThrowItAllMenu(param1, userid);
|
||||||
} else if (action == MenuAction_End)
|
} else if (action == MenuAction_End)
|
||||||
delete menu;
|
delete menu;
|
||||||
|
@ -404,18 +405,7 @@ void ShowTrollMenu(int client, bool isComboList) {
|
||||||
for(int i = 1; i <= MaxClients; i++) {
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
if(IsClientConnected(i) && IsClientInGame(i) && (hAllowEnemyTeam.BoolValue || GetClientTeam(i) == clientTeam)) {
|
if(IsClientConnected(i) && IsClientInGame(i) && (hAllowEnemyTeam.BoolValue || GetClientTeam(i) == clientTeam)) {
|
||||||
IntToString(GetClientUserId(i), userid, sizeof(userid));
|
IntToString(GetClientUserId(i), userid, sizeof(userid));
|
||||||
int realPlayer = L4D_GetIdlePlayerOfBot(i);
|
GetMenuDisplayName(i, display, sizeof(display));
|
||||||
// Incase player is idle, grab their bot instead of them
|
|
||||||
if(realPlayer > 0 && IsClientConnected(realPlayer)) {
|
|
||||||
if(IsPlayerAlive(i))
|
|
||||||
Format(display, sizeof(display), "%N (AFK)", realPlayer);
|
|
||||||
else
|
|
||||||
Format(display, sizeof(display), "%N (AFK/Dead)", realPlayer);
|
|
||||||
} else if(!IsPlayerAlive(i))
|
|
||||||
Format(display, sizeof(display), "%N (Dead)", i);
|
|
||||||
else {
|
|
||||||
GetClientName(i, display, sizeof(display));
|
|
||||||
}
|
|
||||||
menu.AddItem(userid, display);
|
menu.AddItem(userid, display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,11 +517,10 @@ void ShowThrowItAllMenu(int client, int userid) {
|
||||||
|
|
||||||
// Grab all the items the player has, add to menu
|
// Grab all the items the player has, add to menu
|
||||||
for(int slot = 0; slot <= 5; slot++) {
|
for(int slot = 0; slot <= 5; slot++) {
|
||||||
int item = GetPlayerWeaponSlot(victim, slot);
|
int item = GetClientWeaponNameSmart2(victim, slot, itmName, sizeof(itmName));
|
||||||
if(item > -1) {
|
if(item > -1) {
|
||||||
GetEdictClassname(item, itmName, sizeof(itmName));
|
|
||||||
Format(info, sizeof(info), "%d|%d", userid, slot);
|
Format(info, sizeof(info), "%d|%d", userid, slot);
|
||||||
itmMenu.AddItem(info, itmName[7]);
|
itmMenu.AddItem(info, itmName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,20 +174,20 @@ ArrayList GetPhrasesArray(const char[] key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stock int FindClosestClientAdminPriority(int source, bool ignoreBots, float pos[3]) {
|
stock int FindClosestClientAdminPriority(int source, float pos[3]) {
|
||||||
int c = FindClosestAdmin(source, ignoreBots, pos);
|
int c = FindClosestAdmin(source, pos);
|
||||||
if(c == -1) return FindClosestClient(source, ignoreBots, pos);
|
if(c == -1) return FindClosestClient(source, ignoreBots, pos);
|
||||||
else return c;
|
else return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FindClosestClient(int source, bool ignoreBots, float pos[3]) {
|
stock int FindClosestClient(int source, bool ignoreBots, float pos[3]) {
|
||||||
int closest = -1;
|
int closest = -1;
|
||||||
float minDist = -1.0;
|
float minDist = -1.0;
|
||||||
static float pos1[3];
|
static float pos1[3];
|
||||||
static float pos2[3];
|
static float pos2[3];
|
||||||
GetClientAbsOrigin(source, pos1);
|
GetClientAbsOrigin(source, pos1);
|
||||||
for(int i = 1; i <= MaxClients; i++) {
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && (!ignoreBots || !IsFakeClient(i)) && i != source) {
|
if(i != source && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && (!ignoreBots || !IsFakeClient(i)) ) {
|
||||||
GetClientAbsOrigin(i, pos2);
|
GetClientAbsOrigin(i, pos2);
|
||||||
float dist = GetVectorDistance(pos1, pos2);
|
float dist = GetVectorDistance(pos1, pos2);
|
||||||
if(minDist == -1.0 || dist <= minDist) {
|
if(minDist == -1.0 || dist <= minDist) {
|
||||||
|
@ -200,19 +200,16 @@ int FindClosestClient(int source, bool ignoreBots, float pos[3]) {
|
||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FindClosestAdmin(int source, bool ignoreBots, float pos[3]) {
|
stock int FindClosestAdmin(int source, float pos[3]) {
|
||||||
int closest = -1;
|
int closest = -1;
|
||||||
float minDist = -1.0;
|
float minDist = -1.0;
|
||||||
static float pos1[3];
|
static float pos1[3];
|
||||||
static float pos2[3];
|
static float pos2[3];
|
||||||
GetClientAbsOrigin(source, pos);
|
GetClientAbsOrigin(source, pos);
|
||||||
for(int i = 1; i <= MaxClients; i++) {
|
for(int i = 1; i <= MaxClients; i++) {
|
||||||
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) &&
|
if(i != source && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && !IsFakeClient(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) {
|
||||||
(ignoreBots || !IsFakeClient(i))
|
|
||||||
&& GetUserAdmin(i) != INVALID_ADMIN_ID && i != source
|
|
||||||
) {
|
|
||||||
GetClientAbsOrigin(i, pos2);
|
GetClientAbsOrigin(i, pos2);
|
||||||
float dist = GetVectorDistance(pos1, pos2);
|
float dist = GetVectorDistance(pos1, pos2, true);
|
||||||
if(minDist == -1.0 || dist <= minDist) {
|
if(minDist == -1.0 || dist <= minDist) {
|
||||||
closest = i;
|
closest = i;
|
||||||
minDist = dist;
|
minDist = dist;
|
||||||
|
@ -223,9 +220,9 @@ int FindClosestAdmin(int source, bool ignoreBots, float pos[3]) {
|
||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SpawnItem(const char[] entityName, float pos[3], float ang[3] = NULL_VECTOR) {
|
int SpawnItem(const char[] itemName, float pos[3], float ang[3] = NULL_VECTOR) {
|
||||||
static char classname[32];
|
static char classname[32];
|
||||||
Format(classname, sizeof(classname), "weapon_%s", entityName);
|
Format(classname, sizeof(classname), "weapon_%s", itemName);
|
||||||
int spawner = CreateEntityByName(classname);
|
int spawner = CreateEntityByName(classname);
|
||||||
if(spawner == -1) return -1;
|
if(spawner == -1) return -1;
|
||||||
DispatchKeyValue(spawner, "solid", "6");
|
DispatchKeyValue(spawner, "solid", "6");
|
||||||
|
@ -262,16 +259,14 @@ void ThrowItemToPlayer(int victim, int target, int slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stock void AddInFrontOf(float fVecOrigin[3], float fVecAngle[3], float fUnits, float fOutPut[3])
|
stock void AddInFrontOf(float fVecOrigin[3], float fVecAngle[3], float fUnits, float fOutPut[3]) {
|
||||||
{
|
|
||||||
float fVecView[3]; GetViewVector(fVecAngle, fVecView);
|
float fVecView[3]; GetViewVector(fVecAngle, fVecView);
|
||||||
|
|
||||||
fOutPut[0] = fVecView[0] * fUnits + fVecOrigin[0];
|
fOutPut[0] = fVecView[0] * fUnits + fVecOrigin[0];
|
||||||
fOutPut[1] = fVecView[1] * fUnits + fVecOrigin[1];
|
fOutPut[1] = fVecView[1] * fUnits + fVecOrigin[1];
|
||||||
fOutPut[2] = fVecView[2] * fUnits + fVecOrigin[2];
|
fOutPut[2] = fVecView[2] * fUnits + fVecOrigin[2];
|
||||||
}
|
}
|
||||||
stock void GetViewVector(float fVecAngle[3], float fOutPut[3])
|
stock void GetViewVector(float fVecAngle[3], float fOutPut[3]) {
|
||||||
{
|
|
||||||
fOutPut[0] = Cosine(fVecAngle[1] / (180 / FLOAT_PI));
|
fOutPut[0] = Cosine(fVecAngle[1] / (180 / FLOAT_PI));
|
||||||
fOutPut[1] = Sine(fVecAngle[1] / (180 / FLOAT_PI));
|
fOutPut[1] = Sine(fVecAngle[1] / (180 / FLOAT_PI));
|
||||||
fOutPut[2] = -Sine(fVecAngle[0] / (180 / FLOAT_PI));
|
fOutPut[2] = -Sine(fVecAngle[0] / (180 / FLOAT_PI));
|
||||||
|
@ -297,60 +292,23 @@ stock void LookAtClient(int iClient, int iTarget) {
|
||||||
|
|
||||||
|
|
||||||
stock int GetClientRealHealth(int client) {
|
stock int GetClientRealHealth(int client) {
|
||||||
//First filter -> Must be a valid client, successfully in-game and not an spectator (The dont have health).
|
if(!client || !IsValidEntity(client) || !IsClientInGame(client) || !IsPlayerAlive(client) || IsClientObserver(client)) {
|
||||||
if(!client
|
|
||||||
|| !IsValidEntity(client)
|
|
||||||
|| !IsClientInGame(client)
|
|
||||||
|| !IsPlayerAlive(client)
|
|
||||||
|| IsClientObserver(client))
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
} else if(GetClientTeam(client) != 2) {
|
||||||
|
|
||||||
//If the client is not on the survivors team, then just return the normal client health.
|
|
||||||
if(GetClientTeam(client) != 2)
|
|
||||||
{
|
|
||||||
return GetClientHealth(client);
|
return GetClientHealth(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
//First, we get the amount of temporal health the client has
|
|
||||||
float buffer = GetEntPropFloat(client, Prop_Send, "m_healthBuffer");
|
float buffer = GetEntPropFloat(client, Prop_Send, "m_healthBuffer");
|
||||||
|
float tempHealth = 0.0;
|
||||||
//We declare the permanent and temporal health variables
|
if(buffer > 0.0) {
|
||||||
float TempHealth;
|
|
||||||
int PermHealth = GetClientHealth(client);
|
|
||||||
|
|
||||||
//In case the buffer is 0 or less, we set the temporal health as 0, because the client has not used any pills or adrenaline yet
|
|
||||||
if(buffer <= 0.0)
|
|
||||||
{
|
|
||||||
TempHealth = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//In case it is higher than 0, we proceed to calculate the temporl health
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//This is the difference between the time we used the temporal item, and the current time
|
|
||||||
float difference = GetGameTime() - GetEntPropFloat(client, Prop_Send, "m_healthBufferTime");
|
float difference = GetGameTime() - GetEntPropFloat(client, Prop_Send, "m_healthBufferTime");
|
||||||
|
float decay = FindConVar("pain_pills_decay_rate").FloatValue;
|
||||||
//We get the decay rate from this convar (Note: Adrenaline uses this value)
|
float constant = 1.0 / decay;
|
||||||
float decay = GetConVarFloat(FindConVar("pain_pills_decay_rate"));
|
tempHealth = buffer - (difference / constant);
|
||||||
|
if(tempHealth < 0.0) {
|
||||||
//This is a constant we create to determine the amount of health. This is the amount of time it has to pass
|
tempHealth = 0.0;
|
||||||
//before 1 Temporal HP is consumed.
|
}
|
||||||
float constant = 1.0/decay;
|
|
||||||
|
|
||||||
//Then we do the calcs
|
|
||||||
TempHealth = buffer - (difference / constant);
|
|
||||||
}
|
}
|
||||||
|
return RoundToFloor(GetClientHealth(client) + tempHealth);
|
||||||
//If the temporal health resulted less than 0, then it is just 0.
|
|
||||||
if(TempHealth < 0.0)
|
|
||||||
{
|
|
||||||
TempHealth = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Return the value
|
|
||||||
return RoundToFloor(PermHealth + TempHealth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -497,10 +455,7 @@ void StopHealingBots(bool dontKill = false) {
|
||||||
KickClient(i);
|
KickClient(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!dontKill && IsValidHandle(stopHealingTimer)) {
|
delete stopHealingTimer;
|
||||||
delete stopHealingTimer;
|
|
||||||
}
|
|
||||||
stopHealingTimer = null;
|
|
||||||
if(hAbmAutoHard != null) hAbmAutoHard.IntValue = wasAbmAutoHard;
|
if(hAbmAutoHard != null) hAbmAutoHard.IntValue = wasAbmAutoHard;
|
||||||
if(hSbFixEnabled != null) hSbFixEnabled.BoolValue = wasSbFixEnabled;
|
if(hSbFixEnabled != null) hSbFixEnabled.BoolValue = wasSbFixEnabled;
|
||||||
}
|
}
|
||||||
|
@ -580,3 +535,46 @@ stock void PrintToConsoleAdmins(const char[] format, any ...) {
|
||||||
}
|
}
|
||||||
PrintToServer("%s", buffer);
|
PrintToServer("%s", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shakes a client's screen with the specified amptitude,
|
||||||
|
* frequency & duration.
|
||||||
|
*
|
||||||
|
* @param client Client Index.
|
||||||
|
* @param amplitude Shake magnitude/amplitude.
|
||||||
|
* @param frequency Shake noise frequency.
|
||||||
|
* @param duration Shake lasts this long.
|
||||||
|
* @return True on success, false otherwise.
|
||||||
|
*/
|
||||||
|
stock bool ShakePlayer(int client, float amplitude=50.0, float frequency=150.0, float duration=3.0) {
|
||||||
|
if (amplitude <= 0.0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Handle userMessage = StartMessageOne("Shake", client);
|
||||||
|
if (userMessage == INVALID_HANDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
|
||||||
|
&& GetUserMessageType() == UM_Protobuf) {
|
||||||
|
PbSetInt(userMessage, "command", 0);
|
||||||
|
PbSetFloat(userMessage, "local_amplitude", amplitude);
|
||||||
|
PbSetFloat(userMessage, "frequency", frequency);
|
||||||
|
PbSetFloat(userMessage, "duration", duration);
|
||||||
|
} else {
|
||||||
|
BfWriteByte(userMessage, 0); // Shake Command
|
||||||
|
BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude
|
||||||
|
BfWriteFloat(userMessage, frequency); // shake noise frequency
|
||||||
|
BfWriteFloat(userMessage, duration); // shake lasts this long
|
||||||
|
}
|
||||||
|
EndMessage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSlot(int client, int slot) {
|
||||||
|
if(slot == -1)
|
||||||
|
slot = GetRandomInt(0, 4);
|
||||||
|
static char slotStr[8];
|
||||||
|
Format(slotStr, sizeof(slotStr), "slot%d", slot);
|
||||||
|
ClientCommand(client, slotStr);
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ ArrayList g_spSpawnQueue;
|
||||||
// target client index
|
// target client index
|
||||||
stock bool SpawnSpecialForTarget(SpecialType specialType, int target, int spawnFlags = view_as<int>(Special_Anywhere)) {
|
stock bool SpawnSpecialForTarget(SpecialType specialType, int target, int spawnFlags = view_as<int>(Special_Anywhere)) {
|
||||||
static float pos[3];
|
static float pos[3];
|
||||||
int internalFlags = view_as<int>(SPI_AlwaysTarget);
|
|
||||||
if(spawnFlags & view_as<int>(Special_OnTarget)) {
|
if(spawnFlags & view_as<int>(Special_OnTarget)) {
|
||||||
static float ang[3];
|
static float ang[3];
|
||||||
static float testPos[3];
|
static float testPos[3];
|
||||||
|
@ -35,9 +35,6 @@ stock bool SpawnSpecialForTarget(SpecialType specialType, int target, int spawnF
|
||||||
GetClientAbsOrigin(target, pos);
|
GetClientAbsOrigin(target, pos);
|
||||||
GetClientEyeAngles(target, ang);
|
GetClientEyeAngles(target, ang);
|
||||||
|
|
||||||
if(specialType == Special_Boomer || specialType == Special_Spitter)
|
|
||||||
internalFlags |= view_as<int>(SPI_KillOnSpawn);
|
|
||||||
|
|
||||||
if(specialType == Special_Jockey || specialType == Special_Boomer || specialType == Special_Spitter) { // Else spawn a little bit off, and above (above for jockeys)
|
if(specialType == Special_Jockey || specialType == Special_Boomer || specialType == Special_Spitter) { // Else spawn a little bit off, and above (above for jockeys)
|
||||||
pos[2] += 25.0;
|
pos[2] += 25.0;
|
||||||
pos[0] += 5.0;
|
pos[0] += 5.0;
|
||||||
|
@ -45,31 +42,49 @@ stock bool SpawnSpecialForTarget(SpecialType specialType, int target, int spawnF
|
||||||
float minDistance = GetIdealMinDistance(specialType);
|
float minDistance = GetIdealMinDistance(specialType);
|
||||||
GetHorizontalPositionFromOrigin(pos, ang, minDistance, testPos);
|
GetHorizontalPositionFromOrigin(pos, ang, minDistance, testPos);
|
||||||
if(!FindSuitablePosition(pos, testPos, minDistance, 100)) {
|
if(!FindSuitablePosition(pos, testPos, minDistance, 100)) {
|
||||||
PrintToServer("[FTT] Could not find suitable position, falling back");
|
PrintToServer("[FTT] Could not find suitable position, trying in front");
|
||||||
if(spawnFlags & view_as<int>(Special_SpawnDirectOnFailure))
|
GetHorizontalPositionFromOrigin(pos, ang, -minDistance, testPos);
|
||||||
GetClientAbsOrigin(target, pos);
|
if(!FindSuitablePosition(pos, testPos, minDistance, 50)) {
|
||||||
else
|
PrintToServer("[FTT] Could not find suitable position, falling back");
|
||||||
L4D_GetRandomPZSpawnPosition(target, view_as<int>(specialType), 10, testPos);
|
if(spawnFlags & view_as<int>(Special_SpawnDirectOnFailure))
|
||||||
|
GetClientAbsOrigin(target, testPos);
|
||||||
|
else
|
||||||
|
L4D_GetRandomPZSpawnPosition(target, view_as<int>(specialType), 10, testPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pos = testPos;
|
pos = testPos;
|
||||||
}
|
}
|
||||||
pos[2] += 1.0;
|
pos[2] += 1.0;
|
||||||
return SpawnSpecialAtPosition(specialType, pos, ang, target, internalFlags);
|
return SpawnSpecialAtPosition(specialType, pos, ang, target, spawnFlags);
|
||||||
} else {
|
|
||||||
if(L4D_GetRandomPZSpawnPosition(target, view_as<int>(specialType), 10, pos)) {
|
|
||||||
return SpawnSpecialAtPosition(specialType, pos, NULL_VECTOR, target, internalFlags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
// Spawn via director, or fail
|
||||||
|
if(!L4D_GetRandomPZSpawnPosition(target, view_as<int>(specialType), 10, pos)) {
|
||||||
|
if(spawnFlags & view_as<int>(Special_SpawnDirectOnFailure))
|
||||||
|
GetClientAbsOrigin(target, pos);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return SpawnSpecialAtPosition(specialType, pos, NULL_VECTOR, target, spawnFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target is optional
|
// Target is optional
|
||||||
stock bool SpawnSpecialAtPosition(SpecialType special, const float destination[3], const float angle[3], int target = 0, int flags = 0) {
|
stock bool SpawnSpecialAtPosition(SpecialType specialType, const float destination[3], const float angle[3], int target = 0, int spawnFlags = 0) {
|
||||||
|
int internalFlags = 0;
|
||||||
|
if(spawnFlags & view_as<int>(Special_AlwaysTarget)) {
|
||||||
|
internalFlags |= view_as<int>(SPI_AlwaysTarget);
|
||||||
|
}
|
||||||
|
if(spawnFlags & view_as<int>(Special_KillOnIncap)) {
|
||||||
|
internalFlags |= view_as<int>(SPI_KillOnTargetIncap);
|
||||||
|
}
|
||||||
|
if(spawnFlags & view_as<int>(Special_OnTarget)) {
|
||||||
|
if(specialType == Special_Boomer || specialType == Special_Spitter)
|
||||||
|
internalFlags |= view_as<int>(SPI_KillOnSpawn);
|
||||||
|
}
|
||||||
SpecialSpawnRequest request;
|
SpecialSpawnRequest request;
|
||||||
request.type = special;
|
request.type = specialType;
|
||||||
if(target)
|
if(target)
|
||||||
request.targetUserId = GetClientUserId(target);
|
request.targetUserId = GetClientUserId(target);
|
||||||
request.flags = flags;
|
request.flags = internalFlags;
|
||||||
request.position = destination;
|
request.position = destination;
|
||||||
request.angle = angle;
|
request.angle = angle;
|
||||||
g_spSpawnQueue.PushArray(request);
|
g_spSpawnQueue.PushArray(request);
|
||||||
|
@ -100,27 +115,29 @@ bool ProcessSpecialQueue() {
|
||||||
CreateTimer(0.1, Timer_KickBot, bot);
|
CreateTimer(0.1, Timer_KickBot, bot);
|
||||||
}
|
}
|
||||||
CheatCommand(target, "z_spawn_old", SPECIAL_NAMES[view_as<int>(spActiveRequest.type) - 1], "auto");
|
CheatCommand(target, "z_spawn_old", SPECIAL_NAMES[view_as<int>(spActiveRequest.type) - 1], "auto");
|
||||||
|
return true;
|
||||||
} else if(spActiveRequest.type == Special_Witch) {
|
} else if(spActiveRequest.type == Special_Witch) {
|
||||||
int witch = L4D2_SpawnWitch(spActiveRequest.position, spActiveRequest.angle);
|
int witch = L4D2_SpawnWitch(spActiveRequest.position, spActiveRequest.angle);
|
||||||
DataPack pack;
|
DataPack pack;
|
||||||
CreateDataTimer(0.2, Timer_SetWitchTarget, pack);
|
CreateDataTimer(0.2, Timer_SetWitchTarget, pack);
|
||||||
pack.WriteCell(witch);
|
pack.WriteCell(witch);
|
||||||
pack.WriteCell(GetClientUserId(target));
|
pack.WriteCell(spActiveRequest.targetUserId);
|
||||||
if(witch != -1)
|
if(witch != -1)
|
||||||
SetWitchTarget(witch, target);
|
SetWitchTarget(witch, target);
|
||||||
|
spIsActive = false;
|
||||||
return ProcessSpecialQueue();
|
return ProcessSpecialQueue();
|
||||||
} else if(spActiveRequest.type == Special_Tank) {
|
} else if(spActiveRequest.type == Special_Tank) {
|
||||||
// BypassLimit();
|
// BypassLimit();
|
||||||
int tank = L4D2_SpawnTank(spActiveRequest.position, spActiveRequest.angle);
|
int tank = L4D2_SpawnTank(spActiveRequest.position, spActiveRequest.angle);
|
||||||
if(tank > 0 && IsClientConnected(tank)) {
|
if(tank > 0 && IsClientConnected(tank)) {
|
||||||
TeleportEntity(tank, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
|
TeleportEntity(tank, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
|
||||||
PrintToConsoleAll("[ftt/debug] requested tank spawned %d -> %N", tank, target)
|
|
||||||
pdata[tank].attackerTargetUid = spActiveRequest.targetUserId;
|
pdata[tank].attackerTargetUid = spActiveRequest.targetUserId;
|
||||||
pdata[tank].specialAttackFlags = view_as<int>(SPI_AlwaysTarget);
|
pdata[tank].specialAttackFlags = view_as<int>(SPI_AlwaysTarget);
|
||||||
}
|
}
|
||||||
|
spIsActive = false;
|
||||||
return ProcessSpecialQueue();
|
return ProcessSpecialQueue();
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
spIsActive = false;
|
spIsActive = false;
|
||||||
return false;
|
return false;
|
||||||
|
@ -146,8 +163,8 @@ stock SpecialType GetSpecialType(const char[] input) {
|
||||||
stock bool FindSuitablePosition(const float pos[3], float outputPos[3], float minDistance = 19000.0, int tries = 100) {
|
stock bool FindSuitablePosition(const float pos[3], float outputPos[3], float minDistance = 19000.0, int tries = 100) {
|
||||||
outputPos = pos;
|
outputPos = pos;
|
||||||
for(int i = tries; i > 0; i--) {
|
for(int i = tries; i > 0; i--) {
|
||||||
// int nav = L4D_GetNearestNavArea(pos);
|
// Shift position aroudn randomly
|
||||||
outputPos[1] += GetRandomFloat(-30.0, 30.0);
|
outputPos[1] += GetRandomFloat(-35.0, 35.0);
|
||||||
float dist = GetVectorDistance(outputPos, pos, true);
|
float dist = GetVectorDistance(outputPos, pos, true);
|
||||||
if(dist >= minDistance && L4D2Direct_GetTerrorNavArea(outputPos) != Address_Null) { //5m^2
|
if(dist >= minDistance && L4D2Direct_GetTerrorNavArea(outputPos) != Address_Null) { //5m^2
|
||||||
return true;
|
return true;
|
||||||
|
@ -191,7 +208,7 @@ stock bool GetGroundBehind(int client, float vPos[3], float vAng[3]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
stock bool RayFilter_NonClient(int entity, int contentsMask) {
|
stock bool RayFilter_NonClient(int entity, int contentsMask) {
|
||||||
if (entity < 1 || entity > MaxClients) {
|
if (entity <= 0 || entity > MaxClients) {
|
||||||
if (IsValidEntity(entity)) {
|
if (IsValidEntity(entity)) {
|
||||||
static char eClass[128];
|
static char eClass[128];
|
||||||
if (GetEntityClassname(entity, eClass, sizeof(eClass))) {
|
if (GetEntityClassname(entity, eClass, sizeof(eClass))) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
public Action Timer_ThrowTimer(Handle timer) {
|
Action Timer_ThrowTimer(Handle timer) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(int i = 1; i < MaxClients; i++) {
|
for(int i = 1; i < MaxClients; i++) {
|
||||||
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && IsTrollActive(i, "Throw It All")) {
|
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && IsTrollActive(i, "Throw It All")) {
|
||||||
|
@ -17,20 +17,20 @@ Action Timer_RandomVelocity(Handle h, int client) {
|
||||||
return Plugin_Stop;
|
return Plugin_Stop;
|
||||||
}
|
}
|
||||||
float bounds = 50.0;
|
float bounds = 50.0;
|
||||||
if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 2) bounds = 100.0;
|
if(Trolls[t_randomizeVelocityIndex].activeFlagClients[client] & 2) bounds = 100.0;
|
||||||
else if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 4) bounds = 200.0;
|
else if(Trolls[t_randomizeVelocityIndex].activeFlagClients[client] & 4) bounds = 200.0;
|
||||||
else if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 8) bounds = 500.0;
|
else if(Trolls[t_randomizeVelocityIndex].activeFlagClients[client] & 8) bounds = 500.0;
|
||||||
else if(Trolls[t_randomizeAnglesIndex].activeFlagClients[client] & 16) bounds = 1000.0;
|
else if(Trolls[t_randomizeVelocityIndex].activeFlagClients[client] & 16) bounds = 1000.0;
|
||||||
float vel[3];
|
float vel[3];
|
||||||
GetEntPropVector(client, Prop_Data, "m_vecVelocity", vel);
|
GetEntPropVector(client, Prop_Data, "m_vecVelocity", vel);
|
||||||
vel[0] += GetRandomFloat(-bounds, bounds);
|
vel[0] += GetRandomFloat(-bounds, bounds);
|
||||||
vel[1] += GetRandomFloat(-bounds, bounds);
|
vel[1] += GetRandomFloat(-bounds, bounds);
|
||||||
vel[2] += GetRandomFloat(-100.0, 150.0);
|
vel[2] += GetRandomFloat(-20.0, 100.0);
|
||||||
SetAbsVelocity(client, vel);
|
SetAbsVelocity(client, vel);
|
||||||
return Plugin_Continue;
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_Main(Handle timer) {
|
Action Timer_Main(Handle timer) {
|
||||||
static int loopTick;
|
static int loopTick;
|
||||||
|
|
||||||
static int slowDrainIndex;
|
static int slowDrainIndex;
|
||||||
|
@ -81,7 +81,7 @@ public Action Timer_Main(Handle timer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(Trolls[tempHealthQuickDrainIndex].IsActive(i)) {
|
if(Trolls[tempHealthQuickDrainIndex].IsActive(i)) {
|
||||||
if(loopTick % 2 == 0) {
|
if(loopTick % 3 == 0) {
|
||||||
float bufferTime = GetEntPropFloat(i, Prop_Send, "m_healthBufferTime");
|
float bufferTime = GetEntPropFloat(i, Prop_Send, "m_healthBufferTime");
|
||||||
float tempHealth = L4D_GetTempHealth(i);
|
float tempHealth = L4D_GetTempHealth(i);
|
||||||
if(tempHealth > 0.0) {
|
if(tempHealth > 0.0) {
|
||||||
|
@ -115,6 +115,46 @@ public Action Timer_Main(Handle timer) {
|
||||||
SetEntProp(primaryWpn, Prop_Send, "m_iClip1", GetRandomInt(0, maxCap));
|
SetEntProp(primaryWpn, Prop_Send, "m_iClip1", GetRandomInt(0, maxCap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(Trolls[t_vomitPlayerIndex].IsActive(i)) {
|
||||||
|
if(loopTick % 4 == 0) {
|
||||||
|
L4D_CTerrorPlayer_OnVomitedUpon(i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Trolls[t_shakeyCameraIndex].IsActive(i)) {
|
||||||
|
float amplitude = 1.0;
|
||||||
|
float freq = 1.0;
|
||||||
|
if(Trolls[t_shakeyCameraIndex].activeFlagClients[i] & 1) {
|
||||||
|
amplitude = 1.0;
|
||||||
|
freq = 1.0;
|
||||||
|
} else if(Trolls[t_shakeyCameraIndex].activeFlagClients[i] & 2) {
|
||||||
|
amplitude = 5.0;
|
||||||
|
freq = 5.0;
|
||||||
|
} else if(Trolls[t_shakeyCameraIndex].activeFlagClients[i] & 4) {
|
||||||
|
amplitude = 20.0;
|
||||||
|
freq = 20.0;
|
||||||
|
} else if(Trolls[t_shakeyCameraIndex].activeFlagClients[i] & 8) {
|
||||||
|
amplitude = 50.0;
|
||||||
|
freq = 50.0;
|
||||||
|
} else if(Trolls[t_shakeyCameraIndex].activeFlagClients[i] & 16) {
|
||||||
|
amplitude = 100.0;
|
||||||
|
freq = 200.0;
|
||||||
|
}
|
||||||
|
ShakePlayer(i, amplitude, freq, MAIN_TIMER_INTERVAL_S + 1.0);
|
||||||
|
}
|
||||||
|
if(Trolls[t_slotRouletteIndex].IsActive(i) && Trolls[t_slotRouletteIndex].activeFlagClients[i] & 8) {
|
||||||
|
float chance = 1.0;
|
||||||
|
if(Trolls[t_slotRouletteIndex].activeFlagClients[i] & 16) {
|
||||||
|
chance = 0.2;
|
||||||
|
} else if(Trolls[t_slotRouletteIndex].activeFlagClients[i] & 32) {
|
||||||
|
chance = 0.4;
|
||||||
|
} else if(Trolls[t_slotRouletteIndex].activeFlagClients[i] & 64) {
|
||||||
|
chance = 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GetURandomFloat() < chance) {
|
||||||
|
SetSlot(i, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(++loopTick >= 60) {
|
if(++loopTick >= 60) {
|
||||||
|
@ -122,8 +162,28 @@ public Action Timer_Main(Handle timer) {
|
||||||
}
|
}
|
||||||
return Plugin_Continue;
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
Action Timer_SlotRoulette(Handle h, int client) {
|
||||||
|
if(!IsClientConnected(client)) {
|
||||||
|
Trolls[t_slotRouletteIndex].timerHandles[client] = null;
|
||||||
|
return Plugin_Stop;
|
||||||
|
}
|
||||||
|
if(Trolls[t_slotRouletteIndex].activeFlagClients[client] & 8) {
|
||||||
|
float chance = 1.0;
|
||||||
|
if(Trolls[t_slotRouletteIndex].activeFlagClients[client] & 16) {
|
||||||
|
chance = 0.1;
|
||||||
|
} else if(Trolls[t_slotRouletteIndex].activeFlagClients[client] & 32) {
|
||||||
|
chance = 0.3;
|
||||||
|
} else if(Trolls[t_slotRouletteIndex].activeFlagClients[client] & 64) {
|
||||||
|
chance = 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
public Action Timer_GivePistol(Handle timer, int user) {
|
if(GetURandomFloat() < chance) {
|
||||||
|
SetSlot(client, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
Action Timer_GivePistol(Handle timer, int user) {
|
||||||
int client = GetClientOfUserId(user);
|
int client = GetClientOfUserId(user);
|
||||||
if(client > 0) {
|
if(client > 0) {
|
||||||
int flags = GetCommandFlags("give");
|
int flags = GetCommandFlags("give");
|
||||||
|
@ -134,7 +194,7 @@ public Action Timer_GivePistol(Handle timer, int user) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_ThrowWeapon(Handle timer, Handle pack) {
|
Action Timer_ThrowWeapon(Handle timer, Handle pack) {
|
||||||
ResetPack(pack);
|
ResetPack(pack);
|
||||||
float dest[3];
|
float dest[3];
|
||||||
dest[0] = ReadPackFloat(pack);
|
dest[0] = ReadPackFloat(pack);
|
||||||
|
@ -161,7 +221,7 @@ public Action Timer_ThrowWeapon(Handle timer, Handle pack) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_ResetAutoPunish(Handle timer, int user) {
|
Action Timer_ResetAutoPunish(Handle timer, int user) {
|
||||||
int client = GetClientOfUserId(user);
|
int client = GetClientOfUserId(user);
|
||||||
if(client) {
|
if(client) {
|
||||||
if(hAutoPunish.IntValue & 2 == 2)
|
if(hAutoPunish.IntValue & 2 == 2)
|
||||||
|
@ -172,7 +232,7 @@ public Action Timer_ResetAutoPunish(Handle timer, int user) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_NextWitchSet(Handle timer, DataPack pack) {
|
Action Timer_NextWitchSet(Handle timer, DataPack pack) {
|
||||||
pack.Reset();
|
pack.Reset();
|
||||||
int client = GetClientOfUserId(pack.ReadCell());
|
int client = GetClientOfUserId(pack.ReadCell());
|
||||||
int witch = pack.ReadCell();
|
int witch = pack.ReadCell();
|
||||||
|
@ -180,20 +240,20 @@ public Action Timer_NextWitchSet(Handle timer, DataPack pack) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_KickBot(Handle timer, int client) {
|
Action Timer_KickBot(Handle timer, int client) {
|
||||||
if(IsClientInGame(client) && (!IsClientInKickQueue(client))) {
|
if(IsClientInGame(client) && !IsClientInKickQueue(client) && IsFakeClient(client)) {
|
||||||
if(IsFakeClient(client)) KickClient(client);
|
KickClient(client);
|
||||||
}
|
}
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_Delete(Handle h, int id) {
|
Action Timer_Delete(Handle h, int id) {
|
||||||
if(IsValidEntity(id))
|
if(IsValidEntity(id))
|
||||||
AcceptEntityInput(id, "Kill");
|
AcceptEntityInput(id, "Kill");
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_ShootReverse(Handle h, DataPack pack) {
|
Action Timer_ShootReverse(Handle h, DataPack pack) {
|
||||||
pack.Reset();
|
pack.Reset();
|
||||||
int attacker = pack.ReadCell();
|
int attacker = pack.ReadCell();
|
||||||
int target = pack.ReadCell();
|
int target = pack.ReadCell();
|
||||||
|
@ -221,8 +281,9 @@ public Action Timer_ShootReverse(Handle h, DataPack pack) {
|
||||||
return Plugin_Stop;
|
return Plugin_Stop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// We check if the special never spawned (g_iSpId never advances, and run the next in queue)
|
||||||
public Action Timer_CheckSpecialSpawned(Handle h, int id) {
|
// Prevents the queue from stalling
|
||||||
|
Action Timer_CheckSpecialSpawned(Handle h, int id) {
|
||||||
if(g_iSpId == id) {
|
if(g_iSpId == id) {
|
||||||
PrintToServer("[FTT] Special did not spawn in time, continuing.");
|
PrintToServer("[FTT] Special did not spawn in time, continuing.");
|
||||||
g_iSpId++;
|
g_iSpId++;
|
||||||
|
@ -231,7 +292,7 @@ public Action Timer_CheckSpecialSpawned(Handle h, int id) {
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action Timer_CheckIsInSpit(Handle h, int userid) {
|
Action Timer_CheckIsInSpit(Handle h, int userid) {
|
||||||
int client = GetClientOfUserId(userid);
|
int client = GetClientOfUserId(userid);
|
||||||
if(client && GetGameTime() - pdata[userid].lastInSpitTime > 3.0) {
|
if(client && GetGameTime() - pdata[userid].lastInSpitTime > 3.0) {
|
||||||
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
||||||
|
@ -244,7 +305,7 @@ public Action Timer_CheckIsInSpit(Handle h, int userid) {
|
||||||
float CHARGER_CHECK_MIN[3] = { -15.0, -15.0, 2.0};
|
float CHARGER_CHECK_MIN[3] = { -15.0, -15.0, 2.0};
|
||||||
float CHARGER_CHECK_MAX[3] = { 15.0, 15.0, 20.0 };
|
float CHARGER_CHECK_MAX[3] = { 15.0, 15.0, 20.0 };
|
||||||
|
|
||||||
public Action Timer_CheckForChargerOpportunity(Handle h, int userid) {
|
Action Timer_CheckForChargerOpportunity(Handle h, int userid) {
|
||||||
int client = GetClientOfUserId(userid);
|
int client = GetClientOfUserId(userid);
|
||||||
if(client) {
|
if(client) {
|
||||||
int activator = GetClientOfUserId(pdata[client].smartChargeActivator);
|
int activator = GetClientOfUserId(pdata[client].smartChargeActivator);
|
||||||
|
@ -262,7 +323,7 @@ public Action Timer_CheckForChargerOpportunity(Handle h, int userid) {
|
||||||
GetHorizontalPositionFromOrigin(pos, ang, 500.0, endPos);
|
GetHorizontalPositionFromOrigin(pos, ang, 500.0, endPos);
|
||||||
TR_TraceHullFilter(endPos, pos, CHARGER_CHECK_MIN, CHARGER_CHECK_MAX, MASK_SOLID, Filter_CheckChargerValid, client);
|
TR_TraceHullFilter(endPos, pos, CHARGER_CHECK_MIN, CHARGER_CHECK_MAX, MASK_SOLID, Filter_CheckChargerValid, client);
|
||||||
if(!TR_DidHit()) {
|
if(!TR_DidHit()) {
|
||||||
SpawnSpecialAtPosition(Special_Charger, spawnPos, ang, client);
|
SpawnSpecialAtPosition(Special_Charger, spawnPos, ang, client, view_as<int>(Special_AlwaysTarget));
|
||||||
if(activator) PrintToChat(activator, "Auto charge %N successfully after %d tries", client, pdata[client].smartChargeAttempts);
|
if(activator) PrintToChat(activator, "Auto charge %N successfully after %d tries", client, pdata[client].smartChargeAttempts);
|
||||||
pdata[client].smartChargeAttempts = 0;
|
pdata[client].smartChargeAttempts = 0;
|
||||||
pdata[client].smartChargeActivator = 0;
|
pdata[client].smartChargeActivator = 0;
|
||||||
|
@ -311,14 +372,14 @@ Action Timer_SpawnHealBots(Handle h, int max) {
|
||||||
if(count < max) {
|
if(count < max) {
|
||||||
if(!AddSurvivor()) {
|
if(!AddSurvivor()) {
|
||||||
count = 0;
|
count = 0;
|
||||||
CreateTimer(0.3, Timer_SpawnHealBotsPost);
|
CreateTimer(0.5, Timer_SpawnHealBotsPost);
|
||||||
return Plugin_Stop;
|
return Plugin_Stop;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
return Plugin_Continue;
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
count = 0;
|
count = 0;
|
||||||
CreateTimer(0.3, Timer_SpawnHealBotsPost);
|
CreateTimer(0.5, Timer_SpawnHealBotsPost);
|
||||||
return Plugin_Stop;
|
return Plugin_Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,12 +391,11 @@ Action Timer_SpawnHealBotsPost(Handle h) {
|
||||||
int kit = GetPlayerWeaponSlot(i, 3);
|
int kit = GetPlayerWeaponSlot(i, 3);
|
||||||
if(kit > 0) {
|
if(kit > 0) {
|
||||||
GetEntityClassname(kit, classname, sizeof(classname));
|
GetEntityClassname(kit, classname, sizeof(classname));
|
||||||
if(!StrEqual(classname, "weapon_first_aid_kit")) {
|
if(StrEqual(classname, "weapon_first_aid_kit")) {
|
||||||
GiveClientWeapon(i, "weapon_first_aid_kit");
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
GiveClientWeapon(i, "weapon_first_aid_kit");
|
|
||||||
}
|
}
|
||||||
|
GiveClientWeapon(i, "weapon_first_aid_kit");
|
||||||
pdata[i].flags &= view_as<int>(Flag_IsTargettingHealer);
|
pdata[i].flags &= view_as<int>(Flag_IsTargettingHealer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,7 +471,7 @@ Action Timer_WaitForApex(Handle h, int entref) {
|
||||||
Action Timer_ResetGravity(Handle h, int entref) {
|
Action Timer_ResetGravity(Handle h, int entref) {
|
||||||
if(IsValidEntity(entref)) {
|
if(IsValidEntity(entref)) {
|
||||||
int entity = EntRefToEntIndex(entref);
|
int entity = EntRefToEntIndex(entref);
|
||||||
SetEntityGravity(entity, 800.0);
|
SetEntityGravity(entity, 800.0); // could pull from sv_gravity but no ones gonna notice
|
||||||
}
|
}
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
|
@ -5,6 +5,9 @@ int stickyGooIndex = 0;
|
||||||
int invertedTrollIndex;
|
int invertedTrollIndex;
|
||||||
int t_randomizeAnglesIndex;
|
int t_randomizeAnglesIndex;
|
||||||
int t_randomizeVelocityIndex;
|
int t_randomizeVelocityIndex;
|
||||||
|
int t_vomitPlayerIndex;
|
||||||
|
int t_shakeyCameraIndex;
|
||||||
|
int t_slotRouletteIndex;
|
||||||
// int fireSpitMagnetTrollIndex;
|
// int fireSpitMagnetTrollIndex;
|
||||||
|
|
||||||
void SetupTrolls() {
|
void SetupTrolls() {
|
||||||
|
@ -33,7 +36,7 @@ void SetupTrolls() {
|
||||||
/// CATEGORY: Infected
|
/// CATEGORY: Infected
|
||||||
SetCategory("Infected");
|
SetCategory("Infected");
|
||||||
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
|
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
|
||||||
SetupTroll("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant);
|
t_vomitPlayerIndex = SetupTroll("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant | TrollMod_Constant);
|
||||||
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
|
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
|
||||||
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
|
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
|
||||||
SetupTroll("Goo", "Spawns a spitter puddle underneath them", TrollMod_Instant);
|
SetupTroll("Goo", "Spawns a spitter puddle underneath them", TrollMod_Instant);
|
||||||
|
@ -85,7 +88,6 @@ void SetupTrolls() {
|
||||||
// CATEGORY: Items
|
// CATEGORY: Items
|
||||||
SetCategory("Items");
|
SetCategory("Items");
|
||||||
SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
|
SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
|
||||||
|
|
||||||
index = SetupTroll("Spicy Gas", "Gascans player picks up just ignite. Magic.", TrollMod_Constant);
|
index = SetupTroll("Spicy Gas", "Gascans player picks up just ignite. Magic.", TrollMod_Constant);
|
||||||
Trolls[index].AddFlagPrompt(false);
|
Trolls[index].AddFlagPrompt(false);
|
||||||
Trolls[index].AddFlag("Always (100%)", false);
|
Trolls[index].AddFlag("Always (100%)", false);
|
||||||
|
@ -112,6 +114,19 @@ void SetupTrolls() {
|
||||||
SetupTroll("Nerf Gun", "When they shoot it does no damage.", TrollMod_Constant);
|
SetupTroll("Nerf Gun", "When they shoot it does no damage.", TrollMod_Constant);
|
||||||
SetupTroll("Randomize Clip Ammo", "Randomly changes their clip ammo downwards", TrollMod_Constant | TrollMod_Instant);
|
SetupTroll("Randomize Clip Ammo", "Randomly changes their clip ammo downwards", TrollMod_Constant | TrollMod_Instant);
|
||||||
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
|
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
|
||||||
|
index = SetupTroll("Slot Roulette", "Randomize their slots", TrollMod_Constant);
|
||||||
|
Trolls[index].AddCustomFlagPrompt("Activations:", true);
|
||||||
|
Trolls[index].AddFlag("On Vomitted", false); // 1
|
||||||
|
Trolls[index].AddFlag("On Damage", false); // 2
|
||||||
|
Trolls[index].AddFlag("On Vocalize", false); // 4
|
||||||
|
Trolls[index].AddFlag("Periodically", true); //8
|
||||||
|
Trolls[index].AddCustomFlagPrompt("Frequency:", false, 8);
|
||||||
|
Trolls[index].AddFlag("Subtle", false); // 16
|
||||||
|
Trolls[index].AddFlag("Confusing", false); // 32
|
||||||
|
Trolls[index].AddFlag("Annoying", false); // 64
|
||||||
|
Trolls[index].AddFlag("Unusable", false); // 128
|
||||||
|
Trolls[index].SetTimer(0.3, Timer_SlotRoulette, 8);
|
||||||
|
t_slotRouletteIndex = index;
|
||||||
|
|
||||||
|
|
||||||
/// CATEGORY: Chat
|
/// CATEGORY: Chat
|
||||||
|
@ -170,7 +185,7 @@ void SetupTrolls() {
|
||||||
Trolls[index].AddFlag("3", false); // 16
|
Trolls[index].AddFlag("3", false); // 16
|
||||||
Trolls[index].AddFlag("4", true); // 32
|
Trolls[index].AddFlag("4", true); // 32
|
||||||
Trolls[index].AddFlag("5", false); // 64
|
Trolls[index].AddFlag("5", false); // 64
|
||||||
Trolls[index].AddCustomFlagPrompt("Auto Timeout", false);
|
Trolls[index].AddCustomFlagPrompt("Auto Timeout", false, 0);
|
||||||
Trolls[index].AddFlag("Until Healed / Map Change", false); // 128
|
Trolls[index].AddFlag("Until Healed / Map Change", false); // 128
|
||||||
Trolls[index].AddFlag("15 seconds", true); // 255
|
Trolls[index].AddFlag("15 seconds", true); // 255
|
||||||
Trolls[index].AddFlag("30 seconds", false); // 512
|
Trolls[index].AddFlag("30 seconds", false); // 512
|
||||||
|
@ -228,13 +243,24 @@ void SetupTrolls() {
|
||||||
Trolls[index].AddFlag("Incap On Touch", false);
|
Trolls[index].AddFlag("Incap On Touch", false);
|
||||||
Trolls[index].AddFlag("Slay On Touch", false);
|
Trolls[index].AddFlag("Slay On Touch", false);
|
||||||
Trolls[index].AddFlag("0.8x Speed", false);
|
Trolls[index].AddFlag("0.8x Speed", false);
|
||||||
|
// TODO: setup instant
|
||||||
|
index = SetupTroll("Shakey Camera", "Horrible", TrollMod_Constant);
|
||||||
|
Trolls[index].AddFlagPrompt(false);
|
||||||
// add flag: vomit on touch
|
// add flag: vomit on touch
|
||||||
|
Trolls[index].AddFlag("Annoying but playable", false);
|
||||||
|
Trolls[index].AddFlag("Bad", true);
|
||||||
|
Trolls[index].AddFlag("Sickness", false);
|
||||||
|
Trolls[index].AddFlag("Violent", false);
|
||||||
|
Trolls[index].AddFlag("Violent XX", false);
|
||||||
|
t_shakeyCameraIndex = index;
|
||||||
index = SetupTroll("Meta: Inverse", "Uhm you are not supposed to see this...", TrollMod_Instant);
|
index = SetupTroll("Meta: Inverse", "Uhm you are not supposed to see this...", TrollMod_Instant);
|
||||||
Trolls[index].hidden = true;
|
Trolls[index].hidden = true;
|
||||||
Trolls[index].AddFlagPrompt(false);
|
Trolls[index].AddFlagPrompt(false);
|
||||||
Trolls[index].AddFlag("100%", true);
|
Trolls[index].AddFlag("100%", true);
|
||||||
Trolls[index].AddFlag("50%", false);
|
Trolls[index].AddFlag("50%", false);
|
||||||
Trolls[index].AddFlag("10%", false);
|
Trolls[index].AddFlag("10%", false);
|
||||||
|
index = SetupTroll("Meta: Random", "Picks a random troll", TrollMod_Instant);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -297,7 +323,7 @@ bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier mod
|
||||||
static char wpn[32];
|
static char wpn[32];
|
||||||
GetClientWeaponName(victim, 4, wpn, sizeof(wpn));
|
GetClientWeaponName(victim, 4, wpn, sizeof(wpn));
|
||||||
if(StrEqual(wpn, "weapon_adrenaline") || StrEqual(wpn, "weapon_pain_pills")) {
|
if(StrEqual(wpn, "weapon_adrenaline") || StrEqual(wpn, "weapon_pain_pills")) {
|
||||||
ClientCommand(victim, "slot5");
|
SetSlot(victim, 5);
|
||||||
pdata[victim].flags |= view_as<int>(Flag_PendingItemGive);
|
pdata[victim].flags |= view_as<int>(Flag_PendingItemGive);
|
||||||
}else{
|
}else{
|
||||||
ReplyToCommand(activator, "User does not have pills or adrenaline");
|
ReplyToCommand(activator, "User does not have pills or adrenaline");
|
||||||
|
@ -419,7 +445,7 @@ bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier mod
|
||||||
StopHealingBots();
|
StopHealingBots();
|
||||||
return true;
|
return true;
|
||||||
} else if(healTargetPlayer != 0) {
|
} else if(healTargetPlayer != 0) {
|
||||||
if(IsValidHandle(stopHealingTimer)) {
|
if(stopHealingTimer != null) {
|
||||||
TriggerTimer(stopHealingTimer);
|
TriggerTimer(stopHealingTimer);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -493,6 +519,24 @@ bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier mod
|
||||||
CreateTimer(1.0, Timer_CheckForChargerOpportunity, GetClientUserId(victim), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
CreateTimer(1.0, Timer_CheckForChargerOpportunity, GetClientUserId(victim), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
||||||
} else if(StrEqual(troll.name, "No Rushing Us")) {
|
} else if(StrEqual(troll.name, "No Rushing Us")) {
|
||||||
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
||||||
|
} else if(StrEqual(troll.name, "Meta: Random")) {
|
||||||
|
int rndTroll = GetRandomInt(0, MAX_TROLLS);
|
||||||
|
int rndFlags = 0;
|
||||||
|
int maxFlags = Trolls[rndTroll].GetFlagCount();
|
||||||
|
int numFlags = GetRandomInt(0, maxFlags);
|
||||||
|
while(numFlags > 0) {
|
||||||
|
// Apply a random flag
|
||||||
|
rndFlags |= GetRandomInt(0, maxFlags)
|
||||||
|
maxFlags--;
|
||||||
|
}
|
||||||
|
trollModifier rndMod = Trolls[rndTroll].GetDefaultMod();
|
||||||
|
if(Trolls[rndTroll].HasMod(TrollMod_Constant) && GetURandomFloat() > 0.5) {
|
||||||
|
rndMod = TrollMod_Constant;
|
||||||
|
}
|
||||||
|
if(Trolls[rndTroll].HasMod(TrollMod_Instant) && GetURandomFloat() > 0.5) {
|
||||||
|
rndMod |= TrollMod_Instant;
|
||||||
|
}
|
||||||
|
Trolls[rndTroll].Activate(victim, activator, rndMod, rndFlags);
|
||||||
} else if(~modifier & TrollMod_Constant) {
|
} else if(~modifier & TrollMod_Constant) {
|
||||||
PrintToServer("[FTT] Warn: Possibly invalid troll, no apply action defined for \"%s\"", troll.name);
|
PrintToServer("[FTT] Warn: Possibly invalid troll, no apply action defined for \"%s\"", troll.name);
|
||||||
#if defined DEBUG
|
#if defined DEBUG
|
||||||
|
|
|
@ -71,7 +71,6 @@ public void OnPluginStart() {
|
||||||
hThrowItemInterval.AddChangeHook(Change_ThrowInterval);
|
hThrowItemInterval.AddChangeHook(Change_ThrowInterval);
|
||||||
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);
|
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);
|
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", "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");
|
||||||
hShoveFailChance = CreateConVar("sm_ftt_shove_fail_chance", "0.65", "The % chance that a shove fails", FCVAR_NONE, true, 0.0, true, 1.0);
|
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);
|
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);
|
||||||
|
@ -103,6 +102,8 @@ public void OnPluginStart() {
|
||||||
RegAdminCmd("sm_bots_attack", Command_BotsAttack, ADMFLAG_BAN, "Instructs all bots to attack a player until they have X health.");
|
RegAdminCmd("sm_bots_attack", Command_BotsAttack, ADMFLAG_BAN, "Instructs all bots to attack a player until they have X health.");
|
||||||
RegAdminCmd("sm_scharge", Command_SmartCharge, ADMFLAG_BAN, "Auto Smart charge");
|
RegAdminCmd("sm_scharge", Command_SmartCharge, ADMFLAG_BAN, "Auto Smart charge");
|
||||||
RegAdminCmd("sm_healbots", Command_HealTarget, ADMFLAG_BAN, "Make bots heal a player");
|
RegAdminCmd("sm_healbots", Command_HealTarget, ADMFLAG_BAN, "Make bots heal a player");
|
||||||
|
RegAdminCmd("sm_rff", Command_SetReverseFF, ADMFLAG_KICK, "Set reverse FF on player");
|
||||||
|
RegAdminCmd("sm_magnet", Command_SetMagnetShortcut, ADMFLAG_KICK, "");
|
||||||
|
|
||||||
HookEvent("player_spawn", Event_PlayerSpawn);
|
HookEvent("player_spawn", Event_PlayerSpawn);
|
||||||
HookEvent("player_first_spawn", Event_PlayerFirstSpawn);
|
HookEvent("player_first_spawn", Event_PlayerFirstSpawn);
|
||||||
|
@ -116,6 +117,7 @@ public void OnPluginStart() {
|
||||||
HookEvent("entered_spit", Event_EnteredSpit);
|
HookEvent("entered_spit", Event_EnteredSpit);
|
||||||
HookEvent("bot_player_replace", Event_BotPlayerSwap);
|
HookEvent("bot_player_replace", Event_BotPlayerSwap);
|
||||||
HookEvent("heal_success", Event_HealSuccess);
|
HookEvent("heal_success", Event_HealSuccess);
|
||||||
|
HookEvent("player_incapacitated", Event_Incapped);
|
||||||
|
|
||||||
AddNormalSoundHook(SoundHook);
|
AddNormalSoundHook(SoundHook);
|
||||||
|
|
||||||
|
@ -148,7 +150,6 @@ public void Change_BotDefend(ConVar convar, const char[] oldValue, const char[]
|
||||||
// METHODS - Old methods, some are also in feedthetrolls/misc.inc
|
// METHODS - Old methods, some are also in feedthetrolls/misc.inc
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
void ThrowAllItems(int victim) {
|
void ThrowAllItems(int victim) {
|
||||||
float vicPos[3], destPos[3];
|
float vicPos[3], destPos[3];
|
||||||
int clients[4];
|
int clients[4];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue