mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-05 22:33:20 +00:00
Internal refactor
This commit is contained in:
parent
88b7ac09fc
commit
23cbb7aeac
11 changed files with 967 additions and 697 deletions
Binary file not shown.
|
@ -4,9 +4,11 @@
|
|||
//Allow MAX_TROLLS to be defined elsewhere
|
||||
#if defined MAX_TROLLS
|
||||
#else
|
||||
#define MAX_TROLLS 55
|
||||
#define MAX_TROLLS 56
|
||||
#endif
|
||||
|
||||
Troll t_metaReverse;
|
||||
|
||||
enum trollModifier {
|
||||
TrollMod_Invalid = 0,
|
||||
TrollMod_Instant = 1 << 0,
|
||||
|
@ -20,6 +22,10 @@ enum TrollEffectResponse {
|
|||
TE_Menu // Switching menus / etc, don't continue menu
|
||||
}
|
||||
|
||||
typedef ActivateFunction = function void (Troll troll, int activator, int victim, int flags, trollModifier mod);
|
||||
typedef ResetFunction = function void (Troll troll, int activator, int victim);
|
||||
typedef PromptActivateFunction = function TrollEffectResponse (Troll troll, int activator, int victim, any data, int flags, trollModifier mod);
|
||||
|
||||
StringMap trollKV;
|
||||
char trollIds[MAX_TROLLS+1][MAX_TROLL_NAME_LENGTH];
|
||||
char DEFAULT_FLAG_PROMPT_MULTIPLE[] = "Enable options (Multiple)";
|
||||
|
@ -27,7 +33,6 @@ char DEFAULT_FLAG_PROMPT[] = "Select an option";
|
|||
bool SilentMenuSelected[MAXPLAYERS+1];
|
||||
|
||||
static int g_trollAddPromptIndex;
|
||||
ArrayList gRandomClients;
|
||||
|
||||
char SPECIAL_NAMES[][] = {
|
||||
"Smoker", "Boomer", "Hunter", "Spitter", "Jockey", "Charger", "Witch", "Tank"
|
||||
|
@ -35,11 +40,17 @@ char SPECIAL_NAMES[][] = {
|
|||
|
||||
enum struct TrollFlagPrompt {
|
||||
char promptText[MAX_TROLL_FLAG_LENGTH];
|
||||
// enabled flags
|
||||
int flags;
|
||||
// default values
|
||||
int defaults;
|
||||
// is multiple flags selectable?
|
||||
bool multiselect;
|
||||
// flags that need to be active to show this prompt
|
||||
int requireFlags;
|
||||
|
||||
PrivateForward activateFn;
|
||||
|
||||
void GetPromptText(char[] prompt, int maxlength) {
|
||||
if(this.promptText[0] != '\0') {
|
||||
strcopy(prompt, maxlength, this.promptText);
|
||||
|
@ -51,19 +62,12 @@ 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) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(1 << i == powerOfTwo) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
enum struct TrollOptionData {
|
||||
char name[MAX_TROLL_FLAG_LENGTH];
|
||||
int data; // can also be float
|
||||
}
|
||||
|
||||
enum struct Troll {
|
||||
enum struct TrollData {
|
||||
int id; // The id or the index into the global Trolls[] array
|
||||
int categoryID; // The category this troll belongs in
|
||||
|
||||
|
@ -71,11 +75,15 @@ enum struct Troll {
|
|||
char description[128];
|
||||
bool hidden;
|
||||
|
||||
PrivateForward activateFn;
|
||||
PrivateForward resetFn;
|
||||
|
||||
int mods; // Combination of valid modifiers. Only two are ever supported
|
||||
|
||||
// Flags
|
||||
int activeFlagClients[MAXPLAYERS+1];
|
||||
ArrayList flagNames;
|
||||
ArrayList promptOptions;
|
||||
ArrayList flagPrompts;
|
||||
|
||||
// Custom timer
|
||||
|
@ -84,140 +92,6 @@ enum struct Troll {
|
|||
float timerInterval;
|
||||
int timerRequiredFlags;
|
||||
|
||||
void SetTimer(float interval, Timer timer, int requiredFlags = 0) {
|
||||
this.timerInterval = interval;
|
||||
this.timerFunction = timer;
|
||||
this.timerRequiredFlags = requiredFlags;
|
||||
for(int i = 0; i <= MAXPLAYERS; i++) {
|
||||
this.timerHandles[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasMod(trollModifier mod) {
|
||||
return ((this.mods >> (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.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;
|
||||
}
|
||||
|
||||
/////// FLAGS
|
||||
|
||||
bool GetFlagName(int index, char[] buffer, int maxlength) {
|
||||
if(this.flagNames == null || index >= this.flagNames.Length) return false;
|
||||
this.flagNames.GetString(index, buffer, maxlength);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetFlagNames(int client, char[] output, int maxlength) {
|
||||
if(this.flagNames == null) return false;
|
||||
char buffer[16];
|
||||
for(int i = 0; i < this.flagNames.Length; i++) {
|
||||
int value = 1 << i;
|
||||
// If client has this flag:
|
||||
if(this.activeFlagClients[client] & value) {
|
||||
this.flagNames.GetString(i, buffer, sizeof(buffer));
|
||||
Format(output, maxlength, "%s%s,", output, buffer);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int AddCustomFlagPrompt(const char[] promptText, bool multiselect = false, int requireFlags = 0) {
|
||||
TrollFlagPrompt prompt;
|
||||
prompt.multiselect = multiselect;
|
||||
prompt.requireFlags = requireFlags;
|
||||
strcopy(prompt.promptText, MAX_TROLL_FLAG_LENGTH, promptText);
|
||||
int index = this.flagPrompts.PushArray(prompt);
|
||||
g_trollAddPromptIndex = index;
|
||||
return index;
|
||||
}
|
||||
|
||||
int AddFlagPrompt(bool multiselect = false, int requireFlags = 0) {
|
||||
//g_trollAddPromptIndex
|
||||
TrollFlagPrompt prompt;
|
||||
prompt.multiselect = multiselect;
|
||||
prompt.requireFlags = requireFlags;
|
||||
int index = this.flagPrompts.PushArray(prompt);
|
||||
g_trollAddPromptIndex = index;
|
||||
return index;
|
||||
}
|
||||
|
||||
int AddFlag(const char[] name, bool defaultOn) {
|
||||
if(this.flagNames == null) {
|
||||
this.flagNames = new ArrayList(MAX_TROLL_FLAG_LENGTH);
|
||||
}
|
||||
|
||||
// Check if flag already added
|
||||
int flagIndex = this.GetFlagIndex(name);
|
||||
if(flagIndex == -1) flagIndex = this.flagNames.PushString(name);
|
||||
|
||||
// Grab the prompt
|
||||
static TrollFlagPrompt prompt;
|
||||
// TODO: CHECK IF MISSING PROMPT
|
||||
if(g_trollAddPromptIndex >= this.flagPrompts.Length) {
|
||||
ThrowError("No prompt added for troll \"%s\", for flag \"%s\"", this.id, name);
|
||||
}
|
||||
this.flagPrompts.GetArray(g_trollAddPromptIndex, prompt);
|
||||
|
||||
|
||||
prompt.flags |= (1 << flagIndex);
|
||||
|
||||
if(defaultOn) {
|
||||
// If out of bounds, set to default -1 -> pick global prompt
|
||||
if(this.flagPrompts.Length == 0) {
|
||||
ThrowError("Troll \"%s\" does not have any flag prompts, thus a default value cannot be set. (flag=\"%s\")", this.name, name);
|
||||
return -1;
|
||||
}
|
||||
if(!prompt.multiselect && prompt.defaults > 0) {
|
||||
ThrowError("Flag \"%s\" cannot be set as default flag in single select mode, as one has already been set for prompt %d", name, g_trollAddPromptIndex);
|
||||
return -1;
|
||||
}
|
||||
prompt.defaults |= (1 << flagIndex);
|
||||
}
|
||||
this.flagPrompts.SetArray(g_trollAddPromptIndex, prompt); //May not be required
|
||||
return flagIndex;
|
||||
}
|
||||
|
||||
int GetFlagIndex(const char[] flagName) {
|
||||
static char comprFlag[MAX_TROLL_FLAG_LENGTH];
|
||||
for(int i = 0; i < this.flagNames.Length; i++) {
|
||||
this.flagNames.GetString(i, comprFlag, sizeof(comprFlag));
|
||||
if(StrEqual(comprFlag, flagName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool HasFlags() {
|
||||
return this.flagNames != null && this.flagNames.Length > 0 && this.flagPrompts.Length > 0;
|
||||
}
|
||||
|
||||
int GetFlagCount() {
|
||||
return this.flagNames != null ? this.flagNames.Length : 0;
|
||||
}
|
||||
|
||||
int GetClientFlags(int client) {
|
||||
return this.activeFlagClients[client];
|
||||
}
|
||||
void GetFlagPrompt(int index, TrollFlagPrompt prompt) {
|
||||
this.flagPrompts.GetArray(index, prompt);
|
||||
}
|
||||
|
||||
/////// TROLL ACTIVATION
|
||||
|
||||
TrollEffectResponse Activate(int client, int activator, trollModifier modifier = TrollMod_Invalid, int flags = 0, bool silent = false) {
|
||||
if(modifier == TrollMod_Invalid) modifier = this.GetDefaultMod();
|
||||
// Sadly, unable to pass in <this> to ApplyTroll, so it has to do unnecessary lookup via string
|
||||
return ApplyTroll(client, this.name, activator, modifier, flags, silent);
|
||||
}
|
||||
|
||||
|
||||
void Toggle(int client, int flags) {
|
||||
if(this.IsActive(client)) {
|
||||
this.Disable(client);
|
||||
|
@ -245,25 +119,22 @@ enum struct Troll {
|
|||
PrintToServer("FTT Debug: Disabling timer for %N", client);
|
||||
delete this.timerHandles[client];
|
||||
}
|
||||
if(this.resetFn != null) {
|
||||
Call_StartForward(this.resetFn);
|
||||
Call_PushCell(0);
|
||||
Call_PushCell(client);
|
||||
Call_PushCell(0);
|
||||
Call_Finish();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsActive(int client) {
|
||||
return this.activeFlagClients[client] != -1;
|
||||
}
|
||||
|
||||
int GetRandomClient(int start = 0) {
|
||||
gRandomClients.Clear();
|
||||
for(int i = start + 1; i <= MaxClients; i++) {
|
||||
if(this.activeFlagClients[i] != -1) {
|
||||
gRandomClients.Push(i);
|
||||
}
|
||||
}
|
||||
if(gRandomClients.Length == 0) return -1;
|
||||
return GetRandomInt(0, gRandomClients.Length);
|
||||
}
|
||||
}
|
||||
|
||||
Troll Trolls[MAX_TROLLS+1];
|
||||
TrollData Trolls[MAX_TROLLS+1];
|
||||
|
||||
ArrayList categories;
|
||||
static int categoryID = -1;
|
||||
|
@ -271,10 +142,11 @@ static int categoryID = -1;
|
|||
void ResetClient(int victim, bool wipe = true) {
|
||||
if(victim == 0 || !IsClientConnected(victim)) return;
|
||||
if(wipe) {
|
||||
for(int i = 0; i <= MAX_TROLLS; i++) {
|
||||
Trolls[i].Disable(victim);
|
||||
for(int i = 1; i <= MAX_TROLLS; i++) {
|
||||
Troll(i).Reset(victim);
|
||||
}
|
||||
}
|
||||
// TODO: move to reset functions!!
|
||||
noRushingUsSpeed[victim] = 1.0;
|
||||
BaseComm_SetClientMute(victim, false);
|
||||
SetEntityGravity(victim, 1.0);
|
||||
|
@ -286,42 +158,312 @@ void ResetClient(int victim, bool wipe = true) {
|
|||
SDKUnhook(wpn, SDKHook_Reload, Event_WeaponReload);
|
||||
}
|
||||
|
||||
int SetupTroll(const char[] name, const char description[128], int mods) {
|
||||
static int i = 0;
|
||||
if(mods == 0) {
|
||||
ThrowError("Troll \"%s\" has no modifiers defined.", name);
|
||||
return -1;
|
||||
} else if(i == MAX_TROLLS + 1) {
|
||||
ThrowError("Maximum number of trolls (%d) reached. Up MAX_TROLLS value.", MAX_TROLLS);
|
||||
return -1;
|
||||
// TrollInstance of TrollData
|
||||
methodmap Troll {
|
||||
public Troll(int index) {
|
||||
return view_as<Troll>(index);
|
||||
}
|
||||
g_trollAddPromptIndex = 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].mods = mods;
|
||||
Trolls[i].flagPrompts = new ArrayList(sizeof(TrollFlagPrompt));
|
||||
|
||||
strcopy(trollIds[i], MAX_TROLL_NAME_LENGTH, name);
|
||||
trollKV.SetValue(name, i);
|
||||
return i++;
|
||||
public static Troll FromName(const char[] name) {
|
||||
int i = GetTrollID(name);
|
||||
if(i == -1)
|
||||
LogError("Unknown troll \"%s\"", name);
|
||||
return view_as<Troll>(i);
|
||||
}
|
||||
property bool Hidden {
|
||||
public get() { return Trolls[this.Id].hidden; }
|
||||
}
|
||||
property int CategoryId {
|
||||
public get() { return Trolls[this.Id].categoryID; }
|
||||
}
|
||||
property int PromptCount {
|
||||
public get() { return Trolls[this.Id].flagPrompts.Length; }
|
||||
}
|
||||
property int TotalOptionsCount {
|
||||
public get() {
|
||||
return Trolls[this.Id].promptOptions == null ? -1 : Trolls[this.Id].promptOptions.Length;
|
||||
}
|
||||
}
|
||||
property bool HasTimer {
|
||||
public get() { return Trolls[this.Id].timerInterval > 0.0; }
|
||||
}
|
||||
property int Id {
|
||||
public get() { return view_as<int>(this); }
|
||||
}
|
||||
property bool HasOptions {
|
||||
public get() { return this.TotalOptionsCount > 0; }
|
||||
}
|
||||
|
||||
public bool IsActive(int client) {
|
||||
return Trolls[this.Id].activeFlagClients[client] != -1;
|
||||
}
|
||||
|
||||
public bool HasFlag(int client, int flag) {
|
||||
return Trolls[this.Id].activeFlagClients[client] & flag != 0;
|
||||
}
|
||||
|
||||
public int GetFlags(int client) {
|
||||
return Trolls[this.Id].activeFlagClients[client]
|
||||
}
|
||||
|
||||
public bool HasMod(trollModifier mod) {
|
||||
return Trolls[this.Id].mods & view_as<int>(mod) != 0;
|
||||
}
|
||||
|
||||
public void GetName(char[] output, int maxlen) {
|
||||
strcopy(output, maxlen, Trolls[this.Id].name);
|
||||
}
|
||||
|
||||
public TrollEffectResponse Activate(int activator, int victim, trollModifier modifier = TrollMod_Invalid, int flags = 0, bool silent = false) {
|
||||
PrintToServer("Activate: act:%d vic:%d", activator, victim);
|
||||
if(modifier == TrollMod_Invalid) modifier = this.GetDefaultMod();
|
||||
return ApplyTroll(victim, this, activator, modifier, flags, silent);
|
||||
}
|
||||
public void Reset(int victim) {
|
||||
Trolls[this.Id].activeFlagClients[victim] = -1;
|
||||
if(Trolls[this.Id].resetFn != null) {
|
||||
Call_StartForward(Trolls[this.Id].resetFn);
|
||||
Call_PushCell(this);
|
||||
Call_PushCell(0);
|
||||
Call_PushCell(victim);
|
||||
Call_PushCell(0);
|
||||
Call_Finish();
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetOptionData(int optionIndex, TrollOptionData data) {
|
||||
if(optionIndex < 0 || optionIndex >= Trolls[this.Id].promptOptions.Length) return false;
|
||||
Trolls[this.Id].promptOptions.GetArray(optionIndex, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// If prompt is NOT multiselect, returns the selected value from the option's data property
|
||||
public bool GetPromptDataInt(int client, int promptIndex, int &out) {
|
||||
if(promptIndex < 0 || promptIndex >= Trolls[this.Id].flagPrompts.Length) {
|
||||
ThrowError(".GetPromptData called with invalid prompt index (%d, max %d) on troll #%d", promptIndex, Trolls[this.Id].flagPrompts.Length, this.Id);
|
||||
}
|
||||
TrollFlagPrompt prompt;
|
||||
Trolls[this.Id].flagPrompts.GetArray(promptIndex, prompt);
|
||||
if(prompt.multiselect) {
|
||||
ThrowError(".GetPromptData: attempted to receive data for a multiselect prompt. Operation unspported. promptIndex:%d troll:%d", promptIndex, this.Id);
|
||||
}
|
||||
TrollOptionData option;
|
||||
int flags = this.GetFlags(client);
|
||||
for(int i = 0; i < Trolls[this.Id].promptOptions.Length; i++) {
|
||||
int bit = 1 << i;
|
||||
// If prompt has flag AND flag is active:
|
||||
if(prompt.flags & bit && flags & bit) {
|
||||
Trolls[this.Id].promptOptions.GetArray(i, option);
|
||||
out = option.data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetPromptDataFloat(int client, int promptIndex, float &out) {
|
||||
int value;
|
||||
if(this.GetPromptDataInt(client, promptIndex, value)) {
|
||||
// We just retagged it as int, but it's float data
|
||||
out = view_as<float>(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetPrompt(int promptIndex, TrollFlagPrompt prompt) {
|
||||
if(promptIndex < 0 || promptIndex >= Trolls[this.Id].flagPrompts.Length) return false;
|
||||
Trolls[this.Id].flagPrompts.GetArray(promptIndex, prompt);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void GetOptionName(int optionIndex, char[] output, int maxlen) {
|
||||
TrollOptionData option;
|
||||
this.GetOptionData(optionIndex, option);
|
||||
strcopy(output, maxlen, option.name);
|
||||
}
|
||||
|
||||
public bool GetFlagNames(int client, int flags = -1, char[] output, int maxlength) {
|
||||
if(this.TotalOptionsCount == 0) return false;
|
||||
char buffer[32];
|
||||
if(flags == -1) flags = Trolls[this.Id].activeFlagClients[client];
|
||||
int count;
|
||||
for(int i = 0; i < this.TotalOptionsCount; i++) {
|
||||
int bit = 1 << i;
|
||||
// If client has this flag:
|
||||
if(flags & bit) {
|
||||
this.GetOptionName(i, buffer, sizeof(buffer));
|
||||
if(count == 0)
|
||||
Format(output, maxlength, "%s", buffer);
|
||||
else
|
||||
Format(output, maxlength, "%s,%s", output, buffer);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Gets the default modifier to use
|
||||
public trollModifier GetDefaultMod() {
|
||||
// If the flags is equal to the 2^n flag, then it must be the only flag:
|
||||
if(Trolls[this.Id].mods == view_as<int>(TrollMod_Instant)) return TrollMod_Instant;
|
||||
else if(Trolls[this.Id].mods == view_as<int>(TrollMod_Constant)) return TrollMod_Constant;
|
||||
else return TrollMod_Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the Troll enum struct via name
|
||||
// Returns index of troll enum
|
||||
int GetTroll(const char[] name, Troll troll) {
|
||||
static int i = 0;
|
||||
if(trollKV.GetValue(name, i)) {
|
||||
troll = Trolls[i];
|
||||
return i;
|
||||
int g_iTrollIndex;
|
||||
methodmap TrollBuilder {
|
||||
public TrollBuilder(const char[] name, const char description[128], int mods) {
|
||||
if(mods == 0) {
|
||||
ThrowError("Troll \"%s\" has no modifiers defined.", name);
|
||||
} else if(g_iTrollIndex == MAX_TROLLS + 1) {
|
||||
ThrowError("Maximum number of trolls (%d) reached. Up MAX_TROLLS value.", MAX_TROLLS);
|
||||
}
|
||||
int i = g_iTrollIndex;
|
||||
g_iTrollIndex++;
|
||||
g_trollAddPromptIndex = 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].mods = mods;
|
||||
Trolls[i].flagPrompts = new ArrayList(sizeof(TrollFlagPrompt));
|
||||
|
||||
char buffer[MAX_TROLL_NAME_LENGTH];
|
||||
strcopy(buffer, sizeof(buffer), name);
|
||||
StringToLower(buffer);
|
||||
trollKV.SetValue(buffer, i);
|
||||
return view_as<TrollBuilder>(i);
|
||||
}
|
||||
ThrowError("GetTroll: Troll was not found \"%s\"", name);
|
||||
return -1;
|
||||
|
||||
property int Id {
|
||||
public get() { return view_as<int>(this); }
|
||||
}
|
||||
|
||||
public TrollBuilder Hide() {
|
||||
Trolls[this.Id].hidden = true;
|
||||
}
|
||||
|
||||
public TrollBuilder SetDescription(const char description[128]) {
|
||||
strcopy(Trolls[this.Id].description, 128, description);
|
||||
}
|
||||
|
||||
public TrollBuilder SetTimer(float interval, Timer timer, int requiredFlags = 0) {
|
||||
Trolls[this.Id].timerInterval = interval;
|
||||
Trolls[this.Id].timerFunction = timer;
|
||||
Trolls[this.Id].timerRequiredFlags = requiredFlags;
|
||||
for(int i = 0; i <= MAXPLAYERS; i++) {
|
||||
Trolls[this.Id].timerHandles[i] = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TrollBuilder AddPrompt(const char[] customPrompt = "", int requiredFlags = 0) {
|
||||
this._AddPrompt(false, requiredFlags, customPrompt);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TrollBuilder AddPromptMulti(const char[] customPrompt = "", int requiredFlags = 0) {
|
||||
this._AddPrompt(true, requiredFlags, customPrompt);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Adds event handle for when an option for a non-multi prompt is selected. If current prompt is multi, will error
|
||||
public TrollBuilder OnPromptActivate(PromptActivateFunction fn) {
|
||||
TrollFlagPrompt prompt;
|
||||
Trolls[this.Id].flagPrompts.GetArray(g_trollAddPromptIndex, prompt);
|
||||
if(prompt.multiselect) ThrowError("Current prompt is multiselect");
|
||||
if(prompt.activateFn == null) prompt.activateFn = new PrivateForward(ET_Single, Param_Cell, Param_Cell, Param_Cell, Param_Any, Param_Cell, Param_Cell);
|
||||
prompt.activateFn.AddFunction(INVALID_HANDLE, fn);
|
||||
|
||||
Trolls[this.Id].flagPrompts.SetArray(g_trollAddPromptIndex, prompt);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void _AddPrompt(bool multiselect, int requiredFlags = 0, const char[] customPrompt) {
|
||||
TrollFlagPrompt prompt;
|
||||
prompt.multiselect = multiselect;
|
||||
prompt.requireFlags = requiredFlags;
|
||||
if(customPrompt[0] != '\0')
|
||||
strcopy(prompt.promptText, MAX_TROLL_FLAG_LENGTH, customPrompt);
|
||||
int index = Trolls[this.Id].flagPrompts.PushArray(prompt);
|
||||
g_trollAddPromptIndex = index;
|
||||
}
|
||||
|
||||
public TrollBuilder AddOption(const char[] name, bool defaultOn = false) {
|
||||
this._AddOption(name, defaultOn);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TrollBuilder AddOptionInt(const char[] name, bool defaultOn = false, int data) {
|
||||
this._AddOption(name, defaultOn, data);
|
||||
return this;
|
||||
}
|
||||
public TrollBuilder AddOptionFloat(const char[] name, bool defaultOn = false, float data) {
|
||||
// This is intentional - we do not want to convert float -> int, just change type
|
||||
this._AddOption(name, defaultOn, view_as<int>(data));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void _AddOption(const char[] name, bool defaultOn = false, int data = 0) {
|
||||
if(Trolls[this.Id].promptOptions == null) {
|
||||
Trolls[this.Id].promptOptions = new ArrayList(sizeof(TrollOptionData));
|
||||
}
|
||||
TrollOptionData option;
|
||||
strcopy(option.name, MAX_TROLL_FLAG_LENGTH, name);
|
||||
option.data = data;
|
||||
int optionIndex = Trolls[this.Id].promptOptions.PushArray(option);
|
||||
|
||||
// Add option to current prompt
|
||||
TrollFlagPrompt prompt;
|
||||
if(g_trollAddPromptIndex >= Trolls[this.Id].flagPrompts.Length) {
|
||||
ThrowError("No prompt added for troll \"%s\", for flag \"%s\"", this.Id, name);
|
||||
}
|
||||
Trolls[this.Id].flagPrompts.GetArray(g_trollAddPromptIndex, prompt);
|
||||
prompt.flags |= ( 1 << optionIndex );
|
||||
if(defaultOn) {
|
||||
// If out of bounds, set to default -1 -> pick global prompt
|
||||
if(Trolls[this.Id].flagPrompts.Length == 0) {
|
||||
ThrowError("Troll \"%s\" does not have any flag prompts, thus a default value cannot be set. (flag=\"%s\")", Trolls[this.Id].name, name);
|
||||
} else if(!prompt.multiselect && prompt.defaults > 0) {
|
||||
ThrowError("Flag \"%s\" cannot be set as default flag in single select mode, as one has already been set for prompt %d", name, g_trollAddPromptIndex);
|
||||
}
|
||||
prompt.defaults |= (1 << optionIndex);
|
||||
}
|
||||
// Save changes to prompt
|
||||
Trolls[this.Id].flagPrompts.SetArray(g_trollAddPromptIndex, prompt);
|
||||
|
||||
}
|
||||
|
||||
public TrollBuilder SetActivationFunction(ActivateFunction fn) {
|
||||
if(Trolls[this.Id].activateFn == null) {
|
||||
Trolls[this.Id].activateFn = new PrivateForward(ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell);
|
||||
}
|
||||
Trolls[this.Id].activateFn.AddFunction(INVALID_HANDLE, fn);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TrollBuilder SetResetFunction(ResetFunction fn) {
|
||||
if(Trolls[this.Id].resetFn == null) {
|
||||
Trolls[this.Id].resetFn = new PrivateForward(ET_Ignore, Param_Cell, Param_Cell, Param_Cell);
|
||||
}
|
||||
Trolls[this.Id].resetFn.AddFunction(INVALID_HANDLE, fn);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Troll Build() {
|
||||
return Troll(this.Id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetTrollID(const char[] name) {
|
||||
static int i = 0;
|
||||
if(trollKV.GetValue(name, i)) {
|
||||
char buffer[MAX_TROLL_NAME_LENGTH];
|
||||
strcopy(buffer, sizeof(buffer), name);
|
||||
StringToLower(buffer);
|
||||
if(trollKV.GetValue(buffer, i)) {
|
||||
return i;
|
||||
}
|
||||
PrintToServer("GetTrollID: Troll was not found \"%s\"", name);
|
||||
|
@ -334,11 +476,6 @@ bool IsAnyTrollActive(int victim) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
// Gets the Troll enum struct via key index
|
||||
// Returns index of troll enum
|
||||
void GetTrollByKeyIndex(int index, Troll troll) {
|
||||
troll = Trolls[index];
|
||||
}
|
||||
|
||||
void SetTrollFlags(int client, const char[] name, int flags = -1) {
|
||||
int index = GetTrollID(name);
|
||||
|
@ -349,19 +486,15 @@ void SetTrollFlags(int client, const char[] name, int flags = -1) {
|
|||
}
|
||||
|
||||
|
||||
TrollEffectResponse ApplyTroll(int victim, const char[] name, int activator, trollModifier modifier, int flags = 0, bool silent = false) {
|
||||
static Troll troll;
|
||||
int trollIndex = GetTroll(name, troll);
|
||||
if(trollIndex == -1) {
|
||||
ReplyToCommand(activator, "Unknown troll \"%s\"", name);
|
||||
PrintToServer("[FTT] %N attempted to apply unknown troll: %s", activator, name);
|
||||
return TE_Error;
|
||||
}
|
||||
TrollEffectResponse ApplyTroll(int victim, Troll troll, int activator, trollModifier modifier, int flags = 0, bool silent = false) {
|
||||
char name[MAX_TROLL_NAME_LENGTH];
|
||||
troll.GetName(name, sizeof(name));
|
||||
int trollIndex = troll.Id;
|
||||
|
||||
bool isActive = Trolls[trollIndex].activeFlagClients[victim] > -1;
|
||||
bool isActive = troll.IsActive(victim);
|
||||
|
||||
// Clear troll specific timer:
|
||||
if(Trolls[trollIndex].timerInterval > 0.0) {
|
||||
if(troll.HasTimer) {
|
||||
if(!isActive) {
|
||||
if(modifier & TrollMod_Constant && (Trolls[trollIndex].timerRequiredFlags == 0 || Trolls[trollIndex].timerRequiredFlags & flags)) {
|
||||
Trolls[trollIndex].timerHandles[victim] = CreateTimer(Trolls[trollIndex].timerInterval, Trolls[trollIndex].timerFunction, victim, TIMER_REPEAT);
|
||||
|
@ -374,14 +507,10 @@ TrollEffectResponse ApplyTroll(int victim, const char[] name, int activator, tro
|
|||
|
||||
if(!silent && SilentMenuSelected[activator]) silent = true;
|
||||
|
||||
static int MetaInverseTrollID;
|
||||
if(!MetaInverseTrollID) MetaInverseTrollID = GetTrollID("Meta: Inverse");
|
||||
|
||||
if(activator > 0 && Trolls[MetaInverseTrollID].IsActive(activator)) {
|
||||
float max = 1.0;
|
||||
if(Trolls[MetaInverseTrollID].activeFlagClients[activator] & 2) max = 0.5;
|
||||
else if(Trolls[MetaInverseTrollID].activeFlagClients[activator] & 4) max = 0.1;
|
||||
if(GetURandomFloat() <= max) {
|
||||
if(activator > 0 && t_metaReverse.IsActive(activator)) {
|
||||
float chance;
|
||||
t_metaReverse.GetPromptDataFloat(activator, 0, chance);
|
||||
if(GetURandomFloat() <= chance) {
|
||||
victim = activator;
|
||||
}
|
||||
}
|
||||
|
@ -391,9 +520,9 @@ TrollEffectResponse ApplyTroll(int victim, const char[] name, int activator, tro
|
|||
int player = GetSpectatorClient(victim);
|
||||
if(player > 0) {
|
||||
// If there is an idle player, apply troll to them
|
||||
ApplyTroll(player, name, activator, modifier, flags, silent);
|
||||
ApplyTroll(player, troll, activator, modifier, flags, silent);
|
||||
// And continue IF there is TrollMod_PlayerOnly mod
|
||||
if(troll.mods & view_as<int>(TrollMod_PlayerOnly)) return TE_Success;
|
||||
if(troll.HasMod(TrollMod_PlayerOnly)) return TE_Success;
|
||||
// Don't want to show two logs, so just ignore the bot
|
||||
silent = true;
|
||||
}
|
||||
|
@ -409,63 +538,77 @@ TrollEffectResponse ApplyTroll(int victim, const char[] name, int activator, tro
|
|||
TrollEffectResponse response = ApplyAffect(victim, troll, activator, modifier, flags);
|
||||
if(response != TE_Success) return response; // Let the menu handler deal with checking
|
||||
|
||||
// Invoke Callbacks:
|
||||
if(!isActive) {
|
||||
Troll instance = Troll(trollIndex);
|
||||
if(Trolls[trollIndex].activateFn != null) {
|
||||
Call_StartForward(Trolls[trollIndex].activateFn);
|
||||
Call_PushCell(instance);
|
||||
Call_PushCell(activator);
|
||||
Call_PushCell(victim);
|
||||
Call_PushCell(flags);
|
||||
Call_PushCell(modifier);
|
||||
Call_Finish();
|
||||
}
|
||||
|
||||
// Call the corresponding prompt callback if applicable
|
||||
TrollFlagPrompt prompt;
|
||||
for(int i = 0; i < Trolls[trollIndex].flagPrompts.Length; i++) {
|
||||
Trolls[trollIndex].flagPrompts.GetArray(i, prompt);
|
||||
if(!prompt.multiselect && prompt.activateFn != null) {
|
||||
int value;
|
||||
instance.GetPromptDataInt(victim, i, value);
|
||||
for(int j = 0; j < Trolls[trollIndex].promptOptions.Length; i++) {
|
||||
int bit = 1 << j;
|
||||
if(flags & bit && prompt.flags & bit) {
|
||||
Call_StartForward(prompt.activateFn);
|
||||
Call_PushCell(instance);
|
||||
Call_PushCell(activator);
|
||||
Call_PushCell(victim);
|
||||
Call_PushCell(value);
|
||||
Call_PushCell(flags);
|
||||
Call_PushCell(modifier);
|
||||
response = view_as<TrollEffectResponse>(Call_Finish());
|
||||
if(response != TE_Success) return response; // Let the menu handler deal with checking
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if(isActive && Trolls[trollIndex].resetFn != null) {
|
||||
Call_StartForward(Trolls[trollIndex].resetFn);
|
||||
Call_PushCell(Troll(trollIndex));
|
||||
Call_PushCell(activator);
|
||||
Call_PushCell(victim);
|
||||
Call_PushCell(modifier);
|
||||
Call_Finish();
|
||||
}
|
||||
|
||||
// Log all actions, indicating if constant or single-fire, and if any flags
|
||||
if(!silent) {
|
||||
if(isActive) {
|
||||
CShowActivityEx(activator, "[FTT] ", "deactivated {yellow}%s{default} on %N. ", troll.name, victim);
|
||||
LogAction(activator, victim, "\"%L\" deactivated \"%s\" on \"%L\"", activator, troll.name, victim);
|
||||
CShowActivityEx(activator, "[FTT] ", "deactivated {yellow}%s{default} on %N. ", name, victim);
|
||||
LogAction(activator, victim, "\"%L\" deactivated \"%s\" on \"%L\"", activator, name, victim);
|
||||
} else {
|
||||
char flagName[MAX_TROLL_FLAG_LENGTH];
|
||||
// strcopy(flagName, sizeof(flagName), troll.name)
|
||||
// Call_StartForward(g_TrollAppliedForward);
|
||||
// Call_PushCell(victim);
|
||||
// Call_PushString(flagName);
|
||||
// Call_PushCell(flags);
|
||||
// Call_PushCell(activator);
|
||||
// Call_Finish();
|
||||
if(flags > 0) {
|
||||
troll.GetFlagNames(victim, flagName, sizeof(flagName));
|
||||
// Checks if there is not more than one flag set on the bitfield
|
||||
// if(flags & flags - 1 == 0 && flags & flags + 1 == 0) {
|
||||
// // Get the flag name if there is only one flag set
|
||||
// troll.GetFlagName(GetIndexFromPower(flags), flagName, sizeof(flagName));
|
||||
// } else {
|
||||
// Format(flagName, sizeof(flagName), "%d", flags);
|
||||
// }
|
||||
char flagName[50];
|
||||
if(flags > 0 && troll.GetFlagNames(victim, flags, flagName, sizeof(flagName))) {
|
||||
Format(flagName, sizeof(flagName), " (\x04%s|%d\x01)", flagName, flags);
|
||||
// CFormatColor(flagName, sizeof(flagName));
|
||||
}
|
||||
|
||||
if(modifier & TrollMod_Constant) {
|
||||
CShowActivityEx(activator, "[FTT] ", "activated constant {yellow}%s{default}%s for %N. ", troll.name, flagName, victim);
|
||||
CShowActivityEx(activator, "[FTT] ", "activated constant {yellow}%s{default}%s for %N. ", name, flagName, victim);
|
||||
} else {
|
||||
CShowActivityEx(activator, "[FTT] ", "activated {yellow}%s{default}%s for %N. ", troll.name, flagName, victim);
|
||||
CShowActivityEx(activator, "[FTT] ", "activated {yellow}%s{default}%s for %N. ", name, flagName, victim);
|
||||
}
|
||||
LogAction(activator, victim, "\"%L\" activated \"%s\" (%d) for \"%L\"", activator, troll.name, flags, victim);
|
||||
LogAction(activator, victim, "\"%L\" activated \"%s\" (%d) for \"%L\"", activator, name, flags, victim);
|
||||
}
|
||||
} else {
|
||||
CReplyToCommand(activator, "[FTT] Applied silently {yellow}\"%s\"{default} on %N with flags=%d", troll.name, victim, flags);
|
||||
CReplyToCommand(activator, "[FTT] Applied silently {yellow}\"%s\"{default} on %N with flags=%d", name, victim, flags);
|
||||
}
|
||||
return TE_Success;
|
||||
}
|
||||
|
||||
bool IsTrollActive(int client, const char[] troll) {
|
||||
if(troll[0] == '\0') {
|
||||
ThrowError("Troll name is empty");
|
||||
return false;
|
||||
}
|
||||
static int i = 0;
|
||||
if(trollKV.GetValue(troll, i)) {
|
||||
return Trolls[i].activeFlagClients[client] != -1;
|
||||
}
|
||||
ThrowError("Troll \"%s\" does not exist", troll);
|
||||
return false; //errors instead but compiler no like
|
||||
}
|
||||
|
||||
bool IsTrollActiveByRawID(int client, int id) {
|
||||
return Trolls[id].activeFlagClients[client] != -1;
|
||||
}
|
||||
|
||||
|
||||
void EnableTroll(int client, const char[] troll, int flags = 0) {
|
||||
SetTrollFlags(client, troll, flags);
|
||||
|
@ -496,12 +639,8 @@ public int Native_ApplyTroll(Handle plugin, int numParams) {
|
|||
int flags = GetNativeCell(4);
|
||||
int activator = GetNativeCell(5);
|
||||
|
||||
int index = GetTrollID(name);
|
||||
if(index > 0) {
|
||||
Trolls[index].Activate(victim, activator, modifier, flags, GetNativeCell(6));
|
||||
} else {
|
||||
ThrowNativeError(SP_ERROR_NATIVE, "Could not find troll with name \"%s\"", name);
|
||||
}
|
||||
Troll troll = Troll.FromName(name);
|
||||
troll.Activate(victim, activator, modifier, flags, GetNativeCell(6));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -11,10 +11,10 @@ enum struct TrollCombo {
|
|||
ArrayList trolls;
|
||||
|
||||
void AddTroll(const char[] name, int flags = 0, trollModifier mod = TrollMod_Invalid) {
|
||||
int id = GetTrollID(name);
|
||||
if(mod == TrollMod_Invalid) mod = Trolls[id].GetDefaultMod();
|
||||
Troll instance = Troll.FromName(name);
|
||||
if(mod == TrollMod_Invalid) mod = instance.GetDefaultMod();
|
||||
SpecifiedTroll troll;
|
||||
troll.id = id;
|
||||
troll.id = instance.Id;
|
||||
troll.mod = mod;
|
||||
troll.flags = flags;
|
||||
this.trolls.PushArray(troll, sizeof(troll));
|
||||
|
@ -24,7 +24,7 @@ enum struct TrollCombo {
|
|||
for(int i = 0; i < this.trolls.Length; i++) {
|
||||
SpecifiedTroll troll;
|
||||
this.trolls.GetArray(i, troll, sizeof(troll));
|
||||
Trolls[troll.id].Activate(target, client, troll.mod, troll.flags);
|
||||
Troll(troll.id).Activate(target, client, troll.mod, troll.flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,9 +130,12 @@ Action Command_InstaSpecialFace(int client, int args) {
|
|||
|
||||
|
||||
Action Command_WitchAttack(int client, int args) {
|
||||
if(args < 1) {
|
||||
if(!g_actionsAvailable) {
|
||||
ReplyToCommand(client, "Unavailable: Missing \"actions\"");
|
||||
return Plugin_Handled;
|
||||
} else if(args < 1) {
|
||||
ReplyToCommand(client, "Usage: sm_witch_attack <user> [# of witches or 0 for all]");
|
||||
}else{
|
||||
} else{
|
||||
char arg1[32];
|
||||
GetCmdArg(1, arg1, sizeof(arg1));
|
||||
char target_name[MAX_TARGET_LENGTH];
|
||||
|
@ -377,6 +380,7 @@ public Action Command_ListTheTrolls(int client, int args) {
|
|||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char buffer[50];
|
||||
for(int p = 0; p < target_count; p++) {
|
||||
int target = target_list[p];
|
||||
if(IsPlayerAlive(target))
|
||||
|
@ -389,24 +393,17 @@ public Action Command_ListTheTrolls(int client, int args) {
|
|||
if(player != -1) target = player;
|
||||
}
|
||||
|
||||
for(int j = 1; j <= MAX_TROLLS; j++) {
|
||||
if(Trolls[j].hidden) continue;
|
||||
if(trollIds[j][0] != '\0' && IsTrollActive(target, trollIds[j])) {
|
||||
if(Trolls[j].activeFlagClients[target] > 0) {
|
||||
static char list[MAX_TROLL_FLAG_LENGTH*8]; //May in future need to up magic number 8 (supports 8 active flags )
|
||||
static char buffer[MAX_TROLL_FLAG_LENGTH];
|
||||
for(int i = 0; i < Trolls[j].flagNames.Length; i++) {
|
||||
int a = (1 << i);
|
||||
if(Trolls[j].activeFlagClients[target] & a) {
|
||||
Trolls[j].flagNames.GetString(i, buffer, sizeof(buffer));
|
||||
Format(list, sizeof(list), "%s%s;", list, buffer);
|
||||
} else {
|
||||
Trolls[j].flagNames.GetString(i, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
ReplyToCommand(client, "\"%s\" Flags: %s", trollIds[j], list);
|
||||
for(int j = 1; j < MAX_TROLLS; j++) {
|
||||
Troll troll = Troll(j);
|
||||
if(troll.Hidden) continue;
|
||||
if(troll.IsActive(target)) {
|
||||
int flags = troll.GetFlags(target);
|
||||
if(flags > 0) {
|
||||
buffer[0] = '\0';
|
||||
troll.GetFlagNames(target, flags, buffer, sizeof(buffer));
|
||||
ReplyToCommand(client, "\"%s\" Flags: %s", Trolls[troll.Id].name, buffer);
|
||||
} else
|
||||
ReplyToCommand(client, trollIds[j]);
|
||||
ReplyToCommand(client, "%s", Trolls[troll.Id].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,8 +421,9 @@ public Action Command_ListTheTrolls(int client, int args) {
|
|||
}
|
||||
int modeCount = 0;
|
||||
for(int j = 1; j <= MAX_TROLLS; j++) {
|
||||
if(trollIds[j][0] != '\0' && IsTrollActive(i, trollIds[j])) {
|
||||
if(Trolls[j].activeFlagClients[i] > 0)
|
||||
Troll troll = Troll(j);
|
||||
if(troll.IsActive(i)) {
|
||||
if(troll.GetFlags(i) > 0)
|
||||
Format(modeListArr[modeCount], MAX_TROLL_NAME_LENGTH, "%s(%d)", trollIds[j], Trolls[j].activeFlagClients[i]);
|
||||
else
|
||||
strcopy(modeListArr[modeCount], MAX_TROLL_NAME_LENGTH, trollIds[j]);
|
||||
|
@ -729,7 +727,7 @@ Action Command_SetReverseFF(int client, int args) {
|
|||
}
|
||||
|
||||
}
|
||||
ApplyTroll(target, "Reverse FF", client, TrollMod_Constant, flag);
|
||||
ApplyTroll(target, Troll.FromName("Reverse FF"), client, TrollMod_Constant, flag);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
@ -749,7 +747,7 @@ Action Command_SetMagnetShortcut(int client, int args) {
|
|||
}
|
||||
Action Command_CarSplat(int client, int args) {
|
||||
if(args < 1) {
|
||||
ReplyToCommand(client, "Usage: sm_magnet <target> [top/front/back]");
|
||||
ReplyToCommand(client, "Usage: sm_carsplat <target> [top/front/back]");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
char arg[32];
|
||||
|
@ -779,9 +777,21 @@ Action Command_CarSplat(int client, int args) {
|
|||
LogAction(client, target, "spawned car on/in %s of \"%L\"", arg, target);
|
||||
ShowActivity(client, "spawned car (%s) of %N", arg, target);
|
||||
} else {
|
||||
Troll troll;
|
||||
GetTroll("Car Splat", troll);
|
||||
Troll troll = Troll.FromName("Car Splat");
|
||||
ShowSelectFlagMenu(client, GetClientUserId(target), view_as<int>(TrollMod_Instant), troll);
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
Action Command_AddTypo(int client, int args) {
|
||||
if(args == 2) {
|
||||
char src[32], replacement[32];
|
||||
GetCmdArg(1, src, sizeof(src));
|
||||
GetCmdArg(2, replacement, sizeof(replacement));
|
||||
AddTypo(src, replacement, true);
|
||||
ShowActivity(client, "added typo \"%s\" -> \"%s\"", src, replacement);
|
||||
} else {
|
||||
ReplyToCommand(client, "Syntax: /typo <source> <typo>");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
|
@ -22,13 +22,13 @@ public void OnMapStart() {
|
|||
|
||||
g_spSpawnQueue.Clear();
|
||||
spIsActive = false;
|
||||
//CreateTimer(30.0, Timer_AutoPunishCheck, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client) {
|
||||
pdata[client].pendingTrollBan = 0;
|
||||
pdata[client].shootAtTarget = 0;
|
||||
fAntiRushFrequencyCounter[client] = 0.0;
|
||||
if(IsTrollActive(client, "Voice Mute"))
|
||||
if(t_voiceMute.IsActive(client))
|
||||
BaseComm_SetClientMute(client, true);
|
||||
SDKHook(client, SDKHook_OnTakeDamage, Event_TakeDamage);
|
||||
SDKHook(client, SDKHook_OnTakeDamageAlive, NerfGun_OnTakeDamage);
|
||||
|
@ -63,7 +63,7 @@ void OnCarHitByTank(const char[] output, int caller, int activator, float delay)
|
|||
}
|
||||
|
||||
void EntityCreateCallback(int entity) {
|
||||
if(!HasEntProp(entity, Prop_Send, "m_hOwnerEntity") || !IsValidEntity(entity)) return;
|
||||
if(!IsValidEntity(entity) || !HasEntProp(entity, Prop_Send, "m_hOwnerEntity")) return;
|
||||
static char class[16];
|
||||
|
||||
static int badThrowID;
|
||||
|
@ -126,9 +126,8 @@ enum ProjectileMagnetType {
|
|||
ProjType_Cars = 4,
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Event_DoorToggle(Event event, const char[] name, bool dontBroadcast) {
|
||||
void Event_DoorToggle(Event event, const char[] name, bool dontBroadcast) {
|
||||
// TODO: hook OnOpen entity output?
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client && Trolls[t_slipperyShoesIndex].IsActive(client) && Trolls[t_slipperyShoesIndex].activeFlagClients[client] & 2) {
|
||||
L4D_StaggerPlayer(client, client, NULL_VECTOR);
|
||||
|
@ -185,14 +184,25 @@ Action Timer_CheckSpecial(Handle h, int specialID) {
|
|||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
public void Frame_Boom(int special) {
|
||||
void Frame_Boom(int special) {
|
||||
SDKHooks_TakeDamage(special, special, special, 1000.0);
|
||||
}
|
||||
public void Event_PlayerFirstSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||
void Event_PlayerFirstSpawn(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0)
|
||||
ResetClient(client, true);
|
||||
}
|
||||
void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0) {
|
||||
for(int i = 0 ; i < MAX_TROLLS; i++) {
|
||||
Trolls[i].activeFlagClients[client] = 0;
|
||||
if(Trolls[i].timerHandles[client] != null) {
|
||||
delete Trolls[i].timerHandles[client];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
|
||||
int userid = event.GetInt("userid");
|
||||
|
@ -216,7 +226,7 @@ public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast
|
|||
}
|
||||
public Action Event_WeaponReload(int weapon) {
|
||||
int client = GetEntPropEnt(weapon, Prop_Send, "m_hOwner");
|
||||
if(client > 0 && IsTrollActive(client, "Gun Jam")) {
|
||||
if(client > 0 && t_gunJam.IsActive(client)) {
|
||||
if(GetRandomFloat() < 0.10) { //10% chance gun jams
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
@ -385,7 +395,8 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
|
|||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
bool WillMagnetRun(const Troll troll, int i) {
|
||||
// TODO: migrate to Troll
|
||||
bool WillMagnetRun(const TrollData troll, int i) {
|
||||
// In the case none of the flags are set, return true (100% chance)
|
||||
// Some systems may give magnet w/ no flags
|
||||
if(troll.activeFlagClients[i] == 0) return true;
|
||||
|
@ -451,7 +462,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
|
|||
}
|
||||
PrintToServer("%N: %s", client, sArgs);
|
||||
return Plugin_Handled;
|
||||
} else if(IsTrollActive(client, "Reversed")) {
|
||||
} else if(Troll.FromName("Reversed").IsActive(client)) {
|
||||
int length = strlen(sArgs);
|
||||
char[] message = new char[length+1];
|
||||
int j = 0;
|
||||
|
@ -462,7 +473,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
|
|||
CPrintToChatAll("{blue}%N {default}: %s", client, message);
|
||||
PrintToServer("%N: %s", client, sArgs);
|
||||
return Plugin_Handled;
|
||||
}else if(IsTrollActive(client, "iCantSpellNoMore")) {
|
||||
}else if(Troll.FromName("iCantSpellNoMore").IsActive(client)) {
|
||||
int type = GetRandomInt(1, 14 + 3);
|
||||
char letterSrc, replaceChar;
|
||||
switch(type) {
|
||||
|
@ -585,18 +596,21 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
|
|||
PrintToServer("%N: %s", client, sArgs);
|
||||
return Plugin_Handled;
|
||||
} else if(Trolls[typooId].IsActive(client)) {
|
||||
char strings[32][MAX_TYPOS_LENGTH];
|
||||
int words = ExplodeString(sArgs, " ", strings, 32, MAX_TYPOS_LENGTH);
|
||||
// Replace all typos
|
||||
static char typoReplacement[32];
|
||||
for(int i = 0; i < words; i++) {
|
||||
if(TYPOS_DICT.GetString(strings[i], typoReplacement, sizeof(typoReplacement))) {
|
||||
strcopy(strings[i], MAX_TYPOS_LENGTH, typoReplacement);
|
||||
}
|
||||
}
|
||||
int length = MAX_TYPOS_LENGTH * words;
|
||||
char[] message = new char[length];
|
||||
ImplodeStrings(strings, 32, " ", message, length);
|
||||
int len = strlen(sArgs) + 40;
|
||||
char[] message = new char[len];
|
||||
ReplaceWithTypos(sArgs, message, len);
|
||||
// char strings[32][MAX_TYPOS_LENGTH];
|
||||
// int words = ExplodeString(sArgs, " ", strings, 32, MAX_TYPOS_LENGTH);
|
||||
// // Replace all typos
|
||||
// static char typoReplacement[32];
|
||||
// for(int i = 0; i < words; i++) {
|
||||
// if(TYPOS_DICT.GetString(strings[i], typoReplacement, sizeof(typoReplacement))) {
|
||||
// strcopy(strings[i], MAX_TYPOS_LENGTH, typoReplacement);
|
||||
// }
|
||||
// }
|
||||
// int length = MAX_TYPOS_LENGTH * words;
|
||||
// char[] message = new char[length];
|
||||
// ImplodeStrings(strings, 32, " ", message, length);
|
||||
|
||||
CPrintToChatAll("{blue}%N {default}: %s", client, message);
|
||||
PrintToServer("%N: %s", client, sArgs);
|
||||
|
@ -636,7 +650,7 @@ public Action Event_ItemPickup(int client, int weapon) {
|
|||
} else if(flags & 32 && GetEntityClassname(weapon, wpnName, sizeof(wpnName)) && StrEqual(wpnName, "weapon_gascan")) {
|
||||
return Plugin_Handled;
|
||||
}
|
||||
} else if(Trolls[UziRulesIndex].IsActive(client) || IsTrollActive(client, "Primary Disable")) {
|
||||
} else if(Trolls[UziRulesIndex].IsActive(client) || Troll.FromName("Primary Disable").IsActive(client)) {
|
||||
GetEdictClassname(weapon, wpnName, sizeof(wpnName));
|
||||
if(strcmp(wpnName[7], "rifle") >= 0
|
||||
|| strcmp(wpnName[7], "smg") >= 0
|
||||
|
@ -664,7 +678,7 @@ public Action Event_ItemPickup(int client, int weapon) {
|
|||
SetCommandFlags("give", flags);
|
||||
return Plugin_Stop;
|
||||
}
|
||||
} else if(IsTrollActive(client, "Primary Disable")) {
|
||||
} else if(Troll.FromName("Primary Disable").IsActive(client)) {
|
||||
return Plugin_Stop;
|
||||
}
|
||||
}
|
||||
|
@ -793,9 +807,9 @@ Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float& damage
|
|||
if(isSameTeam && Trolls[t_reverseFFIndex].IsActive(attacker)) {
|
||||
// Should this be applied? (as in no FF granted)
|
||||
bool disableFF = false;
|
||||
if(damagetype == DMG_BURN) {
|
||||
if(damagetype & DMG_BURN) {
|
||||
disableFF = Trolls[t_reverseFFIndex].activeFlagClients[attacker] & 32 != 0;
|
||||
} else if(damagetype == DMG_BLAST) {
|
||||
} else if(damagetype & DMG_BLAST) {
|
||||
disableFF = Trolls[t_reverseFFIndex].activeFlagClients[attacker] & 64 != 0;
|
||||
} else {
|
||||
// Does not run if DMG_BURN or DMG_BLAST
|
||||
|
@ -932,11 +946,13 @@ public Action SoundHook(int clients[MAXPLAYERS], int& numClients, char sample[PL
|
|||
if(Trolls[honkID].IsActive(entity)) {
|
||||
if(Trolls[honkID].activeFlagClients[entity] & 1)
|
||||
strcopy(sample, sizeof(sample), "player/footsteps/clown/concrete1.wav");
|
||||
else if(Trolls[honkID].activeFlagClients[entity] & 2)
|
||||
else if(Trolls[honkID].activeFlagClients[entity] & 2) {
|
||||
strcopy(sample, sizeof(sample), "custom/meow1.mp3");
|
||||
else if(Trolls[honkID].activeFlagClients[entity] & 4)
|
||||
volume += 0.2;
|
||||
} else if(Trolls[honkID].activeFlagClients[entity] & 4) {
|
||||
strcopy(sample, sizeof(sample), "custom/woof1.mp3");
|
||||
else
|
||||
volume += 0.6;
|
||||
} else
|
||||
return Plugin_Continue;
|
||||
return Plugin_Changed;
|
||||
} else if(Trolls[vocalGagID].IsActive(entity)) {
|
||||
|
@ -1050,14 +1066,9 @@ public void L4D2_CInsectSwarm_CanHarm_Post(int acid, int spitter, int entity) {
|
|||
|
||||
public void Event_EnteredSpit(Event event, const char[] name, bool dontBroadcast) {
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(Trolls[t_stickyGooIndex].IsActive(client)) {
|
||||
int flags = Trolls[t_stickyGooIndex].activeFlagClients[client];
|
||||
float movement = 0.0;
|
||||
if(flags & 1) movement = 0.9;
|
||||
else if(flags & 2) movement = 0.8;
|
||||
else if(flags & 4) movement = 0.7;
|
||||
else if(flags & 8) movement = 0.5;
|
||||
else if(flags & 16) movement = 0.3;
|
||||
if(t_stickyGoo.IsActive(client)) {
|
||||
float movement;
|
||||
t_stickyGoo.GetPromptDataFloat(client, 0, movement);
|
||||
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", movement);
|
||||
pdata[client].lastInSpitTime = GetGameTime();
|
||||
if(~pdata[client].flags & view_as<int>(Flag_HasSpitTimer)) {
|
||||
|
@ -1065,22 +1076,18 @@ public void Event_EnteredSpit(Event event, const char[] name, bool dontBroadcast
|
|||
pdata[client].flags |= view_as<int>(Flag_HasSpitTimer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Event_BotPlayerSwap(Event event, const char[] name, bool dontBroadcast) {
|
||||
//Player replaced their idle bot
|
||||
int client = GetClientOfUserId(event.GetInt("player"));
|
||||
if(client > 0) {
|
||||
bool debug_hadTroll = false;
|
||||
for(int i = 1; i <= MAX_TROLLS; i++) {
|
||||
if(Trolls[i].IsActive(client) && Trolls[i].HasMod(TrollMod_Constant)) { //Add activeFlagClients >= 0 check possibly?
|
||||
ApplyAffect(client, Trolls[i], -1, TrollMod_Constant, Trolls[i].activeFlagClients[client]);
|
||||
debug_hadTroll = true;
|
||||
Troll troll = Troll(i);
|
||||
if(troll.IsActive(client) && troll.HasMod(TrollMod_Constant)) { //Add activeFlagClients >= 0 check possibly?
|
||||
ApplyAffect(client, troll, -1, TrollMod_Constant, troll.GetFlags(client));
|
||||
}
|
||||
}
|
||||
if(debug_hadTroll)
|
||||
PrintToServer("[FTT] Re-applied trolls for was-idle player %N", client);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ public int ChooseCategoryHandler(Menu menu, MenuAction action, int param1, int p
|
|||
|
||||
// Reset troll:
|
||||
if(category == -1) {
|
||||
ApplyTroll(GetClientOfUserId(userid), "Reset User", param1, TrollMod_Instant);
|
||||
Troll.FromName("Reset User").Activate(param1, victim, TrollMod_Instant);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -182,22 +182,22 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
|
|||
static char str[2][8];
|
||||
ExplodeString(info, "|", str, 2, 8, false);
|
||||
int userid = StringToInt(str[0]);
|
||||
int client = GetClientOfUserId(userid);
|
||||
if(client == 0) {
|
||||
int victim = GetClientOfUserId(userid);
|
||||
if(victim == 0) {
|
||||
ReplyToCommand(param1, "FTT: Could not acquire player");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keyIndex = StringToInt(str[1]);
|
||||
static Troll troll;
|
||||
GetTrollByKeyIndex(keyIndex, troll);
|
||||
Troll troll = Troll(keyIndex);
|
||||
//If troll has multiple flags, prompt:
|
||||
if(StrEqual(troll.name, "Throw It All")) {
|
||||
if(troll == t_throwItAll) {
|
||||
// Setup menu to call itself, but with an extra data point
|
||||
ShowThrowItAllMenu(param1, userid);
|
||||
} else if(!troll.IsActive(client) && troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
|
||||
} else if(!troll.IsActive(victim) && troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
|
||||
Menu modiferMenu = new Menu(ChooseTrollModiferHandler);
|
||||
Format(info, sizeof(info), "%s: Choose Modifier", troll.name);
|
||||
// sadly cannot use methodmap easily to return name
|
||||
Format(info, sizeof(info), "%s: Choose Modifier", Trolls[troll.Id].name);
|
||||
modiferMenu.SetTitle(info);
|
||||
|
||||
Format(info, sizeof(info), "%d|%d|1", userid, keyIndex);
|
||||
|
@ -209,13 +209,13 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
|
|||
|
||||
modiferMenu.ExitButton = true;
|
||||
modiferMenu.Display(param1, 0);
|
||||
} else if(!troll.IsActive(client) && troll.HasFlags()) {
|
||||
} else if(!troll.IsActive(victim) && troll.HasOptions) {
|
||||
ShowSelectFlagMenu(param1, userid, -1, troll);
|
||||
} else {
|
||||
TrollEffectResponse response = troll.Activate(client, param1);
|
||||
TrollEffectResponse response = troll.Activate(param1, victim);
|
||||
// Only show menu if success or error, not TE_Menu
|
||||
if(response != TE_Menu)
|
||||
ShowTrollsForCategory(param1, userid, troll.categoryID);
|
||||
ShowTrollsForCategory(param1, userid, troll.CategoryId);
|
||||
}
|
||||
|
||||
} else if (action == MenuAction_End)
|
||||
|
@ -263,29 +263,27 @@ public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, i
|
|||
static char str[3][8];
|
||||
ExplodeString(info, "|", str, 3, 8, false);
|
||||
int userid = StringToInt(str[0]);
|
||||
int client = GetClientOfUserId(userid);
|
||||
int victim = GetClientOfUserId(userid);
|
||||
int keyIndex = StringToInt(str[1]);
|
||||
int modifiers = StringToInt(str[2]);
|
||||
|
||||
if(client == 0) {
|
||||
if(victim == 0) {
|
||||
ReplyToCommand(param1, "FTT: Could not acquire player");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Troll troll;
|
||||
GetTrollByKeyIndex(keyIndex, troll);
|
||||
|
||||
if(!troll.IsActive(client) && troll.HasFlags()) {
|
||||
Troll troll = Troll(keyIndex);
|
||||
if(!troll.IsActive(victim) && troll.HasOptions) {
|
||||
// Show flag selection if troll is not enabled already
|
||||
ShowSelectFlagMenu(param1, userid, modifiers, troll);
|
||||
} else {
|
||||
TrollEffectResponse response;
|
||||
if(modifiers == 1 || modifiers == 3)
|
||||
response = troll.Activate(client, param1, TrollMod_Instant);
|
||||
response = troll.Activate(param1, victim, TrollMod_Instant);
|
||||
if(modifiers == 2 || modifiers == 3)
|
||||
response = troll.Activate(client, param1, TrollMod_Constant);
|
||||
response = troll.Activate(param1, victim, TrollMod_Constant);
|
||||
if(response != TE_Menu)
|
||||
ShowTrollsForCategory(param1, userid, troll.categoryID);
|
||||
ShowTrollsForCategory(param1, userid, troll.CategoryId);
|
||||
}
|
||||
|
||||
} else if (action == MenuAction_End)
|
||||
|
@ -300,20 +298,19 @@ public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int
|
|||
static char str[6][8];
|
||||
ExplodeString(info, "|", str, 6, 8, false);
|
||||
int userid = StringToInt(str[0]);
|
||||
int client = GetClientOfUserId(userid);
|
||||
int victim = GetClientOfUserId(userid);
|
||||
int keyIndex = StringToInt(str[1]);
|
||||
int modifiers = StringToInt(str[2]);
|
||||
int flags = StringToInt(str[3]);
|
||||
int index = StringToInt(str[4]);
|
||||
bool isDone = StringToInt(str[5]) == 1; // 0 = cont, 1 = done
|
||||
|
||||
if(client == 0) {
|
||||
if(victim == 0) {
|
||||
ReplyToCommand(param1, "FTT: Could not acquire player");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Troll troll;
|
||||
GetTrollByKeyIndex(keyIndex, troll);
|
||||
Troll troll = Troll(keyIndex);
|
||||
|
||||
// If told to go to next prompt, find the next VALID prompt
|
||||
// Valid prompt is one where the required flags for it, are active
|
||||
|
@ -321,7 +318,7 @@ public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int
|
|||
if(isDone || index == -1) {
|
||||
int nextIndex = GetNextPrompt(troll, flags, index);
|
||||
// If there is a prompt available, show it, else fall down
|
||||
if(nextIndex != -1) {
|
||||
if(nextIndex >= 0) {
|
||||
ShowSelectFlagMenu(param1, userid, modifiers, troll, flags, nextIndex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -335,15 +332,15 @@ public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int
|
|||
// Done with prompts, apply flags & modifiers
|
||||
if(modifiers > 0) {
|
||||
if(modifiers & view_as<int>(TrollMod_Instant))
|
||||
response = troll.Activate(client, param1, TrollMod_Instant, flags);
|
||||
response = troll.Activate(param1, victim, TrollMod_Instant, flags);
|
||||
if(modifiers & view_as<int>(TrollMod_Constant))
|
||||
response = troll.Activate(client, param1, TrollMod_Constant, flags);
|
||||
response = troll.Activate(param1, victim, TrollMod_Constant, flags);
|
||||
} else {
|
||||
response = troll.Activate(client, param1, TrollMod_Invalid, flags);
|
||||
response = troll.Activate(param1, victim, TrollMod_Invalid, flags);
|
||||
}
|
||||
// Jump back to selection screen
|
||||
if(response != TE_Menu)
|
||||
ShowTrollsForCategory(param1, userid, troll.categoryID);
|
||||
ShowTrollsForCategory(param1, userid, troll.CategoryId);
|
||||
} else if (action == MenuAction_End)
|
||||
delete menu;
|
||||
return 0;
|
||||
|
@ -426,23 +423,21 @@ void ShowTrollsForCategory(int client, int userid, int category) {
|
|||
Format(info, sizeof(info), "Category: %s", info);
|
||||
trollMenu.SetTitle(info);
|
||||
|
||||
static Troll troll;
|
||||
|
||||
int victim = GetClientOfUserId(userid);
|
||||
|
||||
// Add all menus that have same category ID to list
|
||||
static char name[MAX_TROLL_NAME_LENGTH+8];
|
||||
char name[MAX_TROLL_NAME_LENGTH+8];
|
||||
for(int i = 0; i < trollKV.Size; i++) {
|
||||
GetTrollByKeyIndex(i, troll);
|
||||
Troll troll = Troll(i);
|
||||
// If troll is hidden and using normal menu, do not show
|
||||
if(troll.hidden && !SilentMenuSelected[client]) continue;
|
||||
if(troll.categoryID == category) {
|
||||
if(troll.Hidden && !SilentMenuSelected[client]) continue;
|
||||
if(troll.CategoryId == category) {
|
||||
Format(info, sizeof(info), "%d|%d", userid, i);
|
||||
if(troll.IsActive(victim)) {
|
||||
Format(name, sizeof(name), "%s (Active)", troll.name);
|
||||
Format(name, sizeof(name), "%s (Active)", Trolls[i].name);
|
||||
trollMenu.AddItem(info, name);
|
||||
} else
|
||||
trollMenu.AddItem(info, troll.name);
|
||||
trollMenu.AddItem(info, Trolls[i].name);
|
||||
}
|
||||
}
|
||||
trollMenu.ExitButton = true;
|
||||
|
@ -452,51 +447,44 @@ void ShowTrollsForCategory(int client, int userid, int category) {
|
|||
|
||||
// Called with defaults on start, then recalled by ChooseTrollFlagHandler until prompt selection finished
|
||||
void ShowSelectFlagMenu(int activator, int victimUserID, int modifiers, Troll troll, int prevFlags = -1, int promptIndex = 0) {
|
||||
static char info[MAX_TROLL_NAME_LENGTH+16]; //victimUSERID|trollID|modifiers|flags||flagIndex
|
||||
static char name[32];
|
||||
char info[MAX_TROLL_NAME_LENGTH+16]; //victimUSERID|trollID|modifiers|flags||flagIndex
|
||||
char name[32];
|
||||
|
||||
Menu flagMenu = new Menu(ChooseTrollFlagHandler);
|
||||
|
||||
TrollFlagPrompt prompt;
|
||||
troll.GetFlagPrompt(promptIndex, prompt);
|
||||
troll.GetPrompt(promptIndex, prompt);
|
||||
prompt.GetPromptText(info, sizeof(info));
|
||||
flagMenu.SetTitle("%s", info);
|
||||
|
||||
Format(info, sizeof(info), "%s: %s", troll.name, info);
|
||||
flagMenu.SetTitle(info);
|
||||
if(prevFlags == -1) prevFlags = prompt.defaults;
|
||||
|
||||
Format(info, sizeof(info), "%d|%d|%d|%d|%d|1", victimUserID, troll.Id, modifiers, prevFlags, promptIndex);
|
||||
|
||||
if(prompt.multiselect) {
|
||||
if(prevFlags == -1) prevFlags = prompt.defaults;
|
||||
|
||||
Format(info, sizeof(info), "%d|%d|%d|%d|%d|1", victimUserID, troll.id, modifiers, prevFlags, promptIndex);
|
||||
Format(info, sizeof(info), "%d|%d|%d|%d|%d|1", victimUserID, troll.Id, modifiers, prevFlags, promptIndex);
|
||||
flagMenu.AddItem(info, "Apply / Next Prompt");
|
||||
|
||||
for(int i = 0; i < troll.flagNames.Length; i++) {
|
||||
int a = 1 << i;
|
||||
if(prompt.flags & a) {
|
||||
troll.flagNames.GetString(i, name, sizeof(name));
|
||||
// If flag is enabled, show indication (On)
|
||||
if(prevFlags > 0 && prevFlags & a)
|
||||
Format(name, sizeof(name), "%s ✓", name);
|
||||
int newFlags = prevFlags ^ a; //Toggle the flag instead of setting like below, as it's toggleable here
|
||||
Format(info, sizeof(info), "%d|%d|%d|%d|%d|0", victimUserID, troll.id, modifiers, newFlags, promptIndex);
|
||||
flagMenu.AddItem(info, name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Single choice only
|
||||
if(prevFlags == -1) prevFlags = 0;
|
||||
for(int i = 0; i < troll.flagNames.Length; i++) {
|
||||
int a = 1 << i;
|
||||
if(prompt.flags & a) {
|
||||
troll.flagNames.GetString(i, name, sizeof(name));
|
||||
// Add (default) indicator
|
||||
|
||||
if(prompt.defaults & a)
|
||||
}
|
||||
for(int i = 0; i < troll.TotalOptionsCount; i++) {
|
||||
int bit = 1 << i;
|
||||
// Does prompt have bit
|
||||
if(prompt.flags & bit) {
|
||||
troll.GetOptionName(i, name, sizeof(name));
|
||||
// If flag is enabled, show indication (On)
|
||||
int newFlags;
|
||||
if(prompt.multiselect) {
|
||||
if(prevFlags & bit)
|
||||
Format(name, sizeof(name), "%s ✓", name);
|
||||
newFlags = prevFlags ^ bit; //Toggle the flag instead of setting like below, as it's toggleable here
|
||||
} else {
|
||||
if(prompt.defaults & bit)
|
||||
Format(name, sizeof(name), "%s (default)", name);
|
||||
int newFlags = prevFlags | a; //Set flag with any from previous prompts
|
||||
Format(info, sizeof(info), "%d|%d|%d|%d|%d|1", victimUserID, troll.id, modifiers, newFlags, promptIndex);
|
||||
flagMenu.AddItem(info, name);
|
||||
newFlags = prevFlags | bit;
|
||||
}
|
||||
Format(info, sizeof(info), "%d|%d|%d|%d|%d|%b", victimUserID, troll.Id, modifiers, newFlags, promptIndex, !prompt.multiselect);
|
||||
flagMenu.AddItem(info, name);
|
||||
}
|
||||
}
|
||||
flagMenu.ExitButton = true;
|
||||
|
@ -535,11 +523,12 @@ void ShowThrowItAllMenu(int client, int userid) {
|
|||
}
|
||||
|
||||
int GetNextPrompt(Troll troll, int flags, int currentPrompt = 0) {
|
||||
static TrollFlagPrompt prompt;
|
||||
TrollFlagPrompt prompt;
|
||||
// Check if we at the end of all possible prompts:
|
||||
if(currentPrompt + 1 == troll.PromptCount) return -2;
|
||||
//If this prompt requires flags but they don't exist, skip to next that is valid or be done:
|
||||
if(currentPrompt + 1 == troll.flagPrompts.Length) return -1;
|
||||
for(int i = currentPrompt + 1; i < troll.flagPrompts.Length; i++) {
|
||||
troll.GetFlagPrompt(i, prompt);
|
||||
for(int i = currentPrompt + 1; i < troll.PromptCount; i++) {
|
||||
troll.GetPrompt(i, prompt);
|
||||
if(flags & prompt.requireFlags == prompt.requireFlags) {
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
void ActivateAutoPunish(int client) {
|
||||
if(hAutoPunish.IntValue & 2 == 2)
|
||||
ApplyTroll(client, "Special Magnet", 0, TrollMod_Constant);
|
||||
Troll.FromName("Special Magnet").Activate(0, client, TrollMod_Constant);
|
||||
if(hAutoPunish.IntValue & 1 == 1)
|
||||
ApplyTroll(client, "Tank Magnet", 0, TrollMod_Constant);
|
||||
Troll.FromName("Tank Magnet").Activate(0, client, TrollMod_Constant);
|
||||
if(hAutoPunish.IntValue & 8 == 8)
|
||||
ApplyTroll(client, "Vomit Player", 0, TrollMod_Instant);
|
||||
Troll.FromName("Vomit Player").Activate(0, client, TrollMod_Instant);
|
||||
else if(hAutoPunish.IntValue & 4 == 4)
|
||||
ApplyTroll(client, "Swarm", 0, TrollMod_Instant);
|
||||
Troll.FromName("Swarm").Activate(0, client, TrollMod_Instant);
|
||||
if(hAutoPunishExpire.IntValue > 0) {
|
||||
CreateTimer(60.0 * hAutoPunishExpire.FloatValue, Timer_ResetAutoPunish, GetClientOfUserId(client));
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ stock bool IsPlayerIncapped(int client) {
|
|||
#define MAX_TYPOS_LENGTH 16
|
||||
StringMap TYPOS_DICT;
|
||||
void LoadTypos() {
|
||||
TYPOS_DICT.Clear();
|
||||
TYPOS_DICT = new StringMap();
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sPath, sizeof(sPath), "data/ftt_typos.txt");
|
||||
|
||||
|
@ -100,10 +100,72 @@ void LoadTypos() {
|
|||
char buffer[140], key[32];
|
||||
while(file.ReadLine(buffer, sizeof(buffer))) {
|
||||
int index = SplitString(buffer, " ", key, sizeof(key));
|
||||
TYPOS_DICT.SetString(key, buffer[index]);
|
||||
AddTypo(key, buffer[index]);
|
||||
}
|
||||
|
||||
file.Close();
|
||||
delete file;
|
||||
}
|
||||
|
||||
ArrayList SplitStringList(const char[] message, char separator, int wordSize = 64) {
|
||||
ArrayList words = new ArrayList(ByteCountToCells(wordSize));
|
||||
char[] word = new char[wordSize];
|
||||
int len = strlen(message);
|
||||
int prevIndex;
|
||||
for(int i = 0; i < len; i++) {
|
||||
if(message[i] == separator) {
|
||||
// Only copy the length of the string. The len includes space, which is used as null term
|
||||
int wordLen = (i - prevIndex);
|
||||
if(wordSize < wordLen) wordLen = wordSize;
|
||||
strcopy(word, wordLen, message[prevIndex]);
|
||||
words.PushString(word);
|
||||
prevIndex = i;
|
||||
}
|
||||
}
|
||||
// End of string, copy the remainder
|
||||
strcopy(word, len, message[prevIndex]);
|
||||
words.PushString(word);
|
||||
return words;
|
||||
}
|
||||
void ReplaceWithTypos(const char[] message, char[] output, int maxlen) {
|
||||
ArrayList words = SplitStringList(message, ' ');
|
||||
message[0] = '\0';
|
||||
char word[64];
|
||||
ArrayList replaceList;
|
||||
for(int i = 0; i < words.Length; i++) {
|
||||
words.GetString(i, word, sizeof(word));
|
||||
if(TYPOS_DICT.GetValue(word, replaceList)) {
|
||||
int index = GetRandomInt(0, replaceList.Length - 1);
|
||||
replaceList.GetString(index, word, sizeof(word));
|
||||
if(i == 0)
|
||||
Format(output, maxlen, "%s", word);
|
||||
else
|
||||
Format(output, maxlen, "%s %s", message, word);
|
||||
}
|
||||
}
|
||||
delete words;
|
||||
}
|
||||
|
||||
void AddTypo(const char[] src, const char[] typo, bool save = false) {
|
||||
ArrayList list;
|
||||
TYPOS_DICT.GetValue(src, list);
|
||||
if(list == null) {
|
||||
list = new ArrayList(ByteCountToCells(MAX_TYPOS_LENGTH));
|
||||
}
|
||||
list.PushString(typo);
|
||||
TYPOS_DICT.SetValue(src, list);
|
||||
if(save) {
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sPath, sizeof(sPath), "data/ftt_typos.txt");
|
||||
File file = OpenFile(sPath, "a", false, NULL_STRING);
|
||||
if(file == null) {
|
||||
PrintToServer("[FTT] Cannot open for saving: data/ftt_typos.txt");
|
||||
return;
|
||||
}
|
||||
file.Seek(SEEK_END, 0);
|
||||
file.WriteLine("%s %s", src, typo);
|
||||
file.Flush();
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_PHRASES_PER_WORD 8
|
||||
|
@ -578,3 +640,24 @@ void SetSlot(int client, int slot) {
|
|||
Format(slotStr, sizeof(slotStr), "slot%d", slot);
|
||||
ClientCommand(client, slotStr);
|
||||
}
|
||||
|
||||
void RewindPlayer(int client) {
|
||||
float curFlow = L4D2Direct_GetFlowDistance(client);
|
||||
ArrayList navs = new ArrayList();
|
||||
L4D_GetAllNavAreas(navs);
|
||||
navs.Sort(Sort_Random, Sort_Integer);
|
||||
float minFlow = curFlow - 300.0;
|
||||
float maxFlow = curFlow - 150.0;
|
||||
// This finds the first nav area in range, usually closer
|
||||
for(int i = 0; i < navs.Length; i++) {
|
||||
float flow = L4D2Direct_GetTerrorNavAreaFlow(navs.Get(i));
|
||||
if(flow >= minFlow && flow <= maxFlow) {
|
||||
float pos[3];
|
||||
L4D_FindRandomSpot(navs.Get(i), pos);
|
||||
TeleportEntity(client, pos, NULL_VECTOR, NULL_VECTOR);
|
||||
L4D_WarpToValidPositionIfStuck(client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete navs;
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
|
||||
Action Timer_ThrowTimer(Handle timer, int client) {
|
||||
if(!IsClientInGame(client)) {
|
||||
Trolls[t_throwItAllIndex].timerHandles[client] = null;
|
||||
return Plugin_Stop;
|
||||
}
|
||||
ThrowAllItems(client);
|
||||
if(IsClientInGame(client))
|
||||
ThrowAllItems(client);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
int instantCommonRef[MAXPLAYERS+1];
|
||||
|
@ -482,3 +479,10 @@ Action Timer_RestoreHud(Handle h, int userid) {
|
|||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
Action Timer_RandomRewind(Handle h, int client) {
|
||||
if(IsClientInGame(client) && GetURandomFloat() > 0.3) {
|
||||
RewindPlayer(client);
|
||||
}
|
||||
return Plugin_Handled;
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// UP THE VALUE 'MAX_TROLLS' in base.inc before adding new ones!
|
||||
|
||||
int t_slipperyShoesIndex = 0;
|
||||
int t_stickyGooIndex = 0;
|
||||
Troll t_stickyGoo;
|
||||
int t_invertedTrollIndex;
|
||||
int t_randomizeAnglesIndex;
|
||||
int t_randomizeVelocityIndex;
|
||||
|
@ -10,272 +10,270 @@ int t_shakeyCameraIndex;
|
|||
int t_slotRouletteIndex;
|
||||
int t_damageBoostIndex;
|
||||
int t_reverseFFIndex;
|
||||
int t_throwItAllIndex;
|
||||
int t_hideHUDIndex;
|
||||
Troll t_throwItAll;
|
||||
Troll t_voiceMute;
|
||||
Troll t_gunJam;
|
||||
|
||||
void SetupTrolls() {
|
||||
trollKV = new StringMap();
|
||||
categories = new ArrayList(ByteCountToCells(16));
|
||||
gRandomClients = new ArrayList();
|
||||
int index;
|
||||
SetupTroll("Reset User", "Resets the user, removes all troll effects", TrollMod_Instant);
|
||||
TrollBuilder("Reset User", "Resets the user, removes all troll effects", TrollMod_Instant);
|
||||
|
||||
/// CATEGORY: Magnets
|
||||
TrollBuilder troll;
|
||||
SetCategory("Magnets");
|
||||
index = SetupTroll("Special Magnet", "Attracts ALL specials to any alive target with this troll enabled", TrollMod_Constant);
|
||||
AddMagnetFlags(index);
|
||||
index = SetupTroll("Tank Magnet", "Attracts ALL tanks to any alive target with this troll enabled", TrollMod_Constant);
|
||||
AddMagnetFlags(index);
|
||||
troll = TrollBuilder("Special Magnet", "Attracts ALL specials to any alive target with this troll enabled", TrollMod_Constant);
|
||||
AddMagnetFlags(troll);
|
||||
troll = TrollBuilder("Tank Magnet", "Attracts ALL tanks to any alive target with this troll enabled", TrollMod_Constant);
|
||||
AddMagnetFlags(troll);
|
||||
#if defined _actions_included
|
||||
index = SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant);
|
||||
TrollBuilder("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant);
|
||||
#endif
|
||||
index = SetupTroll("Projectile Magnet", "Makes all projectiles (biles, molotovs, pipes, tank rocks) go to player", TrollMod_Constant);
|
||||
Trolls[index].AddCustomFlagPrompt("Target Sources", true);
|
||||
// Tied to: ProjectileMagnetType
|
||||
Trolls[index].AddFlag("Infected (rocks/goo)", true);
|
||||
Trolls[index].AddFlag("Teammates (grenades)", false);
|
||||
Trolls[index].AddFlag("Thrown Tank Objects", false);
|
||||
TrollBuilder("Projectile Magnet", "Makes all projectiles (biles, molotovs, pipes, tank rocks) go to player", TrollMod_Constant)
|
||||
.AddPromptMulti("Target Sources")
|
||||
// Tied to: ProjectileMagnetType
|
||||
.AddOption("Infected (rocks/goo)", true)
|
||||
.AddOption("Teammates (grenades)")
|
||||
.AddOption("Thrown Tank Objects");
|
||||
|
||||
/// CATEGORY: Infected
|
||||
SetCategory("Infected");
|
||||
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
|
||||
t_vomitPlayerIndex = SetupTroll("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant | TrollMod_Constant);
|
||||
index = SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Around them (Director)", true);
|
||||
Trolls[index].AddFlag("On top / in-face", false);
|
||||
SetupTroll("Goo", "Spawns a spitter puddle underneath them", TrollMod_Instant);
|
||||
index = SetupTroll("Sticky Goo", "Slows player down in goo", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("90% Movement Speed", true);
|
||||
Trolls[index].AddFlag("80% Movement Speed", false);
|
||||
Trolls[index].AddFlag("70% Movement Speed", false);
|
||||
Trolls[index].AddFlag("50% Movement Speed", false);
|
||||
Trolls[index].AddFlag("30% Movement Speed", false);
|
||||
Trolls[index].AddFlag("0% Movement Speed", false);
|
||||
t_stickyGooIndex = index;
|
||||
index = SetupTroll("Vocalize Specials", "Spawn commons on special vocals", TrollMod_Constant)
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Mute Vocalization", true);
|
||||
Trolls[index].AddFlag("Do not mute", false);
|
||||
index = SetupTroll("Instant Commons", "Spawns commons behind or infront", TrollMod_Instant | TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("In Back", true);
|
||||
Trolls[index].AddFlag("In Front", false);
|
||||
index = SetupTroll("Smart Charge", "Waits until coast is clear to charge", TrollMod_Constant);
|
||||
Trolls[index].AddCustomFlagPrompt("Attempt Timeout", false);
|
||||
Trolls[index].AddFlag("15 Seconds", true);
|
||||
Trolls[index].AddFlag("30 Seconds", false);
|
||||
Trolls[index].AddFlag("1 minute", false);
|
||||
Trolls[index].AddFlag("5 minutes", false);
|
||||
TrollBuilder("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
|
||||
t_vomitPlayerIndex = TrollBuilder("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant | TrollMod_Constant).Id;
|
||||
TrollBuilder("Insta Special", "Shortcut to sm_insta", TrollMod_Instant)
|
||||
.AddPrompt()
|
||||
.AddOption("Around them (Director)", true)
|
||||
.AddOption("On top / in-face");
|
||||
TrollBuilder("Goo", "Spawns a spitter puddle underneath them", TrollMod_Instant);
|
||||
t_stickyGoo = TrollBuilder("Sticky Goo", "Slows player down in goo", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOptionFloat("90% Movement Speed", true, 0.9)
|
||||
.AddOptionFloat("80% Movement Speed", false, 0.8)
|
||||
.AddOptionFloat("70% Movement Speed", false, 0.7)
|
||||
.AddOptionFloat("50% Movement Speed", false, 0.5)
|
||||
.AddOptionFloat("30% Movement Speed", false, 0.3)
|
||||
.AddOptionFloat("0% Movement Speed", false, 0.0)
|
||||
.Build();
|
||||
TrollBuilder("Vocalize Specials", "Spawn commons on special vocals", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("Mute Vocalization", true)
|
||||
.AddOption("Do not mute", false)
|
||||
TrollBuilder("Instant Commons", "Spawns commons behind or infront", TrollMod_Instant | TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("In Back", true)
|
||||
.AddOption("In Front", false);
|
||||
TrollBuilder("Smart Charge", "Waits until coast is clear to charge", TrollMod_Constant)
|
||||
.AddPrompt("Attempt Timeout")
|
||||
.OnPromptActivate(Activate_SmartCharge)
|
||||
.AddOptionInt("15 Seconds", true, 15)
|
||||
.AddOptionInt("30 Seconds", false, 30)
|
||||
.AddOptionInt("1 minute", false, 60)
|
||||
.AddOptionInt("5 minutes", false, 300);
|
||||
|
||||
// CATEGORY: Projectiles
|
||||
SetCategory("Projectiles");
|
||||
index = SetupTroll("Rock Dropper", "Drops on a rock. On their head.", TrollMod_Instant);
|
||||
// Trolls[index].AddFlagPrompt(false);
|
||||
// Trolls[index].AddFlag("Drop From Above", true);
|
||||
// Trolls[index].AddFlag("From behind", false);
|
||||
index = SetupTroll("Car Splat", "Car. splats.", TrollMod_Instant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("On Top", true);
|
||||
Trolls[index].AddFlag("Into (Infront)", false);
|
||||
Trolls[index].AddFlag("Into (Behind)", false);
|
||||
index = SetupTroll("Bad Throw", "Player drops throwables on throw, and biles/molotovs themselves", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(true);
|
||||
Trolls[index].AddFlag("Biles", true);
|
||||
Trolls[index].AddFlag("Molotovs", true);
|
||||
Trolls[index].AddFlag("Pipebombs", true);
|
||||
index = SetupTroll("Molotov Bath", "Throws a molotov on their feet", TrollMod_Instant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Normal", true);
|
||||
Trolls[index].AddFlag("Set the town ablaze", false);
|
||||
TrollBuilder("Rock Dropper", "Drops on a rock. On their head.", TrollMod_Instant);
|
||||
TrollBuilder("Car Splat", "Car. splats.", TrollMod_Instant)
|
||||
.AddPrompt()
|
||||
.AddOption("On Top", true)
|
||||
.AddOption("Into (Infront)", false)
|
||||
.AddOption("Into (Behind)", false);
|
||||
TrollBuilder("Bad Throw", "Player drops throwables on throw, and biles/molotovs themselves", TrollMod_Constant)
|
||||
.AddPromptMulti()
|
||||
.AddOption("Biles", true)
|
||||
.AddOption("Molotovs", true)
|
||||
.AddOption("Pipebombs", true)
|
||||
TrollBuilder("Molotov Bath", "Throws a molotov on their feet", TrollMod_Instant)
|
||||
.AddPrompt()
|
||||
.AddOption("Normal", true)
|
||||
.AddOption("Set the town ablaze", false);
|
||||
|
||||
// CATEGORY: Items
|
||||
SetCategory("Items");
|
||||
index = SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
|
||||
Trolls[index].SetTimer(THROWITALL_INTERVAL, Timer_ThrowTimer);
|
||||
index = SetupTroll("Spicy Gas", "Gascans player picks up just ignite. Magic.", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Always (100%)", false);
|
||||
Trolls[index].AddFlag("Half Time (50%)", true);
|
||||
Trolls[index].AddFlag("Rare (10%)", false);
|
||||
index = SetupTroll("No Pickup", "Prevents a player from picking up ANY (new) item. Use ThrowItAll to make them drop", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(true);
|
||||
Trolls[index].AddFlag("No Primary", false);
|
||||
Trolls[index].AddFlag("No Melee", false);
|
||||
Trolls[index].AddFlag("No Throwables", true);
|
||||
Trolls[index].AddFlag("No Kits", true);
|
||||
Trolls[index].AddFlag("No Pills / Adr", true);
|
||||
Trolls[index].AddFlag("No GASCANS", true);
|
||||
index = SetupTroll("UziRules / AwpSmells", "Picking up a weapon gives them a UZI or AWP instead", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("UZI Only", true);
|
||||
Trolls[index].AddFlag("AWP Only", false);
|
||||
SetupTroll("Primary Disable", "Player cannot pickup any weapons, only melee/pistols", TrollMod_Constant);
|
||||
index = SetupTroll("Dull Melee", "Player's melee weapon does 0 damage (based on %). Headshots still work", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Always (100%)", false);
|
||||
Trolls[index].AddFlag("Half Time (50%)", true);
|
||||
Trolls[index].AddFlag("Rare (10%)", false);
|
||||
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("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.2, Timer_SlotRoulette, 8);
|
||||
t_slotRouletteIndex = index;
|
||||
t_throwItAll = TrollBuilder("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant)
|
||||
.SetTimer(THROWITALL_INTERVAL, Timer_ThrowTimer)
|
||||
.Build();
|
||||
TrollBuilder("Spicy Gas", "Gascans player picks up just ignite. Magic.", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("Always (100%)", false)
|
||||
.AddOption("Half Time (50%)", true)
|
||||
.AddOption("Rare (10%)", false);
|
||||
TrollBuilder("No Pickup", "Prevents a player from picking up ANY (new) item. Use ThrowItAll to make them drop", TrollMod_Constant)
|
||||
.AddPromptMulti()
|
||||
.AddOption("No Primary", false)
|
||||
.AddOption("No Melee", false)
|
||||
.AddOption("No Throwables", true)
|
||||
.AddOption("No Kits", true)
|
||||
.AddOption("No Pills / Adr", true)
|
||||
.AddOption("No GASCANS", true);
|
||||
TrollBuilder("UziRules / AwpSmells", "Picking up a weapon gives them a UZI or AWP instead", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("UZI Only", true)
|
||||
.AddOption("AWP Only", false)
|
||||
TrollBuilder("Primary Disable", "Player cannot pickup any weapons, only melee/pistols", TrollMod_Constant);
|
||||
TrollBuilder("Dull Melee", "Player's melee weapon does 0 damage (based on %). Headshots still work", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("Always (100%)", false)
|
||||
.AddOption("Half Time (50%)", true)
|
||||
.AddOption("Rare (10%)", false);
|
||||
TrollBuilder("Nerf Gun", "When they shoot it does no damage.", TrollMod_Constant);
|
||||
TrollBuilder("Randomize Clip Ammo", "Randomly changes their clip ammo downwards", TrollMod_Constant | TrollMod_Instant);
|
||||
TrollBuilder("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
|
||||
|
||||
t_slotRouletteIndex = TrollBuilder("Slot Roulette", "Randomize their slots", TrollMod_Constant)
|
||||
.SetTimer(0.2, Timer_SlotRoulette, 8)
|
||||
.AddPromptMulti("Activiations")
|
||||
.AddOption("On Vomitted") // 1 << 0
|
||||
.AddOption("On Damage") // 1 << 1
|
||||
.AddOption("On Vocalize") // 1 << 2
|
||||
.AddOption("Periodically") // 1 << 3
|
||||
.AddPrompt("Frequency", 1 << 3)
|
||||
.AddOption("Subtle") // 1 << 4
|
||||
.AddOption("Confusing") // 1 << 5
|
||||
.AddOption("Annoying") // 1 << 6
|
||||
.AddOption("Unusuable") // 1 << 7
|
||||
.Id;
|
||||
|
||||
/// CATEGORY: Chat
|
||||
SetCategory("Chat");
|
||||
SetupTroll("Typoos", "", TrollMod_Constant);
|
||||
SetupTroll("iCantSpellNoMore", "Chat messages letter will randomly changed with wrong letters", TrollMod_Constant);
|
||||
index = SetupTroll("No Profanity", "Replaces some words with random phrases", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Only Replace Swears", false);
|
||||
Trolls[index].AddFlag("Replace Full Messages", true);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Show Modified to Them", true);
|
||||
Trolls[index].AddFlag("Show Original to Them", false);
|
||||
index = SetupTroll("Vocalize Gag", "Prevents player from sending any vocalizations (even automatic)", TrollMod_Constant);
|
||||
// Trolls[index].AddFlagPrompt(false);
|
||||
// Trolls[index].AddFlag("Mute for All", true);
|
||||
// Trolls[index].AddFlag("Mute For All But Them", false);
|
||||
index = SetupTroll("Honk / Meow / Woof", "Custom sounds", TrollMod_Constant);
|
||||
Trolls[index].AddCustomFlagPrompt("Choose Sound:");
|
||||
Trolls[index].AddFlag("Honk", true);
|
||||
Trolls[index].AddFlag("Meow", false);
|
||||
Trolls[index].AddFlag("Woof", false);
|
||||
Trolls[index].AddCustomFlagPrompt("Choose Chat modifier:", false, 1);
|
||||
Trolls[index].AddFlag("Show Modified to Them", true);
|
||||
Trolls[index].AddFlag("Show Original to Them", false);
|
||||
Trolls[index].AddFlag("Show Modified Only To Them", false);
|
||||
SetupTroll("Reversed", "Reserves their message", TrollMod_Constant);
|
||||
SetupTroll("Voice Mute", "Mutes from voice", TrollMod_Constant);
|
||||
SetupTroll("No Rushing Us", "Decreases player speed everytime they yell hurry up", TrollMod_Constant);
|
||||
TrollBuilder("Typoos", "", TrollMod_Constant);
|
||||
TrollBuilder("iCantSpellNoMore", "Chat messages letter will randomly changed with wrong letters", TrollMod_Constant);
|
||||
TrollBuilder("No Profanity", "Replaces some words with random phrases", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("Only Replace Swears")
|
||||
.AddOption("Replace Full Messages", true)
|
||||
.AddPrompt()
|
||||
.AddOption("Show Modified to Them", true)
|
||||
.AddOption("Show Original to Them");
|
||||
TrollBuilder("Vocalize Gag", "Prevents player from sending any vocalizations (even automatic)", TrollMod_Constant);
|
||||
// .AddPrompt()
|
||||
// .AddOption("Mute for All", true);
|
||||
// .AddOption("Mute For All But Them", false);
|
||||
TrollBuilder("Honk / Meow / Woof", "Custom sounds", TrollMod_Constant)
|
||||
.AddPrompt("Choose Sound:")
|
||||
.AddOption("Honk", true)
|
||||
.AddOption("Meow", false)
|
||||
.AddOption("Woof", false)
|
||||
.AddPrompt("Choose Chat modifier:", 1)
|
||||
.AddOption("Show Modified to Them", true)
|
||||
.AddOption("Show Original to Them", false)
|
||||
.AddOption("Show Modified Only To Them", false);
|
||||
TrollBuilder("Reversed", "Reserves their message", TrollMod_Constant);
|
||||
t_voiceMute = TrollBuilder("Voice Mute", "Mutes from voice", TrollMod_Constant).Build();
|
||||
TrollBuilder("No Rushing Us", "Decreases player speed everytime they yell hurry up", TrollMod_Constant);
|
||||
|
||||
/// CATEGORY: Health
|
||||
SetCategory("Health");
|
||||
t_damageBoostIndex = 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);
|
||||
index = SetupTroll("Reverse FF", "All damage dealt to a player is reversed", TrollMod_Constant);
|
||||
Trolls[index].AddCustomFlagPrompt("Choose Reverse FF", false);
|
||||
Trolls[index].AddFlag("1:1 Ratio", true); //1
|
||||
Trolls[index].AddFlag("2x Ratio", false); //2
|
||||
Trolls[index].AddFlag("0.5x Ratio", false); //4
|
||||
Trolls[index].AddFlag("0.0x Ratio (None)", false); //8
|
||||
Trolls[index].AddFlag("3x Ratio", false); //16
|
||||
Trolls[index].AddCustomFlagPrompt("Modes", true);
|
||||
Trolls[index].AddFlag("Reverse Fire Damage", false); //32
|
||||
Trolls[index].AddFlag("Reverse Explosions", false); //64
|
||||
t_reverseFFIndex = index;
|
||||
t_damageBoostIndex = TrollBuilder("Damage Boost", "Makes a player take more damage than normal", TrollMod_Constant).Id;
|
||||
TrollBuilder("Temp Health Quick Drain", "Makes a player's temporarily health drain very quickly", TrollMod_Constant);
|
||||
TrollBuilder("Slow Drain", "Will make the player slowly lose health over time", TrollMod_Constant);
|
||||
TrollBuilder("KillMeSoftly", "Make player eat or waste pills whenever possible", TrollMod_Instant | TrollMod_Constant);
|
||||
t_reverseFFIndex = TrollBuilder("Reverse FF", "All damage dealt to a player is reversed", TrollMod_Constant)
|
||||
.AddPrompt("Choose Reverse FF", false)
|
||||
.AddOption("1:1 Ratio", true) //1
|
||||
.AddOption("2x Ratio", false) //2
|
||||
.AddOption("0.5x Ratio", false) //4
|
||||
.AddOption("0.0x Ratio (None)", false) //8
|
||||
.AddOption("3x Ratio", false) //16
|
||||
.AddPromptMulti("Modes")
|
||||
.AddOption("Reverse Fire Damage", false) //32
|
||||
.AddOption("Reverse Explosions", false) //64
|
||||
.Id;
|
||||
|
||||
|
||||
index = SetupTroll("Dep Bots", "Makes bots heal a player. At any cost", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Do not spawn extra", true); // 1
|
||||
Trolls[index].AddFlag("Spawn extra bots (broke)", false); // 2
|
||||
Trolls[index].AddCustomFlagPrompt("# Of Bots", false);
|
||||
Trolls[index].AddFlag("1", false); // 4
|
||||
Trolls[index].AddFlag("2", false); // 8
|
||||
Trolls[index].AddFlag("3", false); // 16
|
||||
Trolls[index].AddFlag("4", true); // 32
|
||||
Trolls[index].AddFlag("5", false); // 64
|
||||
Trolls[index].AddCustomFlagPrompt("Auto Timeout", false, 0);
|
||||
Trolls[index].AddFlag("Until Healed / Map Change", false); // 128
|
||||
Trolls[index].AddFlag("15 seconds", true); // 255
|
||||
Trolls[index].AddFlag("30 seconds", false); // 512
|
||||
Trolls[index].AddFlag("1 minute", false); //1024
|
||||
Trolls[index].AddFlag("5 minutes", false); //2048
|
||||
TrollBuilder("Dep Bots", "Makes bots heal a player. At any cost", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("Do not spawn extra", true) // 1
|
||||
.AddOption("Spawn extra bots (broke)", false) // 2
|
||||
.AddPrompt("# Of Bots")
|
||||
.AddOption("1", false) // 4
|
||||
.AddOption("2", false) // 8
|
||||
.AddOption("3", false) // 16
|
||||
.AddOption("4", true) // 32
|
||||
.AddOption("5", false) // 64
|
||||
.AddPrompt("Auto Timeout")
|
||||
.AddOption("Until Healed / Map Change", false) // 128
|
||||
.AddOption("15 seconds", true) // 255
|
||||
.AddOption("30 seconds", false) // 512
|
||||
.AddOption("1 minute", false) //1024
|
||||
.AddOption("5 minutes", false); //2048
|
||||
|
||||
/// CATEGORY: Movement
|
||||
SetCategory("Movement");
|
||||
index = SetupTroll("Slow Speed", "Sets player speed to 0.8x of normal speed", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("90% Movement Speed", true);
|
||||
Trolls[index].AddFlag("80% Movement Speed", false);
|
||||
Trolls[index].AddFlag("70% Movement Speed", false);
|
||||
Trolls[index].AddFlag("50% Movement Speed", false);
|
||||
Trolls[index].AddFlag("30% Movement Speed", false);
|
||||
Trolls[index].AddFlag("0% Movement Speed", false);
|
||||
SetupTroll("Higher Gravity", "Sets player gravity to 1.3x of normal gravity", TrollMod_Constant);
|
||||
t_invertedTrollIndex = SetupTroll("Inverted Controls", "Well, aint it obvious", TrollMod_Constant);
|
||||
SetupTroll("Stagger", "Like a slap, but different", TrollMod_Instant);
|
||||
index = SetupTroll("Slippery Shoes", "Periodically stumbles around.", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(true);
|
||||
Trolls[index].AddFlag("Periodically", true);
|
||||
Trolls[index].AddFlag("When using doors", false);
|
||||
Trolls[index].AddFlag("On throwable use", false);
|
||||
Trolls[index].AddFlag("On pills/adrenaline use", false);
|
||||
Trolls[index].AddFlag("On zombie bite", false);
|
||||
t_slipperyShoesIndex = index;
|
||||
index = SetupTroll("Randomize Angles", "Randomly change their angles", TrollMod_Constant);
|
||||
Trolls[index].AddCustomFlagPrompt("Frequency:", false);
|
||||
Trolls[index].AddFlag("Once in a while", true); //1
|
||||
Trolls[index].AddFlag("Periodically", false); //2
|
||||
Trolls[index].AddFlag("A lot", false); //4
|
||||
Trolls[index].AddFlag("Painful", false); //8
|
||||
Trolls[index].AddFlag("Seizure", false); //16
|
||||
t_randomizeAnglesIndex = index;
|
||||
index = SetupTroll("Randomize Velocity", "Randomly change their velocity", TrollMod_Constant);
|
||||
Trolls[index].SetTimer(0.1, Timer_RandomVelocity);
|
||||
Trolls[index].AddCustomFlagPrompt("Frequency:", false);
|
||||
Trolls[index].AddFlag("Loose", true); //1
|
||||
Trolls[index].AddFlag("Slippery", false); //2
|
||||
Trolls[index].AddFlag("Earthquake", false); //4
|
||||
Trolls[index].AddFlag("Severe Earthquake", false); //8
|
||||
Trolls[index].AddFlag("Bouncy Castle", false); //16
|
||||
t_randomizeVelocityIndex = index;
|
||||
TrollBuilder("Slow Speed", "Sets player speed to 0.8x of normal speed", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOptionFloat("90% Movement Speed", true, 0.9)
|
||||
.AddOptionFloat("80% Movement Speed", false, 0.8)
|
||||
.AddOptionFloat("70% Movement Speed", false, 0.7)
|
||||
.AddOptionFloat("50% Movement Speed", false, 0.5)
|
||||
.AddOptionFloat("30% Movement Speed", false, 0.3)
|
||||
.AddOptionFloat("0% Movement Speed", false, 0.0);
|
||||
TrollBuilder("Higher Gravity", "Sets player gravity to 1.3x of normal gravity", TrollMod_Constant);
|
||||
t_invertedTrollIndex = TrollBuilder("Inverted Controls", "Well, aint it obvious", TrollMod_Constant).Id;
|
||||
t_slipperyShoesIndex = TrollBuilder("Slippery Shoes", "Periodically stumbles around.", TrollMod_Constant | TrollMod_Instant)
|
||||
.AddPromptMulti()
|
||||
.AddOption("Periodically", true) // 1 << 0
|
||||
.AddOption("When using doors") // 1 << 1
|
||||
.AddOption("On throwable use")
|
||||
.AddOption("On pills/adrenaline use")
|
||||
.AddOption("On zombie bite")
|
||||
.Id
|
||||
t_randomizeAnglesIndex = TrollBuilder("Randomize Angles", "Randomly change their angles", TrollMod_Constant)
|
||||
.AddPrompt("Frequency:")
|
||||
.AddOption("Once in a while", true) //1
|
||||
.AddOption("Periodically", false) //2
|
||||
.AddOption("A lot", false) //4
|
||||
.AddOption("Painful", false) //8
|
||||
.AddOption("Seizure", false) //16
|
||||
.Id;
|
||||
t_randomizeVelocityIndex = TrollBuilder("Randomize Velocity", "Randomly change their velocity", TrollMod_Constant)
|
||||
.SetTimer(0.1, Timer_RandomVelocity)
|
||||
.AddPrompt("Frequency:")
|
||||
.AddOption("Loose", true) //1
|
||||
.AddOption("Slippery", false) //2
|
||||
.AddOption("Earthquake", false) //4
|
||||
.AddOption("Severe Earthquake", false) //8
|
||||
.AddOption("Bouncy Castle", false) //16
|
||||
.Id;
|
||||
TrollBuilder("Rewind", "Teleports player backwards", TrollMod_Instant | TrollMod_Constant)
|
||||
.SetTimer(10.0, Timer_RandomRewind);
|
||||
|
||||
/// CATEGORY: MISC
|
||||
SetCategory("Misc");
|
||||
SetupTroll("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant);
|
||||
SetupTroll("No Shove", "Prevents a player from shoving", TrollMod_Constant);
|
||||
index = SetupTroll("No Button Touchie", "Stops people from pressing buttons", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(true);
|
||||
Trolls[index].AddFlag("Prevent Use", true);
|
||||
Trolls[index].AddFlag("Vomit On Touch", false);
|
||||
Trolls[index].AddFlag("Incap On Touch", false);
|
||||
Trolls[index].AddFlag("Slay On Touch", false);
|
||||
Trolls[index].AddFlag("0.8x Speed", false);
|
||||
t_gunJam = TrollBuilder("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant).Build();
|
||||
TrollBuilder("No Shove", "Prevents a player from shoving", TrollMod_Constant);
|
||||
TrollBuilder("No Button Touchie", "Stops people from pressing buttons", TrollMod_Constant)
|
||||
.AddPromptMulti()
|
||||
.AddOption("Prevent Use", true)
|
||||
.AddOption("Vomit On Touch", false)
|
||||
.AddOption("Incap On Touch", false)
|
||||
.AddOption("Slay On Touch", false)
|
||||
.AddOption("0.8x Speed", false);
|
||||
// TODO: setup instant
|
||||
index = SetupTroll("Shakey Camera", "Horrible", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
t_shakeyCameraIndex = TrollBuilder("Shakey Camera", "Horrible", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
// 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("Hide HUD", "Horrible", TrollMod_Constant);
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("Rare & Short", false);
|
||||
Trolls[index].AddFlag("Sometimes & Medium", false);
|
||||
Trolls[index].AddFlag("Constantly", true);
|
||||
t_hideHUDIndex = index;
|
||||
index = SetupTroll("Meta: Random", "Picks a random troll", TrollMod_Instant);
|
||||
index = SetupTroll("Meta: Inverse", "Uhm you are not supposed to see this...", TrollMod_Instant);
|
||||
Trolls[index].hidden = true;
|
||||
Trolls[index].AddFlagPrompt(false);
|
||||
Trolls[index].AddFlag("100%", true);
|
||||
Trolls[index].AddFlag("50%", false);
|
||||
Trolls[index].AddFlag("10%", false);
|
||||
|
||||
|
||||
|
||||
|
||||
.AddOption("Annoying but playable", false)
|
||||
.AddOption("Bad", true)
|
||||
.AddOption("Sickness", false)
|
||||
.AddOption("Violent", false)
|
||||
.AddOption("Violent XX", false)
|
||||
.Id;
|
||||
t_hideHUDIndex = TrollBuilder("Hide HUD", "Horrible", TrollMod_Constant)
|
||||
.AddPrompt()
|
||||
.AddOption("Rare & Short", false)
|
||||
.AddOption("Sometimes & Medium", false)
|
||||
.AddOption("Constantly", true)
|
||||
.Id;
|
||||
TrollBuilder("Meta: Random", "Picks a random troll", TrollMod_Instant);
|
||||
t_metaReverse = TrollBuilder("Meta: Inverse", "Uhm you are not supposed to see this...", TrollMod_Instant)
|
||||
.Hide()
|
||||
.AddPrompt()
|
||||
.AddOptionFloat("100%", true, 1.0)
|
||||
.AddOptionFloat("50%", false, 0.5)
|
||||
.AddOptionFloat("10%", false, 0.1)
|
||||
.Build();
|
||||
|
||||
// Initialize the default flag values to -1
|
||||
for(int i = 0; i <= MAX_TROLLS; i++) {
|
||||
|
@ -287,16 +285,31 @@ void SetupTrolls() {
|
|||
|
||||
}
|
||||
|
||||
void AddMagnetFlags(int index) {
|
||||
Trolls[index].AddCustomFlagPrompt("Choose Magnet Chance:", false);
|
||||
Trolls[index].AddFlag("Always (100%)", true);
|
||||
Trolls[index].AddFlag("Half Time (50%)", false);
|
||||
Trolls[index].AddFlag("Rare (10%)", false);
|
||||
TrollEffectResponse Activate_SmartCharge(Troll troll, int activator, int victim, int timeout, int flags, trollModifier mod) {
|
||||
if(pdata[victim].smartChargeActivator > 0) {
|
||||
ReplyToCommand(activator, "Target already has smart charge enabled");
|
||||
return TE_Error;
|
||||
}
|
||||
pdata[victim].smartChargeAttempts = 0;
|
||||
pdata[victim].smartChargeMaxAttempts = timeout;
|
||||
pdata[victim].smartChargeActivator = GetClientUserId(activator);
|
||||
CreateTimer(1.0, Timer_CheckForChargerOpportunity, GetClientUserId(victim), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
||||
return TE_Success;
|
||||
}
|
||||
|
||||
TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, trollModifier modifier, int flags) {
|
||||
bool toActive = IsTrollActiveByRawID(victim, troll.id);
|
||||
if(StrEqual(troll.name, "Reset User")) {
|
||||
void AddMagnetFlags(TrollBuilder troll) {
|
||||
PrintToServer("adding: %d", troll.Id);
|
||||
troll.AddPrompt("Choose Magnet Chance:")
|
||||
.AddOptionFloat("Always (100%)", true, 1.0)
|
||||
.AddOptionFloat("Half Time (50%)", false, 0.5)
|
||||
.AddOptionFloat("Rare (10%)", false, 0.1);
|
||||
}
|
||||
|
||||
TrollEffectResponse ApplyAffect(int victim, Troll troll, int activator, trollModifier modifier, int flags) {
|
||||
bool toActive = troll.IsActive(victim);
|
||||
char name[MAX_TROLL_NAME_LENGTH];
|
||||
troll.GetName(name, sizeof(name));
|
||||
if(StrEqual(name, "Reset User")) {
|
||||
LogAction(activator, victim, "\"%L\" reset all effects for \"%L\"", activator, victim);
|
||||
ShowActivityEx(activator, "[FTT] ", "reset effects for %N. ", victim);
|
||||
// for(int i = 0; i <= MAX_TROLLS; i++) {
|
||||
|
@ -306,7 +319,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
// SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
||||
ResetClient(victim, true);
|
||||
return TE_Error; // Not an error, but don't want to show activation
|
||||
} else if(StrEqual(troll.name, "Slow Speed")) {
|
||||
} else if(StrEqual(name, "Slow Speed")) {
|
||||
if(toActive) {
|
||||
float movement = 0.0;
|
||||
if(flags & 1) movement = 0.9;
|
||||
|
@ -317,22 +330,22 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", movement);
|
||||
} else
|
||||
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
||||
} else if(StrEqual(troll.name, "Higher Gravity"))
|
||||
} else if(StrEqual(name, "Higher Gravity"))
|
||||
SetEntityGravity(victim, toActive ? 1.3 : 1.0);
|
||||
else if(StrEqual(troll.name, "UziRules / AwpSmells")) {
|
||||
else if(StrEqual(name, "UziRules / AwpSmells")) {
|
||||
DisableTroll(victim, "No Pickup");
|
||||
DisableTroll(victim, "Primary Disable");
|
||||
} else if(StrEqual(troll.name, "Primary Disable")) {
|
||||
} else if(StrEqual(name, "Primary Disable")) {
|
||||
DisableTroll(victim, "UziRules / AwpSmells");
|
||||
DisableTroll(victim, "No Pickup");
|
||||
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
|
||||
} else if(StrEqual(troll.name, "No Pickup")) {
|
||||
} else if(StrEqual(name, "No Pickup")) {
|
||||
DisableTroll(victim, "UziRules / AwpSmells");
|
||||
DisableTroll(victim, "Primary Disable");
|
||||
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
|
||||
} else if(StrEqual(troll.name, "CameTooEarly")) {
|
||||
} else if(StrEqual(name, "CameTooEarly")) {
|
||||
ReplyToCommand(activator, "This troll mode is not implemented.");
|
||||
} else if(StrEqual(troll.name, "KillMeSoftly")) {
|
||||
} else if(StrEqual(name, "KillMeSoftly")) {
|
||||
static char wpn[32];
|
||||
GetClientWeaponName(victim, 4, wpn, sizeof(wpn));
|
||||
if(StrEqual(wpn, "weapon_adrenaline") || StrEqual(wpn, "weapon_pain_pills")) {
|
||||
|
@ -344,17 +357,17 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
}
|
||||
//TODO: Implement TrollMod_Constant
|
||||
return TE_Error;
|
||||
} else if(StrEqual(troll.name, "Throw It All")) {
|
||||
} else if(StrEqual(name, "Throw It All")) {
|
||||
if(modifier & TrollMod_Instant) {
|
||||
if(flags & 1) { // Hacky, just throw their kit
|
||||
ThrowItemToPlayer(victim, activator, 3);
|
||||
} else ThrowAllItems(victim);
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Swarm")) {
|
||||
} else if(StrEqual(name, "Swarm")) {
|
||||
if(modifier & TrollMod_Instant) {
|
||||
L4D2_RunScript("RushVictim(GetPlayerFromUserID(%d), %d)", victim, 15000);
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Gun Jam")) {
|
||||
} else if(StrEqual(name, "Gun Jam")) {
|
||||
int wpn = GetClientWeaponEntIndex(victim, 0);
|
||||
if(wpn > -1)
|
||||
SDKHook(wpn, SDKHook_Reload, Event_WeaponReload);
|
||||
|
@ -362,25 +375,25 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
ReplyToCommand(activator, "Victim does not have a primary weapon.");
|
||||
return TE_Error;
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Vomit Player"))
|
||||
} else if(StrEqual(name, "Vomit Player"))
|
||||
L4D_CTerrorPlayer_OnVomitedUpon(victim, victim);
|
||||
else if(StrEqual(troll.name, "Insta Special")) {
|
||||
else if(StrEqual(name, "Insta Special")) {
|
||||
int mode = 0;
|
||||
if(flags & 2) mode = 1;
|
||||
ShowInstaSpecialChooser(activator, GetClientUserId(victim), mode);
|
||||
return TE_Menu;
|
||||
} else if(StrEqual(troll.name, "Goo")) {
|
||||
} else if(StrEqual(name, "Goo")) {
|
||||
static float pos[3], ang[3];
|
||||
GetClientAbsOrigin(victim, pos);
|
||||
GetClientAbsAngles(victim, ang);
|
||||
L4D2_SpitterPrj(victim, pos, ang);
|
||||
} else if(StrEqual(troll.name, "Stagger")) {
|
||||
} else if(StrEqual(name, "Stagger")) {
|
||||
L4D_StaggerPlayer(victim, victim, NULL_VECTOR);
|
||||
} else if(StrEqual(troll.name, "Voice Mute")) {
|
||||
} else if(StrEqual(name, "Voice Mute")) {
|
||||
BaseComm_SetClientMute(victim, toActive);
|
||||
} else if(StrEqual(troll.name, "Spicy Gas")) {
|
||||
} else if(StrEqual(name, "Spicy Gas")) {
|
||||
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
|
||||
} else if(StrEqual(troll.name, "Car Splat")) {
|
||||
} else if(StrEqual(name, "Car Splat")) {
|
||||
if(flags & 1) {
|
||||
if(!SpawnCarOnPlayer(victim)) {
|
||||
ReplyToCommand(activator, "Could not find a suitable area to spawn a car. Requires vertical space above victim.");
|
||||
|
@ -397,7 +410,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
return TE_Error;
|
||||
}
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Instant Commons")) {
|
||||
} else if(StrEqual(name, "Instant Commons")) {
|
||||
if(modifier & TrollMod_Instant) {
|
||||
float pos[3];
|
||||
GetHorizontalPositionFromClient(victim, flags & 1 ? -40.0 : 40.0, pos);
|
||||
|
@ -407,7 +420,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
L4D2_RunScript("CommandABot({cmd=0,bot=EntIndexToHScript(%i),target=GetPlayerFromUserID(%i)})", c, victimId);
|
||||
}
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Randomize Clip Ammo")) {
|
||||
} else if(StrEqual(name, "Randomize Clip Ammo")) {
|
||||
if(modifier & TrollMod_Instant) {
|
||||
int primaryWpn = GetPlayerWeaponSlot(victim, 0);
|
||||
if(primaryWpn > 0) {
|
||||
|
@ -415,7 +428,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
SetEntProp(primaryWpn, Prop_Send, "m_iClip1", GetRandomInt(0, maxCap));
|
||||
}
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Rock Dropper")) {
|
||||
} else if(StrEqual(name, "Rock Dropper")) {
|
||||
float pos[3], dropPos[3];
|
||||
GetClientEyePosition(victim, pos);
|
||||
dropPos = pos;
|
||||
|
@ -428,7 +441,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
float ang[3];
|
||||
ang[0] = 90.0;
|
||||
L4D_TankRockPrj(0, dropPos, ang);
|
||||
} else if(StrEqual(troll.name, "Molotov Bath")) {
|
||||
} else if(StrEqual(name, "Molotov Bath")) {
|
||||
int count = 1;
|
||||
if(flags & 2) count = 8;
|
||||
float pos[3], dropPos[3];
|
||||
|
@ -449,7 +462,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
for(int i = 0; i < count; i++) {
|
||||
L4D_MolotovPrj(victim, dropPos, vel);
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Dep Bots")) {
|
||||
} else if(StrEqual(name, "Dep Bots")) {
|
||||
if(!toActive) {
|
||||
StopHealingBots();
|
||||
return TE_Success;
|
||||
|
@ -513,7 +526,7 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
wasSbFixEnabled = hSbFixEnabled.BoolValue;
|
||||
hSbFixEnabled.BoolValue = false;
|
||||
}
|
||||
} else if(StrEqual(troll.name, "Smart Charge")) {
|
||||
} else if(StrEqual(name, "Smart Charge")) {
|
||||
if(pdata[victim].smartChargeActivator > 0) {
|
||||
ReplyToCommand(activator, "Target already has smart charge enabled");
|
||||
return TE_Error;
|
||||
|
@ -526,32 +539,36 @@ TrollEffectResponse ApplyAffect(int victim, const Troll troll, int activator, tr
|
|||
pdata[victim].smartChargeMaxAttempts = timeout;
|
||||
pdata[victim].smartChargeActivator = GetClientUserId(activator);
|
||||
CreateTimer(1.0, Timer_CheckForChargerOpportunity, GetClientUserId(victim), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
|
||||
} else if(StrEqual(troll.name, "No Rushing Us")) {
|
||||
} else if(StrEqual(name, "No Rushing Us")) {
|
||||
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
|
||||
} else if(StrEqual(troll.name, "Hide HUD")) {
|
||||
} else if(StrEqual(name, "Hide HUD")) {
|
||||
if(toActive)
|
||||
HideHUDRandom(victim);
|
||||
else
|
||||
SetEntProp(victim, Prop_Send, "m_iHideHUD", 0);
|
||||
} else if(StrEqual(troll.name, "Meta: Random")) {
|
||||
int rndTroll = GetRandomInt(0, MAX_TROLLS);
|
||||
} else if(StrEqual(name, "Rewind")) {
|
||||
if(modifier & TrollMod_Instant) {
|
||||
RewindPlayer(victim);
|
||||
}
|
||||
} else if(StrEqual(name, "Meta: Random")) {
|
||||
Troll rndTroll = Troll(GetRandomInt(0, MAX_TROLLS));
|
||||
int rndFlags = 0;
|
||||
int maxFlags = Trolls[rndTroll].GetFlagCount();
|
||||
int maxFlags = rndTroll.TotalOptionsCount;
|
||||
int numFlags = GetRandomInt(0, maxFlags);
|
||||
while(numFlags > 0) {
|
||||
// Apply a random flag
|
||||
rndFlags |= GetRandomInt(0, maxFlags)
|
||||
numFlags--;
|
||||
}
|
||||
trollModifier rndMod = Trolls[rndTroll].GetDefaultMod();
|
||||
if(Trolls[rndTroll].HasMod(TrollMod_Constant) && GetURandomFloat() > 0.5) {
|
||||
trollModifier rndMod = rndTroll.GetDefaultMod();
|
||||
if(rndTroll.HasMod(TrollMod_Constant) && GetURandomFloat() > 0.5) {
|
||||
rndMod = TrollMod_Instant;
|
||||
} else if(Trolls[rndTroll].HasMod(TrollMod_Instant) && GetURandomFloat() > 0.5) {
|
||||
} else if(rndTroll.HasMod(TrollMod_Instant) && GetURandomFloat() > 0.5) {
|
||||
rndMod = TrollMod_Constant;
|
||||
}
|
||||
Trolls[rndTroll].Activate(victim, activator, rndMod, rndFlags);
|
||||
rndTroll.Activate(victim, activator, rndMod, rndFlags);
|
||||
} 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\"", name);
|
||||
#if defined DEBUG
|
||||
ReplyToCommand(activator, "[FTT/Debug] If nothing occurs, this troll possibly was not implemented correctly. ");
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,8 @@ enum L4D2Infected
|
|||
L4D2Infected_Tank = 8
|
||||
};
|
||||
|
||||
bool g_actionsAvailable;
|
||||
|
||||
GlobalForward g_PlayerMarkedForward;
|
||||
GlobalForward g_TrollAppliedForward;
|
||||
Handle g_hWitchAttack;
|
||||
|
|
|
@ -10,13 +10,16 @@
|
|||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <sdkhooks>
|
||||
#include <jutils>
|
||||
#include <left4dhooks>
|
||||
#include <jutils>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#tryinclude <sceneprocessor>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#tryinclude <actions>
|
||||
#include <basecomm>
|
||||
#include <ftt>
|
||||
#include <multicolors>
|
||||
#undef REQUIRE_PLUGIN
|
||||
#tryinclude <l4d_anti_rush>
|
||||
|
||||
public Plugin myinfo =
|
||||
|
@ -32,6 +35,19 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
|
|||
CreateNative("ApplyTroll", Native_ApplyTroll);
|
||||
return APLRes_Success;
|
||||
}
|
||||
public void OnLibraryAdded(const char[] name) {
|
||||
if(StrEqual(name, "actionslib")) {
|
||||
g_actionsAvailable = true;
|
||||
}
|
||||
}
|
||||
public void OnLibraryRemoved(const char[] name) {
|
||||
if(StrEqual(name, "actionslib")) {
|
||||
g_actionsAvailable = false;
|
||||
}
|
||||
}
|
||||
public void OnAllPluginsLoaded() {
|
||||
g_actionsAvailable = LibraryExists("actionslib");
|
||||
}
|
||||
|
||||
|
||||
public void OnPluginStart() {
|
||||
|
@ -47,7 +63,6 @@ public void OnPluginStart() {
|
|||
|
||||
// Load core things (trolls & phrases):
|
||||
REPLACEMENT_PHRASES = new StringMap();
|
||||
TYPOS_DICT = new StringMap();
|
||||
LoadPhrases();
|
||||
LoadTypos();
|
||||
SetupTrolls();
|
||||
|
@ -102,9 +117,11 @@ public void OnPluginStart() {
|
|||
RegAdminCmd("sm_rff", Command_SetReverseFF, ADMFLAG_KICK, "Set reverse FF on player");
|
||||
RegAdminCmd("sm_magnet", Command_SetMagnetShortcut, ADMFLAG_KICK, "");
|
||||
RegAdminCmd("sm_csplat", Command_CarSplat, ADMFLAG_KICK, "");
|
||||
RegAdminCmd("sm_typo", Command_AddTypo, ADMFLAG_GENERIC);
|
||||
|
||||
HookEvent("player_spawn", Event_PlayerSpawn);
|
||||
HookEvent("player_first_spawn", Event_PlayerFirstSpawn);
|
||||
HookEvent("player_disconnect", Event_PlayerDisconnect);
|
||||
HookEvent("player_death", Event_PlayerDeath);
|
||||
HookEvent("triggered_car_alarm", Event_CarAlarm);
|
||||
HookEvent("witch_harasser_set", Event_WitchVictimSet);
|
||||
|
@ -198,6 +215,7 @@ bool IsPlayerFarDistance(int client, float distance) {
|
|||
return client == farthestClient && difference > distance;
|
||||
}
|
||||
|
||||
#if defined _actions_included
|
||||
BehaviorAction CreateWitchAttackAction(int target = 0) {
|
||||
BehaviorAction action = ActionsManager.Allocate(18556);
|
||||
SDKCall(g_hWitchAttack, action, target);
|
||||
|
@ -211,6 +229,7 @@ Action OnWitchActionUpdate(BehaviorAction action, int actor, float interval, Act
|
|||
result.SetReason("FTT");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
#endif
|
||||
|
||||
void HideHUD(int victim, float timeout = 0.0) {
|
||||
SetEntProp(victim, Prop_Send, "m_iHideHUD", 64);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue