ftt: Upgrade to categories / minor improvements

This commit is contained in:
Jackzie 2021-09-25 16:47:52 -05:00
parent 32dace5bf6
commit f756ec3100
No known key found for this signature in database
GPG key ID: 1E834FE36520537A
11 changed files with 397 additions and 92 deletions

Binary file not shown.

View file

@ -1,6 +1,6 @@
#define MAX_TROLL_NAME_LENGTH 32
#define MAX_TROLLS 25
#define MAX_TROLLS 28
//#define DEBUG 1
enum trollModifier {
@ -11,14 +11,17 @@ enum trollModifier {
enum struct Troll {
char name[32];
char name[MAX_TROLL_NAME_LENGTH];
char description[128];
bool runsOnce;
int flags;
int categoryID;
void GetID(char[] name, int length) {
strcopy(name, length, this.name);
char _id[MAX_TROLL_NAME_LENGTH];
void GetID(char[] name) {
strcopy(name, MAX_TROLL_NAME_LENGTH, this.name);
ReplaceString(name, MAX_TROLL_NAME_LENGTH, " ", "", false);
}
@ -33,6 +36,10 @@ enum struct Troll {
else if(this.flags == view_as<int>(TrollMod_Constant)) return TrollMod_Constant;
else return TrollMod_Invalid;
}
void Activate(int victim, int activator, trollModifier modifier, bool silent = false) {
ApplyTroll(victim, this._id, activator, modifier, silent);
}
}
Troll Trolls[MAX_TROLLS+1];
@ -50,7 +57,8 @@ void ResetClient(int victim, bool wipe = true) {
if(wpn > -1)
SDKUnhook(wpn, SDKHook_Reload, Event_WeaponReload);
}
ArrayList categories;
static int categoryID = 0;
int SetupTroll(const char[] name, const char description[128], int flags) {
if(flags == 0) {
ThrowError("Troll \"%s\" has no flags defined.", name);
@ -59,11 +67,13 @@ int SetupTroll(const char[] name, const char description[128], int flags) {
static int i = 0;
strcopy(Trolls[i].name, MAX_TROLL_NAME_LENGTH, name);
strcopy(Trolls[i].description, 128, description);
Trolls[i].categoryID = categoryID;
Trolls[i].flags = flags;
static char key[MAX_TROLL_NAME_LENGTH];
strcopy(key, MAX_TROLL_NAME_LENGTH, name);
ReplaceString(key, MAX_TROLL_NAME_LENGTH, " ", "", false);
strcopy(trollIds[i], MAX_TROLL_NAME_LENGTH, key);
strcopy(Trolls[i]._id, MAX_TROLL_NAME_LENGTH, key);
trollKV.SetValue(key, i);
return i++;
}
@ -110,7 +120,9 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
victim = FindIdlePlayerBot(victim);
}
ApplyAffect(victim, name, activator, modifier);
if(!ApplyAffect(victim, name, activator, modifier)) {
return;
}
if(!silent) {
if(IsTrollActive(victim, name)) {
@ -127,11 +139,11 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
}
}
void ApplyAffect(int victim, const char[] name, int activator, trollModifier modifier) {
bool ApplyAffect(int victim, const char[] name, int activator, trollModifier modifier) {
if(StrEqual(name, "ResetTroll")) {
ShowActivity(activator, "reset troll effects for %N. ", victim);
ActiveTrolls[victim] = 0;
return;
return false;
} else if(StrEqual(name, "SlowSpeed"))
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 0.8);
else if(StrEqual(name, "HigherGravity"))
@ -151,26 +163,6 @@ void ApplyAffect(int victim, const char[] name, int activator, trollModifier mod
DisableTroll(victim, "UziRules");
DisableTroll(victim, "PrimaryDisable");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(name, "Clumsy")) {
int wpn = GetClientSecondaryWeapon(victim);
bool hasMelee = DoesClientHaveMelee(victim);
if(hasMelee) {
float pos[3];
int clients[4];
GetClientAbsOrigin(victim, pos);
int clientCount = GetClientsInRange(pos, RangeType_Visibility, clients, sizeof(clients));
for(int i = 0; i < clientCount; i++) {
if(clients[i] != victim) {
float targPos[3];
GetClientAbsOrigin(clients[i], targPos);
SDKHooks_DropWeapon(victim, wpn, targPos);
// g_iTrollUsers[victim] = mode;
CreateTimer(0.2, Timer_GivePistol);
return;
}
}
SDKHooks_DropWeapon(victim, wpn);
}
} else if(StrEqual(name, "CameTooEarly")) {
ReplyToCommand(activator, "This troll mode is not implemented.");
} else if(StrEqual(name, "KillMeSoftly")) {
@ -181,10 +173,10 @@ void ApplyAffect(int victim, const char[] name, int activator, trollModifier mod
g_bPendingItemGive[victim] = true;
}else{
ReplyToCommand(activator, "User does not have pills or adrenaline");
return;
return false;
}
//TODO: Implement TrollMod_Constant
return;
return false;
} else if(StrEqual(name, "ThrowItAll")) {
if(modifier == TrollMod_Instant)
ThrowAllItems(victim);
@ -198,7 +190,7 @@ void ApplyAffect(int victim, const char[] name, int activator, trollModifier mod
}else{
ReplyToCommand(activator, "Invalid modifier for mode.");
return;
return false;
}
} else if(StrEqual(name, "GunJam")) {
int wpn = GetClientWeaponEntIndex(victim, 0);
@ -208,12 +200,19 @@ void ApplyAffect(int victim, const char[] name, int activator, trollModifier mod
ReplyToCommand(activator, "Victim does not have a primary weapon.");
} else if(StrEqual(name, "VomitPlayer"))
L4D_CTerrorPlayer_OnVomitedUpon(victim, victim);
else {
else if(StrEqual(name, "InfaceSpecial")) {
FakeClientCommand(victim, "sm_inface");
return false;
} else if(StrEqual(name, "InstaSpecial")) {
FakeClientCommand(victim, "sm_insta");
return false;
} else {
#if defined DEBUG
PrintToServer("[FTT] Possibly invalid troll, no action: %s", name);
ReplyToCommand(activator, "[FTT/Debug] If nothing occurs, this troll possibly was not implemented correctly. ");
#endif
}
return true;
}
bool IsTrollActive(int client, const char[] troll) {
@ -238,34 +237,53 @@ void DisableTroll(int client, const char[] troll) {
}
}
void SetCategory(const char[] newCat) {
categoryID = categories.PushString(newCat);
}
void GetCategory(int category, char[] buffer, int size) {
categories.GetString(category, buffer, size);
}
void SetupTrolls() {
trollKV = new StringMap();
categories = new ArrayList(ByteCountToCells(16));
SetupTroll("Reset Troll", "Resets the user, removes all troll effects", TrollMod_Instant);
SetCategory("Magnet / Horde");
SetupTroll("Special Magnet", "Attracts ALL specials to any alive target with this troll enabled", TrollMod_Constant);
SetupTroll("Tank Magnet", "Attracts ALL tanks to any alive target with this troll enabled", TrollMod_Constant);
SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant);
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
SetupTroll("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant);
SetupTroll("Throw It All", "Player throws all their items at nearby player, periodically", TrollMod_Instant | TrollMod_Constant);
SetupTroll("Vocalize Gag", "Prevents player from sending any vocalizations (even automatic)", TrollMod_Constant);
SetupTroll("No Profanity", "Replaces some words with random phrases", TrollMod_Constant);
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant);
SetupTroll("UziRules", "Picking up a weapon gives them a UZI instead", TrollMod_Constant);
SetupTroll("Slow Speed", "Sets player speed to 0.8x of normal speed", TrollMod_Constant);
SetupTroll("Higher Gravity", "Sets player gravity to 1.3x of normal gravity", TrollMod_Constant);
SetupTroll("Half Primary Ammo", "Cuts their primary reserve ammo in half", TrollMod_Instant);
SetupTroll("Primary Disable", "Player cannot pickup any weapons, only melee/pistols", TrollMod_Constant);
SetupTroll("Clusmy", "Player drops axe periodically or on demand", TrollMod_Instant | TrollMod_Constant);
SetupTroll("iCantSpellNoMore", "Chat messages letter will randomly changed with wrong letters", TrollMod_Instant);
SetupTroll("KillMeSoftly", "Make player eat or waste pills whenever possible", TrollMod_Instant | TrollMod_Constant);
SetupTroll("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant);
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
SetCategory("Items");
SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
SetupTroll("Bad Throw", "Player drops throwables on throw, and biles/molotovs themselves", TrollMod_Constant);
SetupTroll("No Pickup", "Prevents a player from picking up ANY (new) item. Use ThrowItAll to make them drop", TrollMod_Constant);
SetupTroll("UziRules", "Picking up a weapon gives them a UZI instead", TrollMod_Constant);
SetupTroll("Primary Disable", "Player cannot pickup any weapons, only melee/pistols", TrollMod_Constant);
SetupTroll("Half Primary Ammo", "Cuts their primary reserve ammo in half", TrollMod_Instant);
SetCategory("Chat");
SetupTroll("iCantSpellNoMore", "Chat messages letter will randomly changed with wrong letters", TrollMod_Instant);
SetupTroll("No Profanity", "Replaces some words with random phrases", TrollMod_Constant);
SetupTroll("Vocalize Gag", "Prevents player from sending any vocalizations (even automatic)", TrollMod_Constant);
SetupTroll("Honk", "Honk", TrollMod_Constant);
SetupTroll("No Shove", "Prevents a player from shoving", TrollMod_Constant);
SetupTroll("Meow", "Makes the player meow", TrollMod_Constant);
SetCategory("Health");
SetupTroll("Damage Boost", "Makes a player take more damage than normal", TrollMod_Constant);
SetupTroll("Temp Health Quick Drain", "Makes a player's temporarily health drain very quickly", TrollMod_Constant);
SetupTroll("Slow Drain", "Will make the player slowly lose health over time", TrollMod_Constant);
SetupTroll("KillMeSoftly", "Make player eat or waste pills whenever possible", TrollMod_Instant | TrollMod_Constant);
SetCategory("Misc");
SetupTroll("Gun Jam", "On reload, small chance their gun gets jammed - Can't reload.", TrollMod_Constant);
SetupTroll("Slow Speed", "Sets player speed to 0.8x of normal speed", TrollMod_Constant);
SetupTroll("Higher Gravity", "Sets player gravity to 1.3x of normal gravity", TrollMod_Constant);
SetupTroll("No Shove", "Prevents a player from shoving", TrollMod_Constant);
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
SetupTroll("Meow", "Makes the player meow", TrollMod_Constant);
//INFO: UP MAX_TROLLS when adding new trolls!
}

View file

@ -1,7 +1,7 @@
public Action Command_InstaSpecial(int client, int args) {
if(args < 1) {
Menu menu = new Menu(Insta_PlayerHandler);
menu.SetTitle("Choose a player");
menu.SetTitle("InstaSpecial: Choose a player");
for(int i = 1; i < MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2) {
static char userid[8], display[16];
@ -59,7 +59,7 @@ public Action Command_InstaSpecial(int client, int args) {
public Action Command_InstaSpecialFace(int client, int args) {
if(args < 1) {
Menu menu = new Menu(Insta_PlayerHandler);
menu.SetTitle("Choose a player");
menu.SetTitle("Inface: Choose a player");
for(int i = 1; i < MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2) {
static char userid[8], display[16];
@ -201,7 +201,7 @@ public Action Command_ResetUser(int client, int args) {
public Action Command_ApplyUser(int client, int args) {
if(args < 2) {
Menu menu = new Menu(ChoosePlayerHandler);
menu.SetTitle("Choose a player");
menu.SetTitle("Choose a player to troll");
for(int i = 1; i < MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2) {
static char userid[8], display[16];

View file

@ -12,6 +12,8 @@ public void OnMapStart() {
HookEntityOutput("func_button", "OnPressed", Event_ButtonPress);
CreateTimer(MAIN_TIMER_INTERVAL_S, Timer_Main, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
PrecacheSound("player/footsteps/clown/concrete1.wav");
PrecacheSound("weapons/ceda_jar/ceda_jar_explode.wav");
PrecacheSound("weapons/molotov/molotov_detonate_1.wav");
//CreateTimer(30.0, Timer_AutoPunishCheck, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}
public void OnClientPutInServer(int client) {
@ -219,7 +221,8 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
int words = ExplodeString(sArgs, " ", strings, 32, MAX_PHRASE_LENGTH);
for(int i = 0; i < words; i++) {
//TODO: Check for valid working
if((phrases = GetPhrasesArray(strings[i])) && phrases.Length > 0) {
phrases = GetPhrasesArray(strings[i]);
if(phrases != null && phrases.Length > 0) {
foundWord = true;
int c = phrases.GetString(GetRandomInt(0, phrases.Length - 1), strings[i], MAX_PHRASE_LENGTH);
PrintToServer("replacement: %s (%d)", strings[i], c);
@ -369,3 +372,47 @@ public Action Event_WitchVictimSet(Event event, const char[] name, bool dontBroa
pack.WriteCell(witch);
}
}
public void OnEntityCreated(int entity, const char[] classname) {
if(IsValidEntity(entity) && StrContains(classname, "_projectile", true) > -1 ) {
RequestFrame(EntityCreateCallback, entity);
}
}
void EntityCreateCallback(int entity) {
if(!HasEntProp(entity, Prop_Send, "m_hOwnerEntity") || !IsValidEntity(entity)) return;
static char class[16];
GetEntityClassname(entity, class, sizeof(class));
int entOwner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
if(entOwner > 0 && entOwner <= MaxClients && IsTrollActive(entOwner, "BadThrow")) {
static float pos[3];
GetClientEyePosition(entOwner, pos);
if(StrContains(class, "vomitjar", true) > -1) {
AcceptEntityInput(entity, "Kill");
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue) {
L4D_CTerrorPlayer_OnVomitedUpon(entOwner, entOwner);
EmitSoundToAll("weapons/ceda_jar/ceda_jar_explode.wav", entOwner);
FindClosestClient(entOwner, false, pos);
}
SpawnItem("vomitjar", pos);
} else if(StrContains(class, "molotov", true) > -1) {
// Burn them if no one near :)
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue) {
GetClientAbsOrigin(entOwner, pos);
if(IsAnyPlayerNear(entOwner, 500.0)) {
AcceptEntityInput(entity, "Kill");
EmitSoundToAll("weapons/molotov/molotov_detonate_1.wav", entOwner);
} else { // or delete if there is
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
}
} else {
SpawnItem("molotov", pos);
AcceptEntityInput(entity, "Kill");
}
} else if(StrContains(class, "pipe_bomb", true) > -1) {
if(hBadThrowHitSelf.FloatValue > 0.0 && GetRandomFloat() > hBadThrowHitSelf.FloatValue)
TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR);
SpawnItem("pipe_bomb", pos);
}
}
}

View file

@ -13,9 +13,8 @@ public int Insta_PlayerHandler(Menu menu, MenuAction action, int client, int par
Menu spMenu = new Menu(Insta_SpecialHandler);
spMenu.SetTitle("Choose a Insta-Special™");
for(int i = 1; i <= 6; i++) {
static char id[8];
Format(id, sizeof(id), "%d|%d|%d", userid, instaMode, i);
spMenu.AddItem(id, SPECIAL_NAMES[i-1]);
Format(info, sizeof(info), "%d|%d|%d", userid, instaMode, i);
spMenu.AddItem(info, SPECIAL_NAMES[i-1]);
}
spMenu.ExitButton = true;
spMenu.Display(client, 0);
@ -58,21 +57,42 @@ public int ChooseMarkedTroll(Menu menu, MenuAction action, int activator, int pa
public int ChoosePlayerHandler(Menu menu, MenuAction action, int param1, int param2) {
/* If an option was selected, tell the client about the item. */
if (action == MenuAction_Select) {
static char info[16];
static char info[8];
menu.GetItem(param2, info, sizeof(info));
int userid = StringToInt(info);
SetupCategoryMenu(param1, userid);
} else if (action == MenuAction_End)
delete menu;
}
public int ChooseCategoryHandler(Menu menu, MenuAction action, int param1, int param2) {
if (action == MenuAction_Select) {
static char info[32];
menu.GetItem(param2, info, sizeof(info));
static char str[2][8];
ExplodeString(info, "|", str, 2, 8, false);
int userid = StringToInt(str[0]);
int category = StringToInt(str[1]);
Menu trollMenu = new Menu(ChooseModeMenuHandler);
trollMenu.SetTitle("Choose a troll mode");
GetCategory(category, info, sizeof(info));
Format(info, sizeof(info), "Category: %s", info);
trollMenu.SetTitle(info);
//TODO: Update
static char id[8];
static Troll troll;
for(int i = 0; i <= MAX_TROLLS; i++) {
// add 'return' btn
Format(info, sizeof(info), "%d|-1", userid);
trollMenu.AddItem(info, "<= Go Back");
// Add all menus that have same category
for(int i = 0; i < trollKV.Size; i++) {
GetTrollByKeyIndex(i, troll);
// int trollIndex = GetTrollByKeyIndex(i, troll);
// Pass key index
Format(id, sizeof(id), "%d|%d", userid, i);
trollMenu.AddItem(id, troll.name);
if(troll.categoryID == category) {
Format(info, sizeof(info), "%d|%d", userid, i);
trollMenu.AddItem(info, troll.name);
}
}
trollMenu.ExitButton = true;
trollMenu.Display(param1, 0);
@ -81,7 +101,6 @@ public int ChoosePlayerHandler(Menu menu, MenuAction action, int param1, int par
}
public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int param2) {
/* If an option was selected, tell the client about the item. */
if (action == MenuAction_Select) {
static char info[16];
menu.GetItem(param2, info, sizeof(info));
@ -90,21 +109,44 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
int userid = StringToInt(str[0]);
int client = GetClientOfUserId(userid);
int keyIndex = StringToInt(str[1]);
if(keyIndex == -1) {
SetupCategoryMenu(param1, userid);
return;
}
static Troll troll;
static char trollID[MAX_TROLL_NAME_LENGTH];
GetTrollByKeyIndex(keyIndex, troll);
troll.GetID(trollID, MAX_TROLL_NAME_LENGTH);
troll.GetID(trollID);
//If troll has multiple flags, prompt:
if(troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
if(StrEqual(trollID, "ThrowItAll")) {
// Setup menu to call itself, but with an extra data point
Menu itmMenu = new Menu(ChooseClumsySlotHandler);
itmMenu.SetTitle("Choose Item To Throw");
static char itmName[32];
Format(info, sizeof(info), "%d|-1", userid);
itmMenu.AddItem(info, "All Items");
for(int slot = 0; slot <= 4; slot++) {
int item = GetPlayerWeaponSlot(client, slot);
if(item > -1) {
GetEdictClassname(item, itmName, sizeof(itmName));
Format(info, sizeof(info), "%d|%d", userid, slot);
itmMenu.AddItem(info, itmName[7]);
}
}
itmMenu.ExitButton = true;
itmMenu.Display(param1, 0);
} else if(troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
Menu modiferMenu = new Menu(ChooseTrollModiferHandler);
modiferMenu.SetTitle("Choose Troll Modifer Option");
static char singleUse[16], multiUse[16], bothUse[16];
Format(singleUse, sizeof(singleUse), "%d|%d|1", userid, keyIndex);
Format(multiUse, sizeof(multiUse), "%d|%d|2", userid, keyIndex);
Format(bothUse, sizeof(bothUse), "%d|%d|3", userid, keyIndex);
modiferMenu.AddItem(singleUse, "Activate once");
modiferMenu.AddItem(multiUse, "Activate Periodically");
modiferMenu.AddItem(bothUse, "Activate Periodically & Instantly");
Format(info, sizeof(info), "%d|%d|1", userid, keyIndex);
modiferMenu.AddItem(info, "Activate once");
Format(info, sizeof(info), "%d|%d|2", userid, keyIndex);
modiferMenu.AddItem(info, "Activate Periodically");
Format(info, sizeof(info), "%d|%d|3", userid, keyIndex);
modiferMenu.AddItem(info, "Activate Periodically & Instantly");
modiferMenu.ExitButton = true;
modiferMenu.Display(param1, 0);
} else {
@ -114,6 +156,27 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
delete menu;
}
public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int param2) {
if (action == MenuAction_Select) {
static char info[8];
menu.GetItem(param2, info, sizeof(info));
static char str[2][8];
ExplodeString(info, "|", str, 2, 8, false);
int client = GetClientOfUserId(StringToInt(str[0]));
int slot = StringToInt(str[1]);
PrintToChatAll("%d", slot);
if(slot == -1) {
for(int i = 0; i <= 4; i++) {
ThrowItemToClosestPlayer(client, i);
}
} else {
ThrowItemToClosestPlayer(client, slot);
}
ShowActivity(param1, "activated troll \"Throw It All\" for %N. ", client);
} else if (action == MenuAction_End)
delete menu;
}
public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, int param2) {
if (action == MenuAction_Select) {
static char info[16];
@ -122,15 +185,17 @@ public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, i
ExplodeString(info, "|", str, 3, 8, false);
int client = GetClientOfUserId(StringToInt(str[0]));
int keyIndex = StringToInt(str[1]);
static Troll troll;
static char trollID[MAX_TROLL_NAME_LENGTH];
GetTrollByKeyIndex(keyIndex, troll);
troll.GetID(trollID, MAX_TROLL_NAME_LENGTH);
int flags = StringToInt(str[2]);
static Troll troll;
GetTrollByKeyIndex(keyIndex, troll);
if(flags == 1 || flags == 3)
ApplyTroll(client, trollID, param1, TrollMod_Instant);
troll.Activate(client, param1, TrollMod_Instant);
// ApplyTroll(client, trollID, param1, TrollMod_Instant);
if(flags == 2 || flags == 3)
ApplyTroll(client, trollID, param1, TrollMod_Constant);
troll.Activate(client, param1, TrollMod_Constant);
// ApplyTroll(client, trollID, param1, TrollMod_Constant);
} else if (action == MenuAction_End)
delete menu;
}
@ -138,3 +203,16 @@ public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, i
public void StopItemGive(int client) {
g_bPendingItemGive[client] = false;
}
void SetupCategoryMenu(int client, int victimUserID) {
Menu categoryMenu = new Menu(ChooseCategoryHandler);
categoryMenu.SetTitle("Choose a troll category");
static char category[16], id[8];
for(int i = 0; i < categories.Length; i++) {
categories.GetString(i, category, sizeof(category));
Format(id, sizeof(id), "%d|%d", victimUserID, i);
categoryMenu.AddItem(id, category);
}
categoryMenu.ExitButton = true;
categoryMenu.Display(client, 0);
}

View file

@ -116,6 +116,116 @@ ArrayList GetPhrasesArray(const char[] key) {
keyLower[i] = CharToLower(key[i]);
}
ArrayList phrases;
REPLACEMENT_PHRASES.GetValue(keyLower, phrases);
if(REPLACEMENT_PHRASES.GetValue(keyLower, phrases)) {
return phrases;
} else {
return null;
}
}
int FindClosestClientAdminPriority(int source, bool ignoreBots, float pos[3]) {
int c = FindClosestAdmin(source, ignoreBots, pos);
if(c == -1) return FindClosestClient(source, ignoreBots, pos);
else return c;
}
int FindClosestClient(int source, bool ignoreBots, float pos[3]) {
int closest = -1;
float minDist = -1.0;
static float pos1[3];
static float pos2[3];
GetClientAbsOrigin(source, pos1);
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && (!ignoreBots || !IsFakeClient(i)) && i != source) {
GetClientAbsOrigin(i, pos2);
float dist = GetVectorDistance(pos1, pos2);
if(minDist == -1.0 || dist <= minDist) {
closest = i;
minDist = dist;
}
}
}
GetClientEyePosition(closest, pos);
return closest;
}
int FindClosestAdmin(int source, bool ignoreBots, float pos[3]) {
int closest = -1;
float minDist = -1.0;
static float pos1[3];
static float pos2[3];
GetClientAbsOrigin(source, pos);
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && (|ignoreBots || !IsFakeClient(i)) && GetUserAdmin(i) != INVALID_ADMIN_ID && i != source) {
GetClientAbsOrigin(i, pos2);
float dist = GetVectorDistance(pos1, pos2);
if(minDist == -1.0 || dist <= minDist) {
closest = i;
minDist = dist;
}
}
}
GetClientEyePosition(closest, pos);
return closest;
}
int SpawnItem(const char[] entityName, float pos[3], float ang[3] = NULL_VECTOR) {
static char classname[32];
Format(classname, sizeof(classname), "weapon_%s", entityName);
int spawner = CreateEntityByName(classname);
if(spawner == -1) return -1;
DispatchKeyValue(spawner, "solid", "6");
// DispatchKeyValue(entity_weapon, "model", g_bLeft4Dead2 ? g_sWeaponModels2[model] : g_sWeaponModels[model]);
DispatchKeyValue(spawner, "rendermode", "3");
DispatchKeyValue(spawner, "disableshadows", "1");
TeleportEntity(spawner, pos, ang, NULL_VECTOR);
DispatchSpawn(spawner);
TeleportEntity(spawner, pos, ang, NULL_VECTOR);
return spawner;
}
bool IsAnyPlayerNear(int source, float range) {
static float pos1[3];
static float pos2[3];
GetClientAbsOrigin(source, pos1);
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && i != source) {
GetClientAbsOrigin(i, pos2);
float dist = GetVectorDistance(pos1, pos2);
PrintToChatAll("%f <= %f: %b", dist, range, (dist <= range));
if(dist <= range) return true;
}
}
return false;
}
void ThrowItemToClosestPlayer(int victim, int slot) {
int wpn = GetPlayerWeaponSlot(victim, slot);
if(slot != 1 || DoesClientHaveMelee(victim)) {
static float pos[3];
int clients[4];
GetClientAbsOrigin(victim, pos);
int clientCount = GetClientsInRange(pos, RangeType_Visibility, clients, sizeof(clients));
for(int i = 0; i < clientCount; i++) {
if(clients[i] != victim) {
static float targPos[3];
GetClientAbsOrigin(clients[i], targPos);
SDKHooks_DropWeapon(victim, wpn, targPos);
if(slot == 1)
CreateTimer(0.2, Timer_GivePistol, GetClientUserId(victim));
return;
}
}
// No client found, drop on ground:
SDKHooks_DropWeapon(victim, wpn, NULL_VECTOR);
}
}
void DropItem(int victim, int slot) {
int wpn = GetPlayerWeaponSlot(victim, slot);
if(slot != 1 || DoesClientHaveMelee(victim)) {
SDKHooks_DropWeapon(victim, wpn, NULL_VECTOR);
}
}

View file

@ -72,7 +72,7 @@ bool SpawnSpecialNear(int target, int specialType) {
if(specialType >= sizeof(SPECIAL_NAMES)) return false;
static float pos[3];
if(L4D_GetRandomPZSpawnPosition(target, specialType, 10, pos)) {
int special = (specialType == 7) ? L4D2_SpawnWitch(pos, ZERO_VECTOR) : L4D2_SpawnSpecial(specialType, pos, ZERO_VECTOR);
int special = (specialType == 7) ? L4D2_SpawnWitch(pos, NULL_VECTOR) : L4D2_SpawnSpecial(specialType, pos, NULL_VECTOR);
if(special == -1) return false;
if(specialType == 7)
SetWitchTarget(special, target);

View file

@ -42,11 +42,14 @@ public Action Timer_Main(Handle timer) {
return Plugin_Continue;
}
public Action Timer_GivePistol(Handle timer, int client) {
public Action Timer_GivePistol(Handle timer, int user) {
int client = GetClientOfUserId(user);
if(client > 0) {
int flags = GetCommandFlags("give");
SetCommandFlags("give", flags & ~FCVAR_CHEAT);
FakeClientCommand(client, "give pistol");
SetCommandFlags("give", flags|FCVAR_CHEAT);
SetCommandFlags("give", flags);
}
}
public Action Timer_ThrowWeapon(Handle timer, Handle pack) {
@ -67,7 +70,7 @@ public Action Timer_ThrowWeapon(Handle timer, Handle pack) {
GetEdictClassname(wpn, name, sizeof(name));
if(!StrEqual(name, "weapon_pistol", false)) {
SDKHooks_DropWeapon(victim, wpn, dest);
CreateTimer(0.2, Timer_GivePistol, victim);
CreateTimer(0.2, Timer_GivePistol, GetClientUserId(victim));
}
}else
SDKHooks_DropWeapon(victim, wpn, dest);

View file

@ -21,6 +21,7 @@ Handle g_hWitchAttack;
Handle hThrowTimer;
//CONVARS
ConVar hVictimsList, hThrowItemInterval, hAutoPunish, hMagnetChance, hShoveFailChance, hAutoPunishExpire, hMagnetTargetMode, hWitchTargetIncapp;
ConVar hBadThrowHitSelf;
//BOOLS
bool lateLoaded; //Is plugin late loaded
bool bChooseVictimAvailable = false; //For charge player feature, is it available?
@ -28,7 +29,7 @@ bool bChooseVictimAvailable = false; //For charge player feature, is it availabl
int g_iAmmoTable; //Loads the ammo table to get ammo amounts
int gChargerVictim = -1; //For charge player feature
float ZERO_VECTOR[3] = {0.0, 0.0, 0.0};
#include <feedthetrolls/base>
#include <feedthetrolls/specials>

View file

@ -67,6 +67,7 @@ public void OnPluginStart() {
hMagnetTargetMode = CreateConVar("sm_ftt_magnet_targetting", "1", "How does the specials target players. Add bits together\n0= Target until Dead, 1=Specials ignore incapped, 2=Tank ignores incapped");
hShoveFailChance = CreateConVar("sm_ftt_shove_fail_chance", "0.5", "The % chance that a shove fails", FCVAR_NONE, true, 0.0, true, 1.0);
hWitchTargetIncapp = CreateConVar("sm_ftt_witch_target_incapped", "1", "Should the witch target witch magnet victims who are incapped?\n 0 = No, 1 = Yes", FCVAR_NONE, true, 0.0, true, 1.0);
hBadThrowHitSelf = CreateConVar("sm_ftt_badthrow_fail_chance", "1", "The % chance that on a throw, they will instead hit themselves. 0 to disable", FCVAR_NONE, true, 0.0, true, 1.0);
RegAdminCmd("sm_ftl", Command_ListTheTrolls, ADMFLAG_KICK, "Lists all the trolls currently ingame.");
RegAdminCmd("sm_ftm", Command_ListModes, ADMFLAG_KICK, "Lists all the troll modes and their description");
@ -94,7 +95,6 @@ public void OnPluginStart() {
HookEntityOutput("func_button", "OnPressed", Event_ButtonPress);
}
}
///////////////////////////////////////////////////////////////////////////////
// CVAR CHANGES
///////////////////////////////////////////////////////////////////////////////
@ -201,7 +201,7 @@ stock bool SetPrimaryReserveAmmo(int client, int amount) {
}
stock void SendChatToAll(int client, const char[] message) {
char nameBuf[MAX_NAME_LENGTH];
static char nameBuf[MAX_NAME_LENGTH];
for (int i = 1; i <= MaxClients; i++) {
if (IsClientInGame(i) && IsFakeClient(i)) {
@ -213,7 +213,7 @@ stock void SendChatToAll(int client, const char[] message) {
stock float GetTempHealth(int client) {
//First filter -> Must be a valid client, successfully in-game and not an spectator (The dont have health).
if(!client || !IsValidEntity(client) || !IsClientInGame(client)|| !IsPlayerAlive(client) || IsClientObserver(client)) {
if(client <= 0 || !IsValidEntity(client) || !IsClientInGame(client)|| !IsPlayerAlive(client) || IsClientObserver(client)) {
return -1.0;
}

View file

@ -0,0 +1,48 @@
#include <sourcemod>
#include <sdktools>
#include <left4dhooks>
#pragma semicolon 1
#pragma newdecls required
ConVar g_cvSurvivorSet;
public Plugin myinfo =
{
name = "[L4D2] Survivor Set Enforcer",
author = "DeathChaos, modified by Psyk0tik (Crasher_3637)",
description = "Forces L4D2 survivor set.",
version = "1.0",
url = ""
};
public void OnPluginStart()
{
g_cvSurvivorSet = CreateConVar("l4d_force_survivorset", "0", "Forces specified survivor set (0 - no change, 1 - force L4D1, 2 - Force L4D2)", _, true, 0.0, true, 2.0);
}
public Action L4D_OnGetSurvivorSet(int &retVal)
{
int iSet = g_cvSurvivorSet.IntValue;
if (iSet > 0)
{
retVal = iSet;
return Plugin_Handled;
}
return Plugin_Continue;
}
public Action L4D_OnFastGetSurvivorSet(int &retVal)
{
int iSet = g_cvSurvivorSet.IntValue;
if (iSet > 0)
{
retVal = iSet;
return Plugin_Handled;
}
return Plugin_Continue;
}