lol changes

This commit is contained in:
Jackzie 2021-10-03 15:23:51 -05:00
parent f756ec3100
commit 440808c0c5
No known key found for this signature in database
GPG key ID: 1E834FE36520537A
21 changed files with 868 additions and 301 deletions

View file

@ -1,5 +1,6 @@
#define MAX_TROLL_NAME_LENGTH 32
#define MAX_TROLL_FLAG_LENGTH 32
#define MAX_TROLLS 28
//#define DEBUG 1
@ -9,47 +10,103 @@ enum trollModifier {
TrollMod_Constant = 2
}
enum struct Troll {
char name[MAX_TROLL_NAME_LENGTH];
char description[128];
bool runsOnce;
int flags;
int categoryID;
char _id[MAX_TROLL_NAME_LENGTH];
void GetID(char[] name) {
strcopy(name, MAX_TROLL_NAME_LENGTH, this.name);
ReplaceString(name, MAX_TROLL_NAME_LENGTH, " ", "", false);
}
bool HasMod(trollModifier mod) {
return ((this.flags >> (view_as<int>(mod)) - 1) & 1) == 1;
}
// Gets the default modifier to use
trollModifier GetDefaultMod() {
// If the flags is equal to the 2^n flag, then it must be the only flag:
if(this.flags == view_as<int>(TrollMod_Instant)) return TrollMod_Instant;
else if(this.flags == view_as<int>(TrollMod_Constant)) return TrollMod_Constant;
else return TrollMod_Invalid;
}
void Activate(int victim, int activator, trollModifier modifier, bool silent = false) {
ApplyTroll(victim, this._id, activator, modifier, silent);
}
enum trollFlag {
Flag_1 = 1,
Flag_2 = 4,
Flag_3 = 8,
Flag_4 = 16,
Flag_5 = 32
}
Troll Trolls[MAX_TROLLS+1];
int ActiveTrolls[MAXPLAYERS+1];
StringMap trollKV;
char trollIds[MAX_TROLLS+1][MAX_TROLL_NAME_LENGTH];
enum struct Troll {
int id;
char name[MAX_TROLL_NAME_LENGTH];
char description[128];
int mods;
int enabledFlags;
int categoryID;
int activeFlagClients[MAXPLAYERS+1];
ArrayList flagNames;
bool HasMod(trollModifier mod) {
return ((this.mods >> (view_as<int>(mod)) - 1) & 1) == 1;
}
bool GetFlagName(trollFlag flag, char[] buffer, int maxlength) {
if(this.flagNames == null) return false;
this.flagNames.GetString(view_as<int>(flag), buffer, maxlength);
return true;
}
int AddFlag(const char[] name) {
if(this.flagNames == null) this.flagNames = new ArrayList(MAX_TROLL_FLAG_LENGTH);
int index = this.flagNames.PushString(name);
index = RoundFloat(Pow(2.0, float(index)));
this.enabledFlags |= index;
return index;
}
bool HasFlags() {
return this.enabledFlags > 0 && this.flagNames != null;
}
// Gets the default modifier to use
trollModifier GetDefaultMod() {
// If the flags is equal to the 2^n flag, then it must be the only flag:
if(this.mods == view_as<int>(TrollMod_Instant)) return TrollMod_Instant;
else if(this.mods == view_as<int>(TrollMod_Constant)) return TrollMod_Constant;
else return TrollMod_Invalid;
}
bool IsFlagActive(int client, trollFlag flag) {
if(ActiveTrolls[client] > 0 && IsTrollActive(client, this.name) && this.enabledFlags > 0 && this.activeFlagClients[client] >= 0) {
return ((this.activeFlagClients[client] >> view_as<int>(flag)) & 1) == 1;
}
return false;
}
bool IsFlagNameActive(int client, const char[] flagName) {
static char buffer[MAX_TROLL_FLAG_LENGTH];
for(int i = 0; i < this.flagNames.Length; i++) {
this.flagNames.GetString(i, buffer, sizeof(buffer));
if(StrEqual(buffer, flagName, false)) return this.IsFlagActive(client, view_as<trollFlag>(i));
}
return false;
}
void Activate(int client, int activator, trollModifier modifier = TrollMod_Invalid, int flags = 0) {
if(modifier == TrollMod_Invalid) modifier = this.GetDefaultMod();
ApplyTroll(client, this.name, activator, modifier, false, flags);
}
void Toggle(int client, int flags) {
ToggleTroll(client, this.name, flags);
}
void Enable(int client, int flags) {
EnableTroll(client, this.name, flags);
}
void Disable(int client) {
DisableTroll(client, this.name);
}
}
Troll Trolls[MAX_TROLLS+1];
void ResetClient(int victim, bool wipe = true) {
if(wipe) ActiveTrolls[victim] = 0;
if(wipe) {
ActiveTrolls[victim] = 0;
}
SetEntityGravity(victim, 1.0);
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
SDKUnhook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
@ -57,24 +114,24 @@ void ResetClient(int victim, bool wipe = true) {
if(wpn > -1)
SDKUnhook(wpn, SDKHook_Reload, Event_WeaponReload);
}
ArrayList categories;
static int categoryID = 0;
int SetupTroll(const char[] name, const char description[128], int flags) {
if(flags == 0) {
static int categoryID = -1;
int SetupTroll(const char[] name, const char description[128], int mods) {
if(mods == 0) {
ThrowError("Troll \"%s\" has no flags defined.", name);
return -1;
}
static int i = 0;
Trolls[i].id = i;
strcopy(Trolls[i].name, MAX_TROLL_NAME_LENGTH, name);
strcopy(Trolls[i].description, 128, description);
Trolls[i].categoryID = categoryID;
Trolls[i].flags = flags;
static char key[MAX_TROLL_NAME_LENGTH];
strcopy(key, MAX_TROLL_NAME_LENGTH, name);
ReplaceString(key, MAX_TROLL_NAME_LENGTH, " ", "", false);
strcopy(trollIds[i], MAX_TROLL_NAME_LENGTH, key);
strcopy(Trolls[i]._id, MAX_TROLL_NAME_LENGTH, key);
trollKV.SetValue(key, i);
Trolls[i].mods = mods;
strcopy(trollIds[i], MAX_TROLL_NAME_LENGTH, name);
trollKV.SetValue(name, i);
return i++;
}
// Gets the Troll enum struct via name
@ -87,6 +144,13 @@ int GetTroll(const char[] name, Troll troll) {
}
return -1;
}
int GetTrollIndex(const char[] name) {
static int i = 0;
if(trollKV.GetValue(name, i)) {
return i;
}
return -1;
}
// Gets the Troll enum struct via key index
// Returns index of troll enum
int GetTrollByKeyIndex(int index, Troll troll) {
@ -102,70 +166,86 @@ bool GetTrollID(int index, char name[MAX_TROLL_NAME_LENGTH]) {
return true;
}
void ToggleTroll(int client, const char[] name) {
void ToggleTroll(int client, const char[] name, int flags = 0) {
static Troll troll;
int index = GetTroll(name, troll);
ActiveTrolls[client] ^= 1 << view_as<int>(index);
troll.activeFlagClients[client] = flags;
}
void ApplyTroll(int victim, const char[] name, int activator, trollModifier modifier, bool silent = false) {
void ApplyTroll(int victim, const char[] name, int activator, trollModifier modifier, bool silent = false, int flags = 0) {
static Troll troll;
int trollIndex = GetTroll(name, troll);
if(trollIndex == -1) {
PrintToServer("[FTT] %N attempted to apply unknown troll: %s", activator, name);
return;
}
if(GetClientTeam(victim) == 1) {
//Victim is spectating, find its bot
victim = FindIdlePlayerBot(victim);
}
if(!ApplyAffect(victim, name, activator, modifier)) {
if(!ApplyAffect(victim, troll, activator, modifier, flags)) {
return;
}
if(!silent) {
if(IsTrollActive(victim, name)) {
ShowActivity(activator, "deactivated troll \"%s\" on %N. ", troll.name, victim);
if(IsTrollActive(victim, troll.name)) {
ShowActivityEx(activator, "[FTT] ", "deactivated troll \"%s\" on %N. ", troll.name, victim);
LogAction(activator, victim, "\"%L\" deactivated troll \"%s\" on \"%L\"", activator, troll.name, victim);
} else {
if(modifier == TrollMod_Constant)
ShowActivity(activator, "activated constant troll \"%s\" for %N. ", troll.name, victim);
else
ShowActivity(activator, "activated troll \"%s\" for %N. ", troll.name, victim);
if(modifier == TrollMod_Constant) {
ShowActivityEx(activator, "[FTT] ", "activated constant troll \"%s\" for %N. ", troll.name, victim);
} else {
ShowActivityEx(activator, "[FTT] ", "activated troll \"%s\" for %N. ", troll.name, victim);
}
LogAction(activator, victim, "\"%L\" activated troll \"%s\" for \"%L\"", activator, troll.name, victim);
}
}
if(modifier == TrollMod_Constant) {
ActiveTrolls[victim] ^= 1 << trollIndex;
}
troll.activeFlagClients[victim] = flags;
}
bool ApplyAffect(int victim, const char[] name, int activator, trollModifier modifier) {
if(StrEqual(name, "ResetTroll")) {
ShowActivity(activator, "reset troll effects for %N. ", victim);
bool ApplyAffect(int victim, Troll troll, int activator, trollModifier modifier, int flags) {
bool isActive = IsTrollActiveByRawID(victim, troll.id);
if(StrEqual(troll.name, "Reset User")) {
LogAction(activator, victim, "\"%L\" reset all troll effects for \"%L\"", activator, victim);
ShowActivityEx(activator, "[FTT] ", "reset troll effects for %N. ", victim);
ActiveTrolls[victim] = 0;
troll.activeFlagClients[victim] = 0;
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
SetEntityGravity(victim, 1.0);
return false;
} else if(StrEqual(name, "SlowSpeed"))
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 0.8);
else if(StrEqual(name, "HigherGravity"))
SetEntityGravity(victim, 1.3);
else if(StrEqual(name, "HalfPrimaryAmmo")) {
} else if(StrEqual(troll.name, "Slow Speed"))
if(isActive)
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
else
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 0.8);
else if(StrEqual(troll.name, "Higher Gravity"))
if(isActive)
SetEntityGravity(victim, 1.0);
else
SetEntityGravity(victim, 1.3);
else if(StrEqual(troll.name, "Half Primary Ammo")) {
int current = GetPrimaryReserveAmmo(victim);
SetPrimaryReserveAmmo(victim, current / 2);
} else if(StrEqual(name, "UziRules")) {
DisableTroll(victim, "NoPickup");
DisableTroll(victim, "PrimaryDisable");
} else if(StrEqual(troll.name, "UziRules")) {
DisableTroll(victim, "No Pickup");
DisableTroll(victim, "Primary Disable");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(name, "PrimaryDisable")) {
} else if(StrEqual(troll.name, "Primary Disable")) {
DisableTroll(victim, "UziRules");
DisableTroll(victim, "NoPickup");
DisableTroll(victim, "No Pickup");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(name, "NoPickup")) {
} else if(StrEqual(troll.name, "No Pickup")) {
DisableTroll(victim, "UziRules");
DisableTroll(victim, "PrimaryDisable");
DisableTroll(victim, "Primary Disable");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(name, "CameTooEarly")) {
} else if(StrEqual(troll.name, "CameTooEarly")) {
ReplyToCommand(activator, "This troll mode is not implemented.");
} else if(StrEqual(name, "KillMeSoftly")) {
} else if(StrEqual(troll.name, "KillMeSoftly")) {
static char wpn[32];
GetClientWeaponName(victim, 4, wpn, sizeof(wpn));
if(StrEqual(wpn, "weapon_adrenaline") || StrEqual(wpn, "weapon_pain_pills")) {
@ -177,44 +257,43 @@ bool ApplyAffect(int victim, const char[] name, int activator, trollModifier mod
}
//TODO: Implement TrollMod_Constant
return false;
} else if(StrEqual(name, "ThrowItAll")) {
} else if(StrEqual(troll.name, "Throw It All")) {
if(modifier == TrollMod_Instant)
ThrowAllItems(victim);
if(hThrowTimer == INVALID_HANDLE && modifier == TrollMod_Constant) {
hThrowTimer = CreateTimer(hThrowItemInterval.FloatValue, Timer_ThrowTimer, _, TIMER_REPEAT);
}
} else if(StrEqual(name, "Swarm")) {
} else if(StrEqual(troll.name, "Swarm")) {
if(modifier == TrollMod_Instant) {
L4D2_RunScript("RushVictim(GetPlayerFromUserID(%d), %d)", victim, 15000);
}else if(modifier == TrollMod_Constant) {
}else{
ReplyToCommand(activator, "Invalid modifier for mode.");
return false;
}
} else if(StrEqual(name, "GunJam")) {
return true;
} else if(StrEqual(troll.name, "Gun Jam")) {
int wpn = GetClientWeaponEntIndex(victim, 0);
if(wpn > -1)
SDKHook(wpn, SDKHook_Reload, Event_WeaponReload);
else
else {
ReplyToCommand(activator, "Victim does not have a primary weapon.");
} else if(StrEqual(name, "VomitPlayer"))
return false;
}
} else if(StrEqual(troll.name, "Vomit Player"))
L4D_CTerrorPlayer_OnVomitedUpon(victim, victim);
else if(StrEqual(name, "InfaceSpecial")) {
else if(StrEqual(troll.name, "Inface Special")) {
FakeClientCommand(victim, "sm_inface");
return false;
} else if(StrEqual(name, "InstaSpecial")) {
} else if(StrEqual(troll.name, "Insta Special")) {
FakeClientCommand(victim, "sm_insta");
return false;
} else {
#if defined DEBUG
PrintToServer("[FTT] Possibly invalid troll, no action: %s", name);
PrintToServer("[FTT] Possibly invalid troll, no action: %s", troll.name);
ReplyToCommand(activator, "[FTT/Debug] If nothing occurs, this troll possibly was not implemented correctly. ");
#endif
}
return true;
}
bool IsTrollActive(int client, const char[] troll) {
if(ActiveTrolls[client] == 0) return false;
static int i = 0;
@ -225,9 +304,15 @@ bool IsTrollActive(int client, const char[] troll) {
return false; //errors instead but compiler no like
}
void EnableTroll(int client, const char[] troll) {
bool IsTrollActiveByRawID(int client, int id) {
if(ActiveTrolls[client] == 0) return false;
return ((ActiveTrolls[client] >> id) & 1) == 1;
}
void EnableTroll(int client, const char[] troll, int flags = 0) {
if(!IsTrollActive(client, troll)) {
ToggleTroll(client, troll);
ToggleTroll(client, troll, flags);
}
}
@ -243,47 +328,3 @@ void SetCategory(const char[] newCat) {
void GetCategory(int category, char[] buffer, int size) {
categories.GetString(category, buffer, size);
}
void SetupTrolls() {
trollKV = new StringMap();
categories = new ArrayList(ByteCountToCells(16));
SetupTroll("Reset Troll", "Resets the user, removes all troll effects", TrollMod_Instant);
SetCategory("Magnet / Horde");
SetupTroll("Special Magnet", "Attracts ALL specials to any alive target with this troll enabled", TrollMod_Constant);
SetupTroll("Tank Magnet", "Attracts ALL tanks to any alive target with this troll enabled", TrollMod_Constant);
SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", 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);
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
SetCategory("Items");
SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
SetupTroll("Bad Throw", "Player drops throwables on throw, and biles/molotovs themselves", TrollMod_Constant);
SetupTroll("No Pickup", "Prevents a player from picking up ANY (new) item. Use ThrowItAll to make them drop", TrollMod_Constant);
SetupTroll("UziRules", "Picking up a weapon gives them a UZI instead", TrollMod_Constant);
SetupTroll("Primary Disable", "Player cannot pickup any weapons, only melee/pistols", TrollMod_Constant);
SetupTroll("Half Primary Ammo", "Cuts their primary reserve ammo in half", TrollMod_Instant);
SetCategory("Chat");
SetupTroll("iCantSpellNoMore", "Chat messages letter will randomly changed with wrong letters", TrollMod_Instant);
SetupTroll("No Profanity", "Replaces some words with random phrases", TrollMod_Constant);
SetupTroll("Vocalize Gag", "Prevents player from sending any vocalizations (even automatic)", TrollMod_Constant);
SetupTroll("Honk", "Honk", TrollMod_Constant);
SetupTroll("Meow", "Makes the player meow", TrollMod_Constant);
SetCategory("Health");
SetupTroll("Damage Boost", "Makes a player take more damage than normal", TrollMod_Constant);
SetupTroll("Temp Health Quick Drain", "Makes a player's temporarily health drain very quickly", TrollMod_Constant);
SetupTroll("Slow Drain", "Will make the player slowly lose health over time", TrollMod_Constant);
SetupTroll("KillMeSoftly", "Make player eat or waste pills whenever possible", TrollMod_Instant | TrollMod_Constant);
SetCategory("Misc");
SetupTroll("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant);
SetupTroll("Slow Speed", "Sets player speed to 0.8x of normal speed", TrollMod_Constant);
SetupTroll("Higher Gravity", "Sets player gravity to 1.3x of normal gravity", TrollMod_Constant);
SetupTroll("No Shove", "Prevents a player from shoving", TrollMod_Constant);
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
//INFO: UP MAX_TROLLS when adding new trolls!
}

View file

@ -41,15 +41,22 @@ public Action Command_InstaSpecial(int client, int args) {
ReplyToCommand(client, "Unknown special \"%s\"", arg2);
return Plugin_Handled;
}
int successes = 0;
for (int i = 0; i < target_count; i++) {
int target = target_list[i];
if(GetClientTeam(target) == 2) {
SpawnSpecialNear(target, specialType);
if(SpawnSpecialNear(target, specialType)) {
LogAction(client, target, "\"%L\" spawned Insta-%s™ nearby \"%L\"", client, arg2, target);
successes++;
} else {
ReplyToCommand(client, "[FTT] Could not spawn %s near %s", arg2, target_name);
}
}else{
ReplyToTargetError(client, target_count);
}
}
ShowActivity(client, "spawned Insta-%s™ near %s", arg2, target_name);
if(successes > 0)
ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ near %s", arg2, target_name);
}
@ -99,15 +106,22 @@ public Action Command_InstaSpecialFace(int client, int args) {
ReplyToCommand(client, "Unknown special \"%s\"", arg2);
return Plugin_Handled;
}
int successes = 0;
for (int i = 0; i < target_count; i++) {
int target = target_list[i];
if(GetClientTeam(target) == 2) {
SpawnSpecialInFace(target, specialType);
if(SpawnSpecialInFace(target, specialType)) {
LogAction(client, target, "\"%L\" spawned Insta-%s™ at player \"%L\"", client, arg2, target);
successes++;
} else {
ReplyToCommand(client, "[FTT] Could not spawn %s on %s", arg2, target_name);
}
}else{
ReplyToTargetError(client, target_count);
}
}
ShowActivity(client, "spawned Insta-%s™ on %s", arg2, target_name);
if(successes > 0)
ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ on %s", arg2, target_name);
}
return Plugin_Handled;
}
@ -143,7 +157,8 @@ public Action Command_WitchAttack(int client, int args) {
while ((witch = FindEntityByClassname(witch, "witch")) != INVALID_ENT_REFERENCE) {
SetWitchTarget(witch, target);
ShowActivity(client, "all witches target %s", target_name);
ShowActivityEx(client, "[FTT] ", "set all witches to target %s", target_name);
LogAction(client, target, "\"%L\" set all witches to attack \"%L\"", client, target);
}
}else{
ReplyToTargetError(client, target_count);
@ -157,7 +172,8 @@ public Action Command_FeedTheCrescendoTroll(int client, int args) {
if(lastCrescendoUser > -1) {
ActivateAutoPunish(lastCrescendoUser);
ReplyToCommand(client, "Activated auto punish on %N", lastCrescendoUser);
ShowActivity(client, "activated autopunish for crescendo activator %N",lastCrescendoUser);
LogAction(client, lastCrescendoUser, "\"%L\" autopunished crescendo rusher \"%L\"", client, lastCrescendoUser);
ShowActivityEx(client, "[FTT] ", "activated autopunish for crescendo activator %N",lastCrescendoUser);
}else{
ReplyToCommand(client, "No player could be found to autopunish.");
}
@ -191,7 +207,8 @@ public Action Command_ResetUser(int client, int args) {
for (int i = 0; i < target_count; i++) {
if(ActiveTrolls[target_list[i]] > 0) {
ResetClient(target_list[i], true);
ShowActivity(client, "reset troll effects on \"%N\". ", target_list[i]);
LogAction(client, target_list[i], "\"%L\" reset all troll effects for \"%L\"", client, target_list[i]);
ShowActivityEx(client, "[FTT] ", "reset troll effects for \"%N\". ", target_list[i]);
}
}
}
@ -199,52 +216,30 @@ public Action Command_ResetUser(int client, int args) {
}
public Action Command_ApplyUser(int client, int args) {
if(args < 2) {
Menu menu = new Menu(ChoosePlayerHandler);
menu.SetTitle("Choose a player to troll");
for(int i = 1; i < MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2) {
static char userid[8], display[16];
Format(userid, sizeof(userid), "%d", GetClientUserId(i));
GetClientName(i, display, sizeof(display));
menu.AddItem(userid, display);
}
}
menu.ExitButton = true;
menu.Display(client, 0);
if(args < 1) {
ShowTrollMenu(client);
}else{
char arg1[32], arg2[32], arg3[8];
char arg1[32];
GetCmdArg(1, arg1, sizeof(arg1));
GetCmdArg(2, arg2, sizeof(arg2));
GetCmdArg(3, arg3, sizeof(arg3));
bool silent = StrEqual(arg3, "silent") || StrEqual(arg3, "quiet") || StrEqual(arg3, "mute");
static char name[MAX_TROLL_NAME_LENGTH];
if(!GetTrollID(StringToInt(arg2), name)) {
ReplyToCommand(client, "Not a valid mode. Must be greater than 0. Usage: sm_fta [player] [mode]. Use sm_ftr <player> to reset.");
}else{
char target_name[MAX_TARGET_LENGTH];
int target_list[MAXPLAYERS], target_count;
bool tn_is_ml;
if ((target_count = ProcessTargetString(
arg1,
client,
target_list,
MAXPLAYERS,
0,
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++) {
if(IsClientInGame(target_list[i]) && GetClientTeam(target_list[i]) == 2)
ApplyTroll(target_list[i], name, client, TrollMod_Instant, silent);
}
static char target_name[MAX_TARGET_LENGTH];
int target_list[1], target_count;
bool tn_is_ml;
if ((target_count = ProcessTargetString(
arg1,
client,
target_list,
1,
COMMAND_FILTER_NO_MULTI,
target_name,
sizeof(target_name),
tn_is_ml)) <= 0
&& target_list[0] > 0) {
/* This function replies to the admin with a failure message */
ReplyToTargetError(client, target_count);
return Plugin_Handled;
}
SetupCategoryMenu(client, target_list[0]);
}
return Plugin_Handled;
}
@ -272,9 +267,8 @@ public Action Command_ListTheTrolls(int client, int args) {
int modeCount = 0;
static char name[MAX_TROLL_NAME_LENGTH];
for(int j = 1; j <= MAX_TROLLS; j++) {
GetTrollID(j, name);
if(IsTrollActive(i, name)) {
strcopy(modeListArr[modeCount], MAX_TROLL_NAME_LENGTH, name);
if(trollIds[j][0] != '\0' && IsTrollActive(i, trollIds[j])) {
strcopy(modeListArr[modeCount], MAX_TROLL_NAME_LENGTH, trollIds[j]);
modeCount++;
}
}

View file

@ -43,7 +43,7 @@ public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadca
}
public Action Event_WeaponReload(int weapon) {
int client = GetEntPropEnt(weapon, Prop_Send, "m_hOwner");
if(IsTrollActive(client, "GunJam")) {
if(IsTrollActive(client, "Gun Jam")) {
float dec = GetRandomFloat(0.0, 1.0);
if(FloatCompare(dec, 0.50) == -1) { //10% chance gun jams
return Plugin_Stop;
@ -101,7 +101,7 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
if((class == L4D2Infected_Tank && hMagnetTargetMode.IntValue & 2 == 2) || hMagnetTargetMode.IntValue & 1 == 1 ) continue;
}
if(class == L4D2Infected_Tank && IsTrollActive(i, "TankMagnet") || (class != L4D2Infected_Tank && IsTrollActive(i, "SpecialMagnet"))) {
if(class == L4D2Infected_Tank && IsTrollActive(i, "Tank Magnet") || (class != L4D2Infected_Tank && IsTrollActive(i, "Special Magnet"))) {
GetClientAbsOrigin(i, survPos);
float dist = GetVectorDistance(survPos, spPos, true);
if(closestClient == -1 || dist < closestDistance) {
@ -120,7 +120,7 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
return Plugin_Continue;
}
public Action L4D2_OnEntityShoved(int client, int entity, int weapon, float vecDir[3], bool bIsHighPounce) {
if(client > 0 && client <= MaxClients && IsTrollActive(client, "NoShove") && hShoveFailChance.FloatValue > GetRandomFloat()) {
if(client > 0 && client <= MaxClients && IsTrollActive(client, "No Shove") && hShoveFailChance.FloatValue > GetRandomFloat()) {
return Plugin_Handled;
}
return Plugin_Continue;
@ -214,7 +214,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
PrintToServer("%N: %s", client, sArgs);
CPrintToChatAll("{blue}%N {default}: %s", client, newMessage);
return Plugin_Handled;
}else if(IsTrollActive(client, "NoProfanity")) {
}else if(IsTrollActive(client, "No Profanity")) {
static char strings[32][MAX_PHRASE_LENGTH];
ArrayList phrases;
bool foundWord = false;
@ -224,8 +224,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
phrases = GetPhrasesArray(strings[i]);
if(phrases != null && phrases.Length > 0) {
foundWord = true;
int c = phrases.GetString(GetRandomInt(0, phrases.Length - 1), strings[i], MAX_PHRASE_LENGTH);
PrintToServer("replacement: %s (%d)", strings[i], c);
phrases.GetString(GetRandomInt(0, phrases.Length - 1), strings[i], MAX_PHRASE_LENGTH);
}
}
int length = MAX_PHRASE_LENGTH * words;
@ -233,8 +232,11 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
if(foundWord) {
ImplodeStrings(strings, 32, " ", message, length);
} else {
REPLACEMENT_PHRASES.GetValue("_Full Message Phrases", phrases);
phrases.GetString(GetRandomInt(0, phrases.Length - 1), message, MAX_PHRASE_LENGTH);
if(!fullMessagePhraseList) {
PrintToServer("[FTT] Error: Could not find full message phrases!!!");
return Plugin_Continue;
}
fullMessagePhraseList.GetString(GetRandomInt(0, fullMessagePhraseList.Length - 1), message, MAX_PHRASE_LENGTH);
}
CPrintToChatAll("{blue}%N {default}: %s", client, message);
PrintToServer("%N: %s", client, sArgs);
@ -244,7 +246,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
}
public Action Event_ItemPickup(int client, int weapon) {
if(IsTrollActive(client, "NoPickup")) {
if(IsTrollActive(client, "No Pickup")) {
return Plugin_Stop;
}else{
static char wpnName[64];
@ -270,7 +272,7 @@ public Action Event_ItemPickup(int client, int weapon) {
SetCommandFlags("give", flags);
return Plugin_Stop;
}
}else if(IsTrollActive(client, "PrimaryDisable")) {
}else if(IsTrollActive(client, "Primary Disable")) {
return Plugin_Stop;
}
return Plugin_Continue;
@ -290,6 +292,34 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
}
return Plugin_Continue;
}
static int invertedTrollIndex;
if(invertedTrollIndex <= 0) {
invertedTrollIndex = GetTrollIndex("Inverted Controls");
}
if(IsTrollActiveByRawID(client, invertedTrollIndex)) {
if(buttons & IN_MOVELEFT || buttons & IN_MOVERIGHT) {
vel[1] = -vel[1];
}
if(buttons & IN_FORWARD || buttons & IN_BACK) {
vel[0] = -vel[0];
}
if(buttons & IN_JUMP) {
buttons = buttons & ~IN_JUMP | IN_DUCK;
} else if(buttons & IN_DUCK) {
buttons = buttons & ~IN_DUCK | IN_JUMP;
}
if(buttons & IN_RUN) {
buttons = buttons & ~IN_RUN | IN_WALK;
} else if(buttons & IN_WALK) {
buttons = buttons & ~IN_WALK | IN_RUN;
}
if(buttons & IN_RELOAD) {
buttons = buttons & ~IN_RELOAD | IN_ATTACK2;
} else if(buttons & IN_ATTACK2) {
buttons = buttons & ~IN_ATTACK2 | IN_RELOAD;
}
return Plugin_Changed;
}
return Plugin_Continue;
}
@ -300,7 +330,7 @@ public Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float&
return Plugin_Stop;
}
if(IsTrollActive(attacker, "DamageBoost")) {
if(IsTrollActive(attacker, "Damage Boost")) {
damage * 2;
return Plugin_Changed;
}
@ -318,7 +348,8 @@ public Action SoundHook(int[] clients, int& numClients, char sample[PLATFORM_MAX
lastCrescendoUser = lastButtonUser;
if(IsPlayerFarDistance(lastButtonUser, AUTOPUNISH_FLOW_MIN_DISTANCE)) {
NotifyAllAdmins("Autopunishing player %N for activation of event far from team", lastButtonUser);
ShowActivity(0, "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);
ActivateAutoPunish(lastButtonUser);
}
lastButtonUser = -1;
@ -327,7 +358,7 @@ public Action SoundHook(int[] clients, int& numClients, char sample[PLATFORM_MAX
if(IsTrollActive(entity, "Honk")) {
strcopy(sample, sizeof(sample), "player/footsteps/clown/concrete1.wav");
return Plugin_Changed;
} else if(IsTrollActive(entity, "VocalizeGag")) {
} else if(IsTrollActive(entity, "Vocalize Gag")) {
return Plugin_Handled;
} else if(IsTrollActive(entity, "Meow")) {
strcopy(sample, sizeof(sample), "custom/meow1.mp3");
@ -351,7 +382,7 @@ public Action Event_WitchVictimSet(Event event, const char[] name, bool dontBroa
continue;
}
if(IsTrollActive(i, "WitchMagnet")) {
if(IsTrollActive(i, "Witch Magnet")) {
GetClientAbsOrigin(i, survPos);
float dist = GetVectorDistance(survPos, witchPos, true);
if(closestClient == -1 || dist < closestDistance) {
@ -384,35 +415,49 @@ void EntityCreateCallback(int entity) {
GetEntityClassname(entity, class, sizeof(class));
int entOwner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
if(entOwner > 0 && entOwner <= MaxClients && IsTrollActive(entOwner, "BadThrow")) {
static float pos[3];
GetClientEyePosition(entOwner, pos);
if(StrContains(class, "vomitjar", true) > -1) {
AcceptEntityInput(entity, "Kill");
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue) {
L4D_CTerrorPlayer_OnVomitedUpon(entOwner, entOwner);
EmitSoundToAll("weapons/ceda_jar/ceda_jar_explode.wav", entOwner);
FindClosestClient(entOwner, false, pos);
}
SpawnItem("vomitjar", pos);
} else if(StrContains(class, "molotov", true) > -1) {
// Burn them if no one near :)
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue) {
GetClientAbsOrigin(entOwner, pos);
if(IsAnyPlayerNear(entOwner, 500.0)) {
AcceptEntityInput(entity, "Kill");
EmitSoundToAll("weapons/molotov/molotov_detonate_1.wav", entOwner);
} else { // or delete if there is
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
}
} else {
SpawnItem("molotov", pos);
if(entOwner > 0 && entOwner <= MaxClients) {
if(IsTrollActive(entOwner, "Bad Throw")) {
static float pos[3];
GetClientEyePosition(entOwner, pos);
if(StrContains(class, "vomitjar", true) > -1) {
AcceptEntityInput(entity, "Kill");
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue) {
L4D_CTerrorPlayer_OnVomitedUpon(entOwner, entOwner);
EmitSoundToAll("weapons/ceda_jar/ceda_jar_explode.wav", entOwner);
FindClosestClient(entOwner, false, pos);
}
SpawnItem("vomitjar", pos);
} else if(StrContains(class, "molotov", true) > -1) {
// Burn them if no one near :)
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue) {
GetClientAbsOrigin(entOwner, pos);
if(IsAnyPlayerNear(entOwner, 500.0)) {
AcceptEntityInput(entity, "Kill");
EmitSoundToAll("weapons/molotov/molotov_detonate_1.wav", entOwner);
} else { // or delete if there is
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
}
} else {
SpawnItem("molotov", pos);
AcceptEntityInput(entity, "Kill");
}
} else if(StrContains(class, "pipe_bomb", true) > -1) {
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue)
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
SpawnItem("pipe_bomb", pos);
}
} else if(StrContains(class, "pipe_bomb", true) > -1) {
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue)
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
SpawnItem("pipe_bomb", pos);
}
}
}
}
int FindClosestVisibleClient(int source) {
static float pos[3], ang[3];
GetClientEyePosition(source, pos);
GetClientEyeAngles(source, ang);
Handle handle = TR_TraceRayFilterEx(pos, ang, MASK_VISIBLE, RayType_Infinite, TraceEntityFilterPlayer, source);
return TR_GetEntityIndex(handle);
}
public bool TraceEntityFilterPlayer(int entity, int mask, any data) {
return data != entity && entity <= MaxClients && GetClientTeam(entity) == 2 && IsPlayerAlive(entity);
}

View file

@ -12,7 +12,7 @@ public int Insta_PlayerHandler(Menu menu, MenuAction action, int client, int par
Menu spMenu = new Menu(Insta_SpecialHandler);
spMenu.SetTitle("Choose a Insta-Special™");
for(int i = 1; i <= 6; i++) {
for(int i = 1; i <= 8; i++) {
Format(info, sizeof(info), "%d|%d|%d", userid, instaMode, i);
spMenu.AddItem(info, SPECIAL_NAMES[i-1]);
}
@ -33,11 +33,19 @@ public int Insta_SpecialHandler(Menu menu, MenuAction action, int client, int pa
bool inFace = StrEqual(str[1], "1");
int special = StringToInt(str[2]);
if(inFace) {
SpawnSpecialInFace(target, special);
ShowActivity(client, "spawned Insta-%s™ near %N", SPECIAL_NAMES[special-1], target);
if(SpawnSpecialInFace(target, special)) {
LogAction(client, target, "\"%L\" spawned Insta-%s™ on \"%L\"", client, SPECIAL_NAMES[special-1], target);
ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ on %N", SPECIAL_NAMES[special-1], target);
} else {
ReplyToCommand(client, "Could not spawn special.");
}
} else {
SpawnSpecialNear(target, special);
ShowActivity(client, "spawned Insta-%s™ near %N", SPECIAL_NAMES[special-1], target);
if(SpawnSpecialNear(target, special)) {
LogAction(client, target, "\"%L\" spawned Insta-%s™ near \"%L\"", client, SPECIAL_NAMES[special-1], target);
ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ near %N", SPECIAL_NAMES[special-1], target);
} else {
ReplyToCommand(client, "Could not spawn special.");
}
}
} else if (action == MenuAction_End)
delete menu;
@ -66,26 +74,32 @@ public int ChoosePlayerHandler(Menu menu, MenuAction action, int param1, int par
delete menu;
}
static int iMenuVictimID[MAXPLAYERS+1];
public int ChooseCategoryHandler(Menu menu, MenuAction action, int param1, int param2) {
if (action == MenuAction_Select) {
if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
ShowTrollMenu(param1);
else if (action == MenuAction_Select) {
static char info[32];
menu.GetItem(param2, info, sizeof(info));
static char str[2][8];
ExplodeString(info, "|", str, 2, 8, false);
int userid = StringToInt(str[0]);
iMenuVictimID[param1] = userid;
int category = StringToInt(str[1]);
// Reset troll:
if(category == -1) {
ApplyTroll(GetClientOfUserId(userid), "Reset User", param1, TrollMod_Instant);
return;
}
Menu trollMenu = new Menu(ChooseModeMenuHandler);
GetCategory(category, info, sizeof(info));
Format(info, sizeof(info), "Category: %s", info);
trollMenu.SetTitle(info);
//TODO: Update
static Troll troll;
// add 'return' btn
Format(info, sizeof(info), "%d|-1", userid);
trollMenu.AddItem(info, "<= Go Back");
// Add all menus that have same category
for(int i = 0; i < trollKV.Size; i++) {
GetTrollByKeyIndex(i, troll);
@ -95,30 +109,32 @@ public int ChooseCategoryHandler(Menu menu, MenuAction action, int param1, int p
}
}
trollMenu.ExitButton = true;
trollMenu.ExitBackButton = true;
trollMenu.Display(param1, 0);
} else if (action == MenuAction_End)
delete menu;
}
public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int param2) {
if (action == MenuAction_Select) {
static char info[16];
if (action == MenuAction_Cancel) {
if(param2 == MenuCancel_ExitBack) {
if(iMenuVictimID[param1] == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
}
SetupCategoryMenu(param1, iMenuVictimID[param1]);
}
} else if (action == MenuAction_Select) {
static char info[32];
menu.GetItem(param2, info, sizeof(info));
static char str[2][8];
ExplodeString(info, "|", str, 2, 8, false);
int userid = StringToInt(str[0]);
int client = GetClientOfUserId(userid);
int keyIndex = StringToInt(str[1]);
if(keyIndex == -1) {
SetupCategoryMenu(param1, userid);
return;
}
static Troll troll;
static char trollID[MAX_TROLL_NAME_LENGTH];
GetTrollByKeyIndex(keyIndex, troll);
troll.GetID(trollID);
//If troll has multiple flags, prompt:
if(StrEqual(trollID, "ThrowItAll")) {
if(StrEqual(troll.name, "Throw It All")) {
// Setup menu to call itself, but with an extra data point
Menu itmMenu = new Menu(ChooseClumsySlotHandler);
itmMenu.SetTitle("Choose Item To Throw");
@ -138,10 +154,11 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
itmMenu.Display(param1, 0);
} else if(troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
Menu modiferMenu = new Menu(ChooseTrollModiferHandler);
modiferMenu.SetTitle("Choose Troll Modifer Option");
Format(info, sizeof(info), "%s: Choose Modifier", troll.name);
modiferMenu.SetTitle(info);
Format(info, sizeof(info), "%d|%d|1", userid, keyIndex);
modiferMenu.AddItem(info, "Activate once");
modiferMenu.AddItem(info, "Activate Once");
Format(info, sizeof(info), "%d|%d|2", userid, keyIndex);
modiferMenu.AddItem(info, "Activate Periodically");
Format(info, sizeof(info), "%d|%d|3", userid, keyIndex);
@ -150,7 +167,7 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
modiferMenu.ExitButton = true;
modiferMenu.Display(param1, 0);
} else {
ApplyTroll(client, trollID, param1, troll.GetDefaultMod());
troll.Activate(client, param1);
}
} else if (action == MenuAction_End)
delete menu;
@ -164,15 +181,19 @@ public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int
ExplodeString(info, "|", str, 2, 8, false);
int client = GetClientOfUserId(StringToInt(str[0]));
int slot = StringToInt(str[1]);
PrintToChatAll("%d", slot);
if(slot == -1) {
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
}else if(slot == -1) {
for(int i = 0; i <= 4; i++) {
ThrowItemToClosestPlayer(client, i);
}
} else {
ThrowItemToClosestPlayer(client, slot);
}
ShowActivity(param1, "activated troll \"Throw It All\" for %N. ", client);
LogAction(param1, client, "\"%L\" activated troll \"Throw It all\" for \"%L\"", param1, client);
ShowActivityEx(param1, "[FTT] ", "activated troll \"Throw It All\" for %N. ", client);
} else if (action == MenuAction_End)
delete menu;
}
@ -187,15 +208,18 @@ public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, i
int keyIndex = StringToInt(str[1]);
int flags = StringToInt(str[2]);
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
}
static Troll troll;
GetTrollByKeyIndex(keyIndex, troll);
if(flags == 1 || flags == 3)
troll.Activate(client, param1, TrollMod_Instant);
// ApplyTroll(client, trollID, param1, TrollMod_Instant);
if(flags == 2 || flags == 3)
troll.Activate(client, param1, TrollMod_Constant);
// ApplyTroll(client, trollID, param1, TrollMod_Constant);
troll.Activate(client, param1, TrollMod_Constant);
} else if (action == MenuAction_End)
delete menu;
}
@ -206,13 +230,37 @@ public void StopItemGive(int client) {
void SetupCategoryMenu(int client, int victimUserID) {
Menu categoryMenu = new Menu(ChooseCategoryHandler);
categoryMenu.SetTitle("Choose a troll category");
static char category[16], id[8];
static char category[64], id[8];
Format(category, sizeof(category), "%N: Choose troll category", GetClientOfUserId(victimUserID));
categoryMenu.SetTitle(category);
Format(id, sizeof(id), "%d|-1", victimUserID);
categoryMenu.AddItem(id, "Reset User");
for(int i = 0; i < categories.Length; i++) {
categories.GetString(i, category, sizeof(category));
Format(id, sizeof(id), "%d|%d", victimUserID, i);
categoryMenu.AddItem(id, category);
}
categoryMenu.ExitButton = true;
categoryMenu.ExitBackButton = true;
categoryMenu.Display(client, 0);
}
void ShowTrollMenu(int client) {
Menu menu = new Menu(ChoosePlayerHandler);
menu.SetTitle("Choose a player to troll");
static char userid[8], display[32];
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2) {
IntToString(GetClientUserId(i), userid, sizeof(userid));
int specClient = GetSpectatorClient(i);
if(specClient > 0)
Format(display, sizeof(display), "%N (Idle)", specClient);
else
GetClientName(i, display, sizeof(display));
menu.AddItem(userid, display);
}
}
menu.ExitButton = true;
menu.Display(client, 0);
}

View file

@ -1,13 +1,14 @@
#define AUTOPUNISH_FLOW_MIN_DISTANCE 5000.0
#define AUTOPUNISH_MODE_COUNT 3
// #define DEBUG_PHRASE_LOAD 1
void ActivateAutoPunish(int client) {
if(hAutoPunish.IntValue & 2 == 2)
ApplyTroll(lastButtonUser, "SpecialMagnet", 0, TrollMod_Constant);
ApplyTroll(lastButtonUser, "Special Magnet", 0, TrollMod_Constant);
if(hAutoPunish.IntValue & 1 == 1)
ApplyTroll(lastButtonUser, "TankMagnet", 0, TrollMod_Constant);
ApplyTroll(lastButtonUser, "Tank Magnet", 0, TrollMod_Constant);
if(hAutoPunish.IntValue & 8 == 8)
ApplyTroll(lastButtonUser, "VomitPlayer", 0, TrollMod_Instant);
ApplyTroll(lastButtonUser, "Vomit Player", 0, TrollMod_Instant);
else if(hAutoPunish.IntValue & 4 == 4)
ApplyTroll(lastButtonUser, "Swarm", 0, TrollMod_Instant);
if(hAutoPunishExpire.IntValue > 0) {
@ -29,7 +30,8 @@ void SetWitchTarget(int witch, int target) {
bool ToggleMarkPlayer(int client, int target) {
if(g_PendingBanTroll[target]) {
g_PendingBanTroll[target] = false;
ShowActivity(client, "unmarked %N as troll", target);
LogAction(client, target, "\"%L\" unmarked \"%L\" as troll", client, target);
ShowActivityEx(client, "[FTT] ", "unmarked %N as troll", target);
return true;
}else{
AdminId admin_client = GetUserAdmin(client);
@ -41,7 +43,8 @@ bool ToggleMarkPlayer(int client, int target) {
Call_Finish();
g_PendingBanTroll[target] = true;
EnableTroll(target, "NoProfanity");
ShowActivity(client, "marked %N as troll", target);
LogAction(client, target, "\"%L\" marked \"%L\" as troll", client, target);
ShowActivityEx(client, "[FTT] ", "marked %N as troll", target);
return true;
}else{
ReplyToCommand(client, "cannot mark %N as troll as they are an admin.", target);
@ -68,6 +71,7 @@ stock bool IsPlayerIncapped(int client) {
#define MAX_PHRASES_PER_WORD 8
#define MAX_PHRASE_LENGTH 191
StringMap REPLACEMENT_PHRASES;
ArrayList fullMessagePhraseList;
/* Example:
exWord
{
@ -104,6 +108,13 @@ void LoadPhrases() {
phrases.PushString(phrase);
}
i = 0;
if(StrEqual(word, "_full message phrases")) {
fullMessagePhraseList = phrases.Clone();
continue;
}
#if defined DEBUG_PHRASE_LOAD
PrintToServer("Loaded %d phrases for word \"%s\"", phrases.Length, word);
#endif
REPLACEMENT_PHRASES.SetValue(word, phrases.Clone(), true);
} while (kv.GotoNextKey(false));
delete kv;
@ -193,7 +204,6 @@ bool IsAnyPlayerNear(int source, float range) {
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && i != source) {
GetClientAbsOrigin(i, pos2);
float dist = GetVectorDistance(pos1, pos2);
PrintToChatAll("%f <= %f: %b", dist, range, (dist <= range));
if(dist <= range) return true;
}
}
@ -202,7 +212,7 @@ bool IsAnyPlayerNear(int source, float range) {
void ThrowItemToClosestPlayer(int victim, int slot) {
int wpn = GetPlayerWeaponSlot(victim, slot);
if(slot != 1 || DoesClientHaveMelee(victim)) {
if(wpn > 0 && (slot != 1 || DoesClientHaveMelee(victim))) {
static float pos[3];
int clients[4];
GetClientAbsOrigin(victim, pos);
@ -229,3 +239,13 @@ void DropItem(int victim, int slot) {
}
}
int GetSpectatorClient(int bot) {
if(!IsFakeClient(bot)) return -1;
static char netclass[16];
GetEntityNetClass(bot, netclass, sizeof(netclass));
if(strcmp(netclass, "SurvivorBot") == 0 ) {
int user = GetEntProp(bot, Prop_Send, "m_humanSpectatorUserID");
if(user > 0) return GetClientOfUserId(user);
}
return -1;
}

View file

@ -1,9 +1,9 @@
char SPECIAL_NAMES[][] = {
"Smoker", "Boomer", "Hunter", "Spitter", "Jockey", "Charger", "Witch"
"Smoker", "Boomer", "Hunter", "Spitter", "Jockey", "Charger", "Witch", "Tank"
};
stock int GetSpecialType(const char[] input) {
for(int i = 0; i < sizeof(SPECIAL_NAMES); i++) {
for(int i = 0; i < 8; i++) {
if(strcmp(SPECIAL_NAMES[i], input, false) == 0) return i + 1;
}
return -1;
@ -37,16 +37,18 @@ float GetIdealMinDistance(int specialType) {
}
bool SpawnSpecialInFace(int target, int specialType) {
if(specialType >= sizeof(SPECIAL_NAMES)) return false;
if(specialType > 8) return false;
static float pos[3], ang[3];
static float testPos[3];
testPos = pos;
GetClientAbsOrigin(target, pos);
GetClientEyeAngles(target, ang);
if(specialType != 5 && specialType != 2) { //If charger/hunter, find a suitable area that is at least 5 m away
if(specialType != 5 && specialType != 2) { //If not jockey/hunter find a suitable area that is at least 5 m away
float minDistance = GetIdealMinDistance(specialType);
GetHorizontalPositionFromOrigin(pos, ang, minDistance, testPos);
FindSuitablePosition(target, pos, testPos, minDistance, 100);
if(!FindSuitablePosition(target, pos, testPos, minDistance, 100)) {
L4D_GetRandomPZSpawnPosition(target, specialType, 10, testPos);
}
pos = testPos;
} else { // Else spawn a little bit off, and above (above for jockeys)
pos[2] += 10.0;
@ -54,31 +56,49 @@ bool SpawnSpecialInFace(int target, int specialType) {
}
pos[2] += 1.0;
NegateVector(ang);
int special = (specialType == 7) ? L4D2_SpawnWitch(pos, ang) : L4D2_SpawnSpecial(specialType, pos, ang);
if(special == -1) return false;
if(specialType == 7)
SetWitchTarget(special, target);
else
g_iAttackerTarget[special] = GetClientUserId(target);
if(specialType == 2) { //Kill boomer
ForcePlayerSuicide(special);
}
return true;
return SpawnSpecialInternal(specialType, target, pos, NULL_VECTOR) > 0;
}
bool SpawnSpecialNear(int target, int specialType) {
if(specialType >= sizeof(SPECIAL_NAMES)) return false;
if(specialType > 8) return false;
static float pos[3];
if(L4D_GetRandomPZSpawnPosition(target, specialType, 10, pos)) {
int special = (specialType == 7) ? L4D2_SpawnWitch(pos, NULL_VECTOR) : L4D2_SpawnSpecial(specialType, pos, NULL_VECTOR);
if(special == -1) return false;
if(specialType == 7)
SetWitchTarget(special, target);
else
g_iAttackerTarget[special] = GetClientUserId(target);
return true;
return SpawnSpecialInternal(specialType, target, pos, NULL_VECTOR) > 0;
}
return false;
}
// doesnt seem to work with l4dhooks methods
void BypassLimit() {
int bot = CreateFakeClient("InfectedBot");
if (bot != 0) {
ChangeClientTeam(bot, 3);
CreateTimer(0.1, Timer_KickBot, bot);
}
}
int SpawnSpecialInternal(int type, int target, float pos[3], float ang[3]) {
if(type <= 6) {
// BypassLimit();
int special = L4D2_SpawnSpecial(type, pos, ang);
if(special != -1)
g_iAttackerTarget[special] = GetClientUserId(target);
return special;
}
else if(type == 7) {
int witch = L4D2_SpawnWitch(pos, ang);
if(witch != -1)
SetWitchTarget(witch, target);
return witch;
}
else if(type == 8) {
// BypassLimit();
int tank = L4D2_SpawnTank(pos, ang);
if(tank <= 0 || !IsClientConnected(tank)) return -1;
if(tank != -1)
g_iAttackerTarget[tank] = GetClientUserId(target);
return tank;
}
else return -1;
}

View file

@ -1,7 +1,8 @@
public Action Timer_ThrowTimer(Handle timer) {
int count = 0;
for(int i = 1; i < MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && IsTrollActive(i, "ThrowItAll")) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && IsTrollActive(i, "Throw It All")) {
ThrowAllItems(i);
count++;
}
@ -13,14 +14,14 @@ public Action Timer_Main(Handle timer) {
static int loop;
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i)) {
if(IsTrollActive(i, "SlowDrain")) {
if(IsTrollActive(i, "Slow Drain")) {
if(loop % 4 == 0) {
int hp = GetClientHealth(i);
if(hp > 50) {
SetEntProp(i, Prop_Send, "m_iHealth", hp - 1);
}
}
}else if(IsTrollActive(i, "TempHealthQuickDrain")) {
}else if(IsTrollActive(i, "Temp Health Quick Drain")) {
if(loop % 2 == 0) {
float bufferTime = GetEntPropFloat(i, Prop_Send, "m_healthBufferTime");
float buffer = GetEntPropFloat(i, Prop_Send, "m_healthBuffer");
@ -82,9 +83,9 @@ public Action Timer_ResetAutoPunish(Handle timer, int user) {
int client = GetClientOfUserId(user);
if(client) {
if(hAutoPunish.IntValue & 2 == 2)
DisableTroll(client, "SpecialMagnet");
DisableTroll(client, "Special Magnet");
if(hAutoPunish.IntValue & 1 == 1)
DisableTroll(client, "TankMagnet");
DisableTroll(client, "Tank Magnet");
}
}
@ -93,4 +94,10 @@ public Action Timer_NextWitchSet(Handle timer, DataPack pack) {
int client = GetClientOfUserId(pack.ReadCell());
int witch = pack.ReadCell();
SetWitchTarget(witch, client);
}
public Action Timer_KickBot(Handle timer, int client) {
if(IsClientInGame(client) && (!IsClientInKickQueue(client))) {
if(IsFakeClient(client)) KickClient(client);
}
}

View file

@ -0,0 +1,48 @@
// UP THE VALUE 'MAX_TROLLS' in base.inc before adding new ones!
void SetupTrolls() {
trollKV = new StringMap();
categories = new ArrayList(ByteCountToCells(16));
SetupTroll("Reset User", "Resets the user, removes all troll effects", TrollMod_Instant);
SetCategory("Magnets");
SetupTroll("Special Magnet", "Attracts ALL specials to any alive target with this troll enabled", TrollMod_Constant);
SetupTroll("Tank Magnet", "Attracts ALL tanks to any alive target with this troll enabled", TrollMod_Constant);
SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant);
SetCategory("Infected");
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);
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
SetCategory("Items");
SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
SetupTroll("Bad Throw", "Player drops throwables on throw, and biles/molotovs themselves", TrollMod_Constant);
SetupTroll("No Pickup", "Prevents a player from picking up ANY (new) item. Use ThrowItAll to make them drop", TrollMod_Constant);
SetupTroll("UziRules", "Picking up a weapon gives them a UZI instead", TrollMod_Constant);
SetupTroll("Primary Disable", "Player cannot pickup any weapons, only melee/pistols", TrollMod_Constant);
SetupTroll("Half Primary Ammo", "Cuts their primary reserve ammo in half", TrollMod_Instant);
SetCategory("Chat");
SetupTroll("iCantSpellNoMore", "Chat messages letter will randomly changed with wrong letters", TrollMod_Instant);
SetupTroll("No Profanity", "Replaces some words with random phrases", TrollMod_Constant);
SetupTroll("Vocalize Gag", "Prevents player from sending any vocalizations (even automatic)", TrollMod_Constant);
SetupTroll("Honk", "Honk", TrollMod_Constant);
SetupTroll("Meow", "Makes the player meow", TrollMod_Constant);
SetCategory("Health");
SetupTroll("Damage Boost", "Makes a player take more damage than normal", TrollMod_Constant);
SetupTroll("Temp Health Quick Drain", "Makes a player's temporarily health drain very quickly", TrollMod_Constant);
SetupTroll("Slow Drain", "Will make the player slowly lose health over time", TrollMod_Constant);
SetupTroll("KillMeSoftly", "Make player eat or waste pills whenever possible", TrollMod_Instant | TrollMod_Constant);
SetCategory("Misc");
SetupTroll("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant);
SetupTroll("Slow Speed", "Sets player speed to 0.8x of normal speed", TrollMod_Constant);
SetupTroll("Higher Gravity", "Sets player gravity to 1.3x of normal gravity", TrollMod_Constant);
SetupTroll("No Shove", "Prevents a player from shoving", TrollMod_Constant);
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
SetupTroll("Inverted Controls", "Well, aint it obvious", TrollMod_Constant);
//INFO: UP MAX_TROLLS when adding new trolls!
}