Add new trolls and things

This commit is contained in:
Jackz 2022-06-27 11:39:40 -05:00
parent 24ca8e73cc
commit ca7d54b6f3
No known key found for this signature in database
GPG key ID: E0BBD94CF657F603
10 changed files with 673 additions and 425 deletions

Binary file not shown.

View file

@ -4,7 +4,7 @@
//Allow MAX_TROLLS to be defined elsewhere
#if defined MAX_TROLLS
#else
#define MAX_TROLLS 40
#define MAX_TROLLS 41
#endif
enum trollModifier {
@ -298,11 +298,8 @@ bool IsAnyTrollActive(int victim) {
}
// Gets the Troll enum struct via key index
// Returns index of troll enum
int GetTrollByKeyIndex(int index, Troll troll) {
// static char name[MAX_TROLL_NAME_LENGTH];
// trollIds.GetKey(index, name, sizeof(name));
void GetTrollByKeyIndex(int index, Troll troll) {
troll = Trolls[index];
// return GetTroll(name, troll);
}
void ToggleTroll(int client, const char[] name, int flags = 0) {
@ -365,8 +362,8 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
// Log all actions, indicating if constant or single-fire, and if any flags
if(!silent) {
if(isActive) {
CShowActivityEx(activator, "[FTT] ", "deactivated {green}\"%s\"{default} on %N. ", troll.name, victim);
LogAction(activator, victim, "\"%L\" deactivated {green}\"%s\"{default} on \"%L\"", activator, troll.name, victim);
CShowActivityEx(activator, "[FTT] ", "deactivated {yellow}\"%s\"{default} on %N. ", troll.name, victim);
LogAction(activator, victim, "\"%L\" deactivated {yellow}\"%s\"{default} on \"%L\"", activator, troll.name, victim);
} else {
static char flagName[MAX_TROLL_FLAG_LENGTH];
flagName[0] = '\0';
@ -387,25 +384,25 @@ void ApplyTroll(int victim, const char[] name, int activator, trollModifier modi
if(modifier & TrollMod_Constant) {
if(flags > 0) {
if(flagName[0] != '\0') {
CShowActivityEx(activator, "[FTT] ", "activated constant {green}\"%s\"{default} ({yellow}%s{default}) for %N. ", troll.name, flagName, victim);
CShowActivityEx(activator, "[FTT] ", "activated constant {yellow}%s{default} ({yellow}%s{default}) for %N. ", troll.name, flagName, victim);
} else {
CShowActivityEx(activator, "[FTT] ", "activated constant {green}\"%s\"{default} ({yellow}%d{default}) for %N. ", troll.name, flags, victim);
CShowActivityEx(activator, "[FTT] ", "activated constant {yellow}%s{default} ({yellow}%d{default}) for %N. ", troll.name, flags, victim);
}
} else
CShowActivityEx(activator, "[FTT] ", "activated constant {green}\"%s\"{default} for %N. ", troll.name, victim);
CShowActivityEx(activator, "[FTT] ", "activated constant {yellow}%s{default} for %N. ", troll.name, victim);
} else if(flags > 0) {
if(flagName[0] != '\0') {
CShowActivityEx(activator, "[FTT] ", "activated {green}\"%s\"{default} ({yellow}%s{default}) for %N. ", troll.name, flagName, victim);
CShowActivityEx(activator, "[FTT] ", "activated {yellow}%s{default} ({yellow}%s{default}) for %N. ", troll.name, flagName, victim);
} else {
CShowActivityEx(activator, "[FTT] ", "activated {green}\"%s\"{default} ({yellow}%d{default}) for %N. ", troll.name, flags, victim);
CShowActivityEx(activator, "[FTT] ", "activated {yellow}%s{default} ({yellow}%d{default}) for %N. ", troll.name, flags, victim);
}
} else
CShowActivityEx(activator, "[FTT] ", "activated {green}\"%s\"{default} for %N. ", troll.name, victim);
CShowActivityEx(activator, "[FTT] ", "activated {yellow}%s{default} for %N. ", troll.name, victim);
LogAction(activator, victim, "\"%L\" activated {green}\"%s\"{default} ({yellow}%d{default}) for \"%L\"", activator, troll.name, flags, victim);
LogAction(activator, victim, "\"%L\" activated \"%s\" (%d) for \"%L\"", activator, troll.name, flags, victim);
}
} else {
CReplyToCommand(activator, "ftt: Applied {green}\"%s\"{default} on %N with flags=%d", troll.name, victim, flags);
CReplyToCommand(activator, "ftt: Applied {yellow}\"%s\"{default} on %N with flags=%d", troll.name, victim, flags);
}
}

View file

@ -36,7 +36,6 @@ public Action Command_InstaSpecial(int client, int args) {
return Plugin_Handled;
}
SpecialType specialType = GetSpecialType(arg2);
static float pos[3];
if(specialType == Special_Invalid) {
ReplyToCommand(client, "Unknown special \"%s\"", arg2);
return Plugin_Handled;
@ -101,7 +100,6 @@ public Action Command_InstaSpecialFace(int client, int args) {
return Plugin_Handled;
}
SpecialType specialType = GetSpecialType(arg2);
static float pos[3];
if(specialType == Special_Invalid) {
ReplyToCommand(client, "Unknown special \"%s\"", arg2);
return Plugin_Handled;
@ -337,7 +335,6 @@ public Action Command_ApplyUserSilent(int client, int args) {
}
public Action Command_ListModes(int client, int args) {
static char name[MAX_TROLL_NAME_LENGTH];
static Troll troll;
for(int i = 0; i <= MAX_TROLLS; i++) {
GetTrollByKeyIndex(i, troll);
@ -410,7 +407,6 @@ public Action Command_ListTheTrolls(int client, int args) {
int count = 0;
char[][] modeListArr = new char[MAX_TROLLS+1][MAX_TROLL_NAME_LENGTH];
static char modeList[255];
static char name[MAX_TROLL_NAME_LENGTH];
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) > 1 && IsAnyTrollActive(i)) {
if(IsFakeClient(i)) {
@ -612,4 +608,68 @@ public Action Command_SmartCharge(int client, int args) {
ReplyToCommand(client, "syntax: sm_smartcharge <target player> [timeout or default 10s]");
}
return Plugin_Handled;
}
public Action Command_HealTarget(int client, int args) {
if(args > 0) {
char arg1[32], arg2[4];
GetCmdArg(1, arg1, sizeof(arg1));
GetCmdArg(2, arg2, sizeof(arg2));
int target_list[1], target_count;
static char target_name[MAX_TARGET_LENGTH];
bool tn_is_ml;
if ((target_count = ProcessTargetString(
arg1,
client,
target_list,
1,
COMMAND_FILTER_ALIVE | COMMAND_FILTER_NO_MULTI,
target_name,
sizeof(target_name),
tn_is_ml)) <= 0
) {
/* This function replies to the admin with a failure message */
ReplyToTargetError(client, target_count);
return Plugin_Handled;
}
int target = target_list[0];
int targetUserId = GetClientUserId(target);
if(targetUserId == healTargetPlayer) {
ShowActivity(client, "cleared bots healing for %N", target);
StopHealingBots();
} else {
healTargetPlayer = targetUserId;
CreateTimer(3.0, Timer_UpdateHealTargetPos, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
int limit = StringToInt(arg2);
if(limit <= 0) limit = MaxClients;
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2 && IsFakeClient(i)) {
int kit = GetPlayerWeaponSlot(i, 3);
if(kit > 0) {
GetEntityClassname(kit, arg1, sizeof(arg1));
if(StrEqual(arg1, "weapon_first_aid_kit")) {
isTargettingHealer[i] = true;
if(--limit == 0) {
break;
}
}
}
}
}
if(limit > 0) {
wasAbmAutoHard = hAbmAutoHard.IntValue;
hAbmAutoHard.IntValue = 0;
CreateTimer(0.2, Timer_SpawnBots, limit, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT);
}
ShowActivity(client, "made all bots heal %N", target);
wasSbFixEnabled = hSbFixEnabled.BoolValue;
hSbFixEnabled.BoolValue = false;
}
} else {
ReplyToCommand(client, "Usage: /healbots <player> [# of bots or 0 for all]");
}
return Plugin_Handled;
}

View file

@ -51,33 +51,40 @@ public Action Timer_CheckSpecial(Handle h, int specialID) {
int special = GetClientOfUserId(specialID);
// Check if new player is the spawned special:
if(spIsActive && special > 0 && IsFakeClient(special) && GetClientTeam(special) == 3) {
SpecialType type = view_as<SpecialType>(GetEntProp(special, Prop_Send, "m_zombieClass"));
if(type == spActiveRequest.type) {
// Ignore any fake clients with 'Bot' in name
static char buf[32];
GetClientName(special, buf, sizeof(buf));
if(StrContains(buf, "bot", false) == -1) {
if(spActiveRequest.targetUserId) {
g_iAttackerTarget[special] = spActiveRequest.targetUserId;
g_iSpecialAttackFlags[special] = spActiveRequest.flags;
}
TeleportEntity(special, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
if(spActiveRequest.flags & view_as<int>(SPI_KillOnSpawn)) {
if(type == Special_Spitter) {
float pos[3];
GetClientEyePosition(special, pos);
L4D2_SpitterPrj(special, pos, SPIT_VEL);
//g_iPendingSurvivorAdd
if(GetClientTeam(special) == 2 && g_iPendingSurvivorAdd && GetEntProp(special, Prop_Send, "m_humanSpectatorUserID") == 0) {
g_iPendingSurvivorAdd = false;
isCustomSurvivor[special] = true;
} else if(GetClientTeam(special) == 3) {
SpecialType type = view_as<SpecialType>(GetEntProp(special, Prop_Send, "m_zombieClass"));
if(type == spActiveRequest.type) {
// Ignore any fake clients with 'Bot' in name
static char buf[32];
GetClientName(special, buf, sizeof(buf));
if(StrContains(buf, "bot", false) == -1) {
if(spActiveRequest.targetUserId) {
g_iAttackerTarget[special] = spActiveRequest.targetUserId;
g_iSpecialAttackFlags[special] = spActiveRequest.flags;
}
RequestFrame(Frame_Boom, special);
TeleportEntity(special, spActiveRequest.position, spActiveRequest.angle, NULL_VECTOR);
if(spActiveRequest.flags & view_as<int>(SPI_KillOnSpawn)) {
if(type == Special_Spitter) {
float pos[3];
GetClientEyePosition(special, pos);
L4D2_SpitterPrj(special, pos, SPIT_VEL);
}
RequestFrame(Frame_Boom, special);
}
g_iSpId++;
ProcessSpecialQueue();
}
g_iSpId++;
ProcessSpecialQueue();
}
}
}
return Plugin_Handled;
}
public void Frame_Boom(int special) {
SDKHooks_TakeDamage(special, special, special, 1000.0);
@ -98,7 +105,8 @@ public void OnClientAuthorized(int client, const char[] auth) {
}
}
public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
int client = GetClientOfUserId(event.GetInt("userid"));
int userid = event.GetInt("userid");
int client = GetClientOfUserId(userid);
if(client > 0 && g_PendingBanTroll[client] > 0) {
if(!IsFakeClient(client) && GetUserAdmin(client) == INVALID_ADMIN_ID) {
BanIdentity(steamids[client], 0, BANFLAG_AUTHID, "Marked as Troll", "ftt", GetClientOfUserId(g_PendingBanTroll[client]));
@ -110,8 +118,13 @@ public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroa
shootAtTarget[client] = 0;
shootAtTargetLoops[client] = 0;
shootAtTargetHP[client] = 0;
isTargettingHealer[client] = false;
isCustomSurvivor[client] = false;
if(healTargetPlayer == userid) {
healTargetPlayer = 0;
}
}
public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) {
int userid = event.GetInt("userid");
int client = GetClientOfUserId(userid);
if(client > 0) {
@ -166,6 +179,7 @@ public void Event_CarAlarm(Event event, const char[] name, bool dontBroadcast) {
}
public Action RushPlayer(Handle h, int user) {
L4D2_RunScript("RushVictim(GetPlayerFromUserID(%d), %d)", user, 15000);
return Plugin_Handled;
}
public Action L4D2_OnChooseVictim(int attacker, int &curTarget) {
static int spMagnetID, tankMagnetID;
@ -269,10 +283,10 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
if(Trolls[honkID].IsActive(client) && Trolls[honkID].activeFlagClients[client] & 1) {
// Honk Processing
static char strings[32][7];
static char strings[32][8];
int words = ExplodeString(sArgs, " ", strings, sizeof(strings), 5);
for(int i = 0; i < words; i++) {
if(GetRandomFloat() <= 0.8) strings[i] = "honk";
if(GetRandomFloat() <= 0.8) strings[i] = "honk ";
else strings[i] = "squeak";
}
int length = 7 * words;
@ -306,7 +320,7 @@ public Action OnClientSayCommand(int client, const char[] command, const char[]
PrintToServer("%N: %s", client, sArgs);
return Plugin_Handled;
}else if(IsTrollActive(client, "iCantSpellNoMore")) {
int type = GetRandomInt(1, 13 + 5);
int type = GetRandomInt(1, 14 + 3);
char letterSrc, replaceChar;
switch(type) {
case 1: {
@ -513,6 +527,19 @@ public Action Event_ItemPickup(int client, int weapon) {
public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2]) {
// If 'KillMeSoftly' activated:
int healTarget = GetClientOfUserId(healTargetPlayer);
if(healTarget > 0 && isTargettingHealer[client] && healTarget != client) {
static float pos[3];
GetClientAbsOrigin(client, pos);
LookAtClient(client, healTarget);
if(GetVectorDistance(pos, healTargetPos, true) < 10000.0) {
if(GetClientAimTarget(client, true) == healTarget) {
buttons |= IN_ATTACK2;
return Plugin_Changed;
}
}
}
if(g_bPendingItemGive[client] && !(buttons & IN_ATTACK2)) {
int target = GetClientAimTarget(client, true);
if(target > -1) {
@ -570,9 +597,16 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3
public Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float& damage, int& damagetype) {
//Stop FF from marked:
static int reverseFF;
static int reverseFF, nerfGunIndex;
if(reverseFF == 0) reverseFF = GetTrollID("Reverse FF");
if(attacker > 0 && attacker <= MaxClients && GetClientTeam(attacker) == 4 && IsFakeClient(attacker)) return Plugin_Continue;
if(nerfGunIndex == 0) nerfGunIndex = GetTrollID("Nerf Gun");
if(attacker > 0 && attacker <= MaxClients) {
if(GetClientTeam(attacker) == 4 && IsFakeClient(attacker)) return Plugin_Continue;
else if(Trolls[nerfGunIndex].IsActive(attacker)) {
damage = 0.0;
return Plugin_Changed;
}
}
if(attacker > 0 && victim <= MaxClients && attacker <= MaxClients && IsClientInGame(attacker) && IsPlayerAlive(attacker)) {
if(shootAtTarget[attacker] == victim) return Plugin_Continue;
@ -630,7 +664,50 @@ public Action Event_TakeDamage(int victim, int& attacker, int& inflictor, float&
return Plugin_Continue;
}
public Action SoundHook(int[] clients, int& numClients, char sample[PLATFORM_MAX_PATH], int& entity, int& channel, float& volume, int& level, int& pitch, int& flags, char[] soundEntry, int& seed) {
public Action OnVocalizeCommand(int client, const char[] vocalize, int initiator) {
static int vocalGagID;
if(vocalGagID == 0) vocalGagID = GetTrollID("Vocalize Gag");
if(Trolls[vocalGagID].IsActive(client)) {
return Plugin_Handled;
}
return Plugin_Continue;
}
public void OnSceneStageChanged(int scene, SceneStages stage) {
if(stage == SceneStage_Spawned) {
static int vocalGagID, vocalizeSpecials;
if(vocalizeSpecials == 0) vocalizeSpecials = GetTrollID("Vocalize Specials");
int activator = GetSceneInitiator(scene);
if(activator > 0 && activator <= MaxClients) {
if(Trolls[vocalizeSpecials].IsActive(activator)) {
static char sceneFile[32];
GetSceneFile(scene, sceneFile, sizeof(sceneFile));
if(StrContains(sceneFile, "warnboomer") > -1) {
SpawnSpecialForTarget(Special_Boomer, activator, Special_OnTarget);
} else if(StrContains(sceneFile, "warnhunter") > -1) {
SpawnSpecialForTarget(Special_Hunter, activator, Special_OnTarget);
} else if(StrContains(sceneFile, "warnsmoker") > -1) {
SpawnSpecialForTarget(Special_Smoker, activator, Special_OnTarget);
} else if(StrContains(sceneFile, "warnspitter") > -1) {
SpawnSpecialForTarget(Special_Spitter, activator, Special_OnTarget);
} else if(StrContains(sceneFile, "warnjockey") > -1) {
SpawnSpecialForTarget(Special_Jockey, activator, Special_OnTarget);
} else if(StrContains(sceneFile, "warncharger") > -1) {
SpawnSpecialForTarget(Special_Charger, activator, Special_OnTarget);
}
if(Trolls[vocalizeSpecials].activeFlagClients[activator] & 1) {
CancelScene(scene);
}
} else if(Trolls[vocalGagID].IsActive(activator)) {
CancelScene(scene);
}
}
}
}
public Action SoundHook(int clients[MAXPLAYERS], int& numClients, char sample[PLATFORM_MAX_PATH], int& entity, int& channel, float& volume, int& level, int& pitch, int& flags, char soundEntry[PLATFORM_MAX_PATH], int& seed) {
static int honkID;
static int vocalGagID;
if(honkID == 0) honkID = GetTrollID("Honk / Meow");
@ -657,7 +734,9 @@ public Action SoundHook(int[] clients, int& numClients, char sample[PLATFORM_MAX
strcopy(sample, sizeof(sample), "player/footsteps/clown/concrete1.wav");
else if(Trolls[honkID].activeFlagClients[entity] & 2)
strcopy(sample, sizeof(sample), "custom/meow1.mp3");
else return Plugin_Changed;
else
return Plugin_Continue;
return Plugin_Changed;
} else if(Trolls[vocalGagID].IsActive(entity)) {
if(Trolls[vocalGagID].activeFlagClients[entity] & 2) {
clients[0] = entity;
@ -671,7 +750,7 @@ public Action SoundHook(int[] clients, int& numClients, char sample[PLATFORM_MAX
return Plugin_Continue;
}
public Action Event_WitchVictimSet(Event event, const char[] name, bool dontBroadcast) {
public void Event_WitchVictimSet(Event event, const char[] name, bool dontBroadcast) {
static int witchTrollID;
if(witchTrollID == 0) witchTrollID = GetTrollID("Witch Magnet");
@ -779,7 +858,7 @@ public Action L4D2_MeleeGetDamageForVictim(int client, int weapon, int victim, f
return Plugin_Continue;
}
int FindClosestVisibleClient(int source) {
stock int FindClosestVisibleClient(int source) {
static float pos[3], ang[3];
GetClientEyePosition(source, pos);
GetClientEyeAngles(source, ang);
@ -801,11 +880,12 @@ public Action OnAntiRush(int client, int &type, float distance) {
PrintToConsoleAll("[FTT] Spawning anti-rush special on %N (dist=%f) (special=%N)", client, distance, SPECIAL_NAMES[view_as<int>(special)-1]);
}
}
return Plugin_Continue;
}
public void L4D2_CInsectSwarm_CanHarm_Post(int acid, int spitter, int entity) {
if(entity <= MaxClients)
iLastInSpit[entity] = GetGameTime();
fLastInSpit[entity] = GetGameTime();
}
public void Event_EnteredSpit(Event event, const char[] name, bool dontBroadcast) {
@ -816,8 +896,11 @@ public void Event_EnteredSpit(Event event, const char[] name, bool dontBroadcast
else if(Trolls[stickyGooIndex].activeFlagClients[client] & 2) movement = 0.3;
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", movement);
iLastInSpit[client] = GetGameTime();
CreateTimer(0.2, Timer_CheckIsInSpit, GetClientUserId(client), TIMER_REPEAT);
fLastInSpit[client] = GetGameTime();
if(!hasSpitTimer[client]) {
CreateTimer(0.2, Timer_CheckIsInSpit, GetClientUserId(client), TIMER_REPEAT);
hasSpitTimer[client] = true;
}
}
}
@ -837,3 +920,11 @@ public void Event_BotPlayerSwap(Event event, const char[] name, bool dontBroadca
PrintToServer("[FTT] Re-applied trolls for was-idle player %N", client);
}
}
void Event_HealSuccess(Event event, const char[] name, bool dontBroadcast) {
int userid = event.GetInt("subject");
int client = GetClientOfUserId(userid);
if(client > 0 && userid == healTargetPlayer) {
StopHealingBots();
}
}

View file

@ -12,6 +12,7 @@ public int Insta_PlayerHandler(Menu menu, MenuAction action, int client, int par
ShowInstaSpecialChooser(client, userid, instaMode);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
void ShowInstaSpecialChooser(int activator, int userid, int instaMode) {
@ -72,6 +73,7 @@ public int ChooseMarkedTroll(Menu menu, MenuAction action, int activator, int pa
ToggleMarkPlayer(activator, target);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChoosePlayerHandler(Menu menu, MenuAction action, int param1, int param2) {
@ -84,12 +86,13 @@ public int ChoosePlayerHandler(Menu menu, MenuAction action, int param1, int par
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
return 0;
}
SetupCategoryMenu(param1, userid);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChoosePlayerHandlerForCombos(Menu menu, MenuAction action, int client, int param2) {
@ -101,12 +104,13 @@ public int ChoosePlayerHandlerForCombos(Menu menu, MenuAction action, int client
if(victim == 0) {
ReplyToCommand(victim, "FTT: Could not acquire player");
return;
return 0;
}
ShowTrollCombosMenu(client, userid);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChooseComboHandler(Menu menu, MenuAction action, int client, int param2) {
@ -121,7 +125,7 @@ public int ChooseComboHandler(Menu menu, MenuAction action, int client, int para
if(victim == 0) {
ReplyToCommand(client, "FTT: Could not acquire player");
return;
return 0;
}
static TrollCombo combo;
@ -129,6 +133,7 @@ public int ChooseComboHandler(Menu menu, MenuAction action, int client, int para
combo.Activate(client, victim);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
static int iMenuVictimID[MAXPLAYERS+1];
@ -144,7 +149,7 @@ public int ChooseCategoryHandler(Menu menu, MenuAction action, int param1, int p
int client = GetClientOfUserId(userid);
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
return 0;
}
iMenuVictimID[param1] = userid;
@ -153,12 +158,13 @@ public int ChooseCategoryHandler(Menu menu, MenuAction action, int param1, int p
// Reset troll:
if(category == -1) {
ApplyTroll(GetClientOfUserId(userid), "Reset User", param1, TrollMod_Instant);
return;
return 0;
}
ShowTrollsForCategory(param1, userid, category);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int param2) {
@ -178,7 +184,7 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
int client = GetClientOfUserId(userid);
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
return 0;
}
int keyIndex = StringToInt(str[1]);
@ -188,7 +194,7 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
if(StrEqual(troll.name, "Throw It All")) {
// Setup menu to call itself, but with an extra data point
ShowThrowItAllMenu(param1, userid);
} else if(troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
} else if(!troll.IsActive(client) && troll.HasMod(TrollMod_Instant) && troll.HasMod(TrollMod_Constant)) {
Menu modiferMenu = new Menu(ChooseTrollModiferHandler);
Format(info, sizeof(info), "%s: Choose Modifier", troll.name);
modiferMenu.SetTitle(info);
@ -203,7 +209,7 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
modiferMenu.ExitButton = true;
modiferMenu.Display(param1, 0);
} else if(troll.HasFlags() && !troll.IsActive(client)) {
ShowSelectFlagMenu(param1, userid, 0, troll);
ShowSelectFlagMenu(param1, userid, -1, troll);
} else {
troll.Activate(client, param1);
ShowTrollsForCategory(param1, userid, troll.categoryID);
@ -211,6 +217,7 @@ public int ChooseModeMenuHandler(Menu menu, MenuAction action, int param1, int p
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int param2) {
@ -224,7 +231,7 @@ public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int
int slot = StringToInt(str[1]);
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
return 0;
}else if(slot == -1) {
for(int i = 0; i <= 4; i++) {
ThrowItemToPlayer(client, param1, i);
@ -238,6 +245,7 @@ public int ChooseClumsySlotHandler(Menu menu, MenuAction action, int param1, int
ShowThrowItAllMenu(param1, userid);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, int param2) {
@ -253,7 +261,7 @@ public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, i
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
return 0;
}
static Troll troll;
@ -272,6 +280,7 @@ public int ChooseTrollModiferHandler(Menu menu, MenuAction action, int param1, i
} else if (action == MenuAction_End)
delete menu;
return 0;
}
public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int param2) {
@ -290,13 +299,12 @@ public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int
if(client == 0) {
ReplyToCommand(param1, "FTT: Could not acquire player");
return;
return 0;
}
static Troll troll;
GetTrollByKeyIndex(keyIndex, troll);
static TrollFlagPrompt prompt;
// If told to go to next prompt, find the next VALID prompt
// Valid prompt is one where the required flags for it, are active
@ -305,12 +313,12 @@ public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int
// If there is a prompt available, show it, else fall down
if(nextIndex != -1) {
ShowSelectFlagMenu(param1, userid, modifiers, troll, flags, nextIndex);
return;
return 0;
}
// else fall through & apply
} else {
ShowSelectFlagMenu(param1, userid, modifiers, troll, flags, index);
return;
return 0;
}
// Done with prompts, apply flags & modifiers
@ -326,6 +334,7 @@ public int ChooseTrollFlagHandler(Menu menu, MenuAction action, int param1, int
ShowTrollsForCategory(param1, userid, troll.categoryID);
} else if (action == MenuAction_End)
delete menu;
return 0;
}
@ -428,7 +437,7 @@ 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 = 0, int promptIndex = 0) {
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];
@ -442,7 +451,7 @@ void ShowSelectFlagMenu(int activator, int victimUserID, int modifiers, Troll tr
flagMenu.SetTitle(info);
if(prompt.multiselect) {
if(prevFlags == 0) prevFlags = prompt.defaults;
if(prevFlags == -1) prevFlags = prompt.defaults;
Format(info, sizeof(info), "%d|%d|%d|%d|%d|1", victimUserID, troll.id, modifiers, prevFlags, promptIndex);
flagMenu.AddItem(info, "Apply / Next Prompt");
@ -461,6 +470,7 @@ void ShowSelectFlagMenu(int activator, int victimUserID, int modifiers, Troll tr
}
} 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) {

View file

@ -4,15 +4,15 @@
void ActivateAutoPunish(int client) {
if(hAutoPunish.IntValue & 2 == 2)
ApplyTroll(lastButtonUser, "Special Magnet", 0, TrollMod_Constant);
ApplyTroll(client, "Special Magnet", 0, TrollMod_Constant);
if(hAutoPunish.IntValue & 1 == 1)
ApplyTroll(lastButtonUser, "Tank Magnet", 0, TrollMod_Constant);
ApplyTroll(client, "Tank Magnet", 0, TrollMod_Constant);
if(hAutoPunish.IntValue & 8 == 8)
ApplyTroll(lastButtonUser, "Vomit Player", 0, TrollMod_Instant);
ApplyTroll(client, "Vomit Player", 0, TrollMod_Instant);
else if(hAutoPunish.IntValue & 4 == 4)
ApplyTroll(lastButtonUser, "Swarm", 0, TrollMod_Instant);
ApplyTroll(client, "Swarm", 0, TrollMod_Instant);
if(hAutoPunishExpire.IntValue > 0) {
CreateTimer(60.0 * hAutoPunishExpire.FloatValue, Timer_ResetAutoPunish, GetClientOfUserId(lastButtonUser));
CreateTimer(60.0 * hAutoPunishExpire.FloatValue, Timer_ResetAutoPunish, GetClientOfUserId(client));
}
}
@ -137,7 +137,7 @@ ArrayList GetPhrasesArray(const char[] key) {
}
int FindClosestClientAdminPriority(int source, bool ignoreBots, float pos[3]) {
stock 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;
@ -170,7 +170,10 @@ int FindClosestAdmin(int source, bool ignoreBots, float pos[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) {
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) {
@ -221,34 +224,6 @@ void ThrowItemToPlayer(int victim, int target, int slot) {
}
}
void ThrowItemToClosestPlayer(int victim, int slot) {
int wpn = GetPlayerWeaponSlot(victim, slot);
if(wpn > 0 && (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);
}
}
stock void AddInFrontOf(float fVecOrigin[3], float fVecAngle[3], float fUnits, float fOutPut[3])
{
@ -450,4 +425,51 @@ bool SpawnCarToPlayer(int target, float distance) {
int id = CreateProp("prop_physics", MODEL_CAR, endPos, ang, vel);
CreateTimer(6.0, Timer_Delete, id);
return true;
}
bool g_iPendingSurvivorAdd;
int isCustomSurvivor[MAXPLAYERS+1];
bool AddSurvivor() {
if (GetClientCount(false) >= MaxClients - 1) {
return false;
}
int i = CreateFakeClient("GuessWhoBot");
bool result;
if (i > 0) {
if (DispatchKeyValue(i, "classname", "SurvivorBot")) {
ChangeClientTeam(i, 2);
if (DispatchSpawn(i)) {
result = true;
}
}
g_iPendingSurvivorAdd = true;
CreateTimer(0.2, Timer_KickBot, i);
}
return result;
}
void ClearInventory(int client) {
for(int i = 0; i <= 5; i++) {
int item = GetPlayerWeaponSlot(client, i);
if(item > 0) {
AcceptEntityInput(item, "Kill");
}
}
}
void StopHealingBots() {
healTargetPlayer = 0;
for(int i = 1; i <= MaxClients; i++) {
isTargettingHealer[i] = false;
if(isCustomSurvivor[i]) {
ClearInventory(i);
KickClient(i);
}
}
hAbmAutoHard.IntValue = wasAbmAutoHard;
hSbFixEnabled.BoolValue = wasSbFixEnabled;
}

View file

@ -9,18 +9,24 @@ public Action Timer_ThrowTimer(Handle timer) {
}
return count > 0 ? Plugin_Continue : Plugin_Stop;
}
int instantCommonRef[MAXPLAYERS+1];
public Action Timer_Main(Handle timer) {
static int loopTick;
static int slowDrainIndex;
if(!slowDrainIndex) slowDrainIndex = GetTrollID("Slow Drain");
static int tempHealthQuickDrainIndex;
if(!tempHealthQuickDrainIndex) tempHealthQuickDrainIndex = GetTrollID("Temp Health Quick Drain");
static int swarmIndex;
if(!swarmIndex) swarmIndex = GetTrollID("Swarm");
static int instantCommonIndex;
if(!instantCommonIndex) instantCommonIndex = GetTrollID("Instant Commons");
static int randomizeAmmoIndex;
if(!randomizeAmmoIndex) randomizeAmmoIndex = GetTrollID("Randomize Clip Ammo");
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i)) {
if(IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2) {
if(Trolls[slowDrainIndex].IsActive(i)) {
if(loopTick % 4 == 0) {
int hp = GetClientHealth(i);
@ -31,11 +37,8 @@ public Action Timer_Main(Handle timer) {
}else if(Trolls[tempHealthQuickDrainIndex].IsActive(i)) {
if(loopTick % 2 == 0) {
float bufferTime = GetEntPropFloat(i, Prop_Send, "m_healthBufferTime");
float buffer = GetEntPropFloat(i, Prop_Send, "m_healthBuffer");
float tempHealth = GetTempHealth(i);
float tempHealth = L4D_GetTempHealth(i);
if(tempHealth > 0.0) {
PrintToConsole(i, "%f | %f %f", tempHealth, buffer, bufferTime);
//SetEntPropFloat(i, Prop_Send, "m_healthBuffer", buffer - 10.0);
SetEntPropFloat(i, Prop_Send, "m_healthBufferTime", bufferTime - 7.0);
}
}
@ -45,6 +48,22 @@ public Action Timer_Main(Handle timer) {
if(GetRandomFloat() <= 0.4) {
L4D_StaggerPlayer(i, i, NULL_VECTOR);
}
} else if(Trolls[instantCommonIndex].IsActive(i)) {
int common = EntRefToEntIndex(instantCommonRef[i]);
if(common <= 0 || !IsValidEntity(common)) {
static float pos[3];
GetHorizontalPositionFromClient(i, Trolls[instantCommonIndex].activeFlagClients[i] & 1 ? -40.0 : 40.0, pos);
common = L4D_SpawnCommonInfected(pos);
instantCommonRef[i] = EntIndexToEntRef(common);
}
SetEntPropEnt(common, Prop_Send, "m_clientLookatTarget", i);
SetEntProp(common, Prop_Send, "m_nSequence", 96);
} else if(loopTick % 60 && Trolls[randomizeAmmoIndex].IsActive(i)) {
int primaryWpn = GetPlayerWeaponSlot(i, 0);
if(primaryWpn > 0) {
int maxCap = GetEntProp(primaryWpn, Prop_Send, "m_iClip1");
SetEntProp(primaryWpn, Prop_Send, "m_iClip", GetRandomInt(0, maxCap));
}
}
}
}
@ -62,6 +81,7 @@ public Action Timer_GivePistol(Handle timer, int user) {
FakeClientCommand(client, "give pistol");
SetCommandFlags("give", flags);
}
return Plugin_Handled;
}
public Action Timer_ThrowWeapon(Handle timer, Handle pack) {
@ -88,6 +108,7 @@ public Action Timer_ThrowWeapon(Handle timer, Handle pack) {
SDKHooks_DropWeapon(victim, wpn, dest);
}
}
return Plugin_Handled;
}
public Action Timer_ResetAutoPunish(Handle timer, int user) {
@ -98,6 +119,7 @@ public Action Timer_ResetAutoPunish(Handle timer, int user) {
if(hAutoPunish.IntValue & 1 == 1)
DisableTroll(client, "Tank Magnet");
}
return Plugin_Handled;
}
public Action Timer_NextWitchSet(Handle timer, DataPack pack) {
@ -105,16 +127,19 @@ public Action Timer_NextWitchSet(Handle timer, DataPack pack) {
int client = GetClientOfUserId(pack.ReadCell());
int witch = pack.ReadCell();
SetWitchTarget(witch, client);
return Plugin_Handled;
}
public Action Timer_KickBot(Handle timer, int client) {
if(IsClientInGame(client) && (!IsClientInKickQueue(client))) {
if(IsFakeClient(client)) KickClient(client);
}
return Plugin_Handled;
}
public Action Timer_Delete(Handle h, int id) {
AcceptEntityInput(id, "Kill");
return Plugin_Handled;
}
public Action Timer_ShootReverse(Handle h, DataPack pack) {
@ -152,12 +177,14 @@ public Action Timer_CheckSpecialSpawned(Handle h, int id) {
g_iSpId++;
ProcessSpecialQueue();
}
return Plugin_Handled;
}
public Action Timer_CheckIsInSpit(Handle h, int userid) {
int client = GetClientOfUserId(userid);
if(client && GetGameTime() - iLastInSpit[userid] > 3.0) {
if(client && GetGameTime() - fLastInSpit[userid] > 3.0) {
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.0);
hasSpitTimer[client] = false;
return Plugin_Stop;
}
return Plugin_Continue;
@ -204,4 +231,53 @@ public Action Timer_CheckForChargerOpportunity(Handle h, int userid) {
public bool Filter_CheckChargerValid(int entity, int contentsMask, any data) {
return entity <= 0 || entity >= MaxClients || (entity != data && GetClientTeam(entity) == 2);
}
public Action Timer_UpdateHealTargetPos(Handle h) {
int healTarget = GetClientOfUserId(healTargetPlayer);
if(healTarget == 0) {
PrintToServer("[FTT] Lost heal target, stopping");
return Plugin_Stop;
}
GetAbsOrigin(healTarget, healTargetPos);
int bots = 0;
for(int i = 1; i <= MaxClients; i++) {
if(IsClientConnected(i) && IsFakeClient(i) && isTargettingHealer[i]) {
bots++;
L4D2_RunScript("CommandABot({cmd=1,bot=GetPlayerFromUserID(%d),pos=Vector(%f,%f,%f)})", GetClientUserId(i), healTargetPos[0], healTargetPos[1], healTargetPos[2]);
int kit = GetPlayerWeaponSlot(i, 3);
if(kit > -1) {
SetEntPropEnt(i, Prop_Send, "m_hActiveWeapon", kit);
}
}
}
return bots > 0 ? Plugin_Continue : Plugin_Stop;
}
Action Timer_SpawnBots(Handle h, int max) {
static int count;
if(count < max) {
if(!AddSurvivor()) return Plugin_Stop;
count++;
return Plugin_Continue;
}
count = 0;
CreateTimer(0.2, Timer_SpawnBotsPost);
return Plugin_Stop;
}
Action Timer_SpawnBotsPost(Handle h) {
char classname[32];
for(int i = 1; i <= MaxClients; i++) {
if(isCustomSurvivor[i]) {
int kit = GetPlayerWeaponSlot(i, 3);
if(kit > 0) {
GetEntityClassname(kit, classname, sizeof(classname));
if(!StrEqual(classname, "weapon_first_aid_kit")) {
kit = GiveClientWeapon(i, "weapon_first_aid_kit");
}
isTargettingHealer[i] = true;
}
}
}
}

View file

@ -6,285 +6,302 @@ int invertedTrollIndex;
// int fireSpitMagnetTrollIndex;
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);
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);
/// CATEGORY: Magnets
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);
index = SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant);
// fireSpitMagnetTrollIndex = SetupTroll("Fire & Acid Magnet", "Make the player gravitate toward danger", TRollMod_Constant);
/// CATEGORY: Magnets
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);
index = SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant);
// fireSpitMagnetTrollIndex = SetupTroll("Fire & Acid Magnet", "Make the player gravitate toward danger", TRollMod_Constant);
/// CATEGORY: Infected
SetCategory("Infected");
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
SetupTroll("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant);
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
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("60% Movement Speed", true);
Trolls[index].AddFlag("30% Movement Speed", false);
Trolls[index].AddFlag("0% Movement Speed", false);
stickyGooIndex = index;
SetupTroll("Instant Commons", "Spawns commons behind or infront", TrollMod_Instant);
/// CATEGORY: Infected
SetCategory("Infected");
SetupTroll("Swarm", "Swarms a player with zombies. Requires swarm plugin", TrollMod_Instant | TrollMod_Constant);
SetupTroll("Vomit Player", "Shortcut to sm_vomitplayer. vomits the player.", TrollMod_Instant);
SetupTroll("Inface Special", "Shortcut to sm_inface", TrollMod_Instant);
SetupTroll("Insta Special", "Shortcut to sm_insta", TrollMod_Instant);
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("60% Movement Speed", true);
Trolls[index].AddFlag("30% Movement Speed", false);
Trolls[index].AddFlag("0% Movement Speed", false);
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);
// CATEGORY: Items
SetCategory("Items");
index = SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
//Can't add directly, is custom troll:
// Trolls[index].AddFlag("Throw to Admin", true);
// Trolls[index].AddFlag("Drop At Feet", false);
// Trolls[index].AddFlag("Drop At Admin", 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("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("Half Primary Ammo", "Cuts their primary reserve ammo in half", TrollMod_Instant);
/// CATEGORY: Chat
SetCategory("Chat");
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", "Honk or Meow", TrollMod_Constant);
Trolls[index].AddCustomFlagPrompt("Choose Sound Type:");
Trolls[index].AddFlag("Honk", true);
Trolls[index].AddFlag("Meow", 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);
// CATEGORY: Items
SetCategory("Items");
index = SetupTroll("Throw It All", "Player throws their item(s) periodically to a nearby player", TrollMod_Instant);
//Can't add directly, is custom troll:
// Trolls[index].AddFlag("Throw to Admin", true);
// Trolls[index].AddFlag("Drop At Feet", false);
// Trolls[index].AddFlag("Drop At Admin", 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("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);
/// CATEGORY: Health
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);
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].AddFlag("-2x Ratio", false); //16
/// CATEGORY: Chat
SetCategory("Chat");
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", "Honk or Meow", TrollMod_Constant);
Trolls[index].AddCustomFlagPrompt("Choose Sound:");
Trolls[index].AddFlag("Honk", true);
Trolls[index].AddFlag("Meow", 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);
/// 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("60% Movement Speed", true);
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);
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);
slipperyShoesIndex = index;
/// CATEGORY: Health
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);
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].AddFlag("-2x Ratio", false); //16
/// 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);
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
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("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);
/// 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("60% Movement Speed", true);
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);
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);
slipperyShoesIndex = index;
/// 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("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);
SetupTroll("CameTooEarly", "When they shoot, random chance they empty whole clip", TrollMod_Constant);
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);
// Initialize the default flag values to -1
for(int i = 0; i <= MAX_TROLLS; i++) {
for(int j = 1; j <= MAXPLAYERS; j++) {
Trolls[i].activeFlagClients[j] = -1;
}
}
// Initialize the default flag values to -1
for(int i = 0; i <= MAX_TROLLS; i++) {
for(int j = 1; j <= MAXPLAYERS; j++) {
Trolls[i].activeFlagClients[j] = -1;
}
}
}
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);
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);
}
bool ApplyAffect(int victim, const Troll troll, int activator, trollModifier modifier, int flags) {
bool toActive = IsTrollActiveByRawID(victim, troll.id);
if(StrEqual(troll.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++) {
Trolls[i].activeFlagClients[victim] = -1;
}
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
SetEntityGravity(victim, 1.0);
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
return false;
} else if(StrEqual(troll.name, "Slow Speed")) {
if(toActive) {
float movement = 0.0;
if(flags & 1) movement = 0.6;
else if(flags & 2) movement = 0.3;
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", movement);
} else
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
} else if(StrEqual(troll.name, "Higher Gravity"))
SetEntityGravity(victim, toActive ? 1.3 : 1.0);
else if(StrEqual(troll.name, "Half Primary Ammo")) {
int current = GetPrimaryReserveAmmo(victim);
SetPrimaryReserveAmmo(victim, current / 2);
} else if(StrEqual(troll.name, "UziRules / AwpSmells")) {
DisableTroll(victim, "No Pickup");
DisableTroll(victim, "Primary Disable");
} else if(StrEqual(troll.name, "Primary Disable")) {
DisableTroll(victim, "UziRules / AwpSmells");
DisableTroll(victim, "No Pickup");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(troll.name, "No Pickup")) {
DisableTroll(victim, "UziRules / AwpSmells");
DisableTroll(victim, "Primary Disable");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(troll.name, "CameTooEarly")) {
ReplyToCommand(activator, "This troll mode is not implemented.");
} else if(StrEqual(troll.name, "KillMeSoftly")) {
static char wpn[32];
GetClientWeaponName(victim, 4, wpn, sizeof(wpn));
if(StrEqual(wpn, "weapon_adrenaline") || StrEqual(wpn, "weapon_pain_pills")) {
ClientCommand(victim, "slot5");
g_bPendingItemGive[victim] = true;
}else{
ReplyToCommand(activator, "User does not have pills or adrenaline");
return false;
}
//TODO: Implement TrollMod_Constant
return false;
} else if(StrEqual(troll.name, "Throw It All")) {
if(modifier & TrollMod_Instant)
ThrowAllItems(victim);
if(hThrowTimer == INVALID_HANDLE && modifier & TrollMod_Constant) {
hThrowTimer = CreateTimer(hThrowItemInterval.FloatValue, Timer_ThrowTimer, _, TIMER_REPEAT);
}
} else if(StrEqual(troll.name, "Swarm")) {
if(modifier & TrollMod_Instant) {
L4D2_RunScript("RushVictim(GetPlayerFromUserID(%d), %d)", victim, 15000);
}
return true;
} else if(StrEqual(troll.name, "Gun Jam")) {
int wpn = GetClientWeaponEntIndex(victim, 0);
if(wpn > -1)
SDKHook(wpn, SDKHook_Reload, Event_WeaponReload);
else {
ReplyToCommand(activator, "Victim does not have a primary weapon.");
return false;
}
} else if(StrEqual(troll.name, "Vomit Player"))
L4D_CTerrorPlayer_OnVomitedUpon(victim, victim);
else if(StrEqual(troll.name, "Inface Special")) {
FakeClientCommand(activator, "sm_inface");
return false;
} else if(StrEqual(troll.name, "Insta Special")) {
FakeClientCommand(activator, "sm_insta");
return false;
} else if(StrEqual(troll.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")) {
L4D_StaggerPlayer(victim, victim, NULL_VECTOR);
} else if(StrEqual(troll.name, "Voice Mute")) {
BaseComm_SetClientMute(victim, toActive);
} else if(StrEqual(troll.name, "Spicy Gas")) {
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(troll.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.");
return false;
}
} else if(flags & 2) {
if(!SpawnCarToPlayer(victim, 450.0)) {
ReplyToCommand(activator, "Could not find a suitable area to spawn a car. Requires space ahead of victim");
return false;
}
} else if(flags & 4) {
if(!SpawnCarToPlayer(victim, -450.0)) {
ReplyToCommand(activator, "Could not find a suitable area to spawn a car. Requires space behind victim");
return false;
}
}
} else if(StrEqual(troll.name, "Instant Commons")) {
float pos[3];
GetHorizontalPositionFromClient(victim, -40.0, pos);
for(int i = 0; i < 30; i++) {
L4D_SpawnCommonInfected(pos);
}
CreateTimer(0.1, RushPlayer, victim);
} else if(modifier != TrollMod_Constant) {
PrintToServer("[FTT] Warn: Possibly invalid troll, no apply action defined for \"%s\"", troll.name);
#if defined DEBUG
ReplyToCommand(activator, "[FTT/Debug] If nothing occurs, this troll possibly was not implemented correctly. ");
#endif
}
return true;
}
bool toActive = IsTrollActiveByRawID(victim, troll.id);
if(StrEqual(troll.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++) {
Trolls[i].activeFlagClients[victim] = -1;
}
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
SetEntityGravity(victim, 1.0);
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
return false;
} else if(StrEqual(troll.name, "Slow Speed")) {
if(toActive) {
float movement = 0.0;
if(flags & 1) movement = 0.6;
else if(flags & 2) movement = 0.3;
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", movement);
} else
SetEntPropFloat(victim, Prop_Send, "m_flLaggedMovementValue", 1.0);
} else if(StrEqual(troll.name, "Higher Gravity"))
SetEntityGravity(victim, toActive ? 1.3 : 1.0);
else if(StrEqual(troll.name, "UziRules / AwpSmells")) {
DisableTroll(victim, "No Pickup");
DisableTroll(victim, "Primary Disable");
} else if(StrEqual(troll.name, "Primary Disable")) {
DisableTroll(victim, "UziRules / AwpSmells");
DisableTroll(victim, "No Pickup");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(troll.name, "No Pickup")) {
DisableTroll(victim, "UziRules / AwpSmells");
DisableTroll(victim, "Primary Disable");
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(troll.name, "CameTooEarly")) {
ReplyToCommand(activator, "This troll mode is not implemented.");
} else if(StrEqual(troll.name, "KillMeSoftly")) {
static char wpn[32];
GetClientWeaponName(victim, 4, wpn, sizeof(wpn));
if(StrEqual(wpn, "weapon_adrenaline") || StrEqual(wpn, "weapon_pain_pills")) {
ClientCommand(victim, "slot5");
g_bPendingItemGive[victim] = true;
}else{
ReplyToCommand(activator, "User does not have pills or adrenaline");
return false;
}
//TODO: Implement TrollMod_Constant
return false;
} else if(StrEqual(troll.name, "Throw It All")) {
if(modifier & TrollMod_Instant)
ThrowAllItems(victim);
if(hThrowTimer == INVALID_HANDLE && modifier & TrollMod_Constant) {
hThrowTimer = CreateTimer(hThrowItemInterval.FloatValue, Timer_ThrowTimer, _, TIMER_REPEAT);
}
} else if(StrEqual(troll.name, "Swarm")) {
if(modifier & TrollMod_Instant) {
L4D2_RunScript("RushVictim(GetPlayerFromUserID(%d), %d)", victim, 15000);
}
return true;
} else if(StrEqual(troll.name, "Gun Jam")) {
int wpn = GetClientWeaponEntIndex(victim, 0);
if(wpn > -1)
SDKHook(wpn, SDKHook_Reload, Event_WeaponReload);
else {
ReplyToCommand(activator, "Victim does not have a primary weapon.");
return false;
}
} else if(StrEqual(troll.name, "Vomit Player"))
L4D_CTerrorPlayer_OnVomitedUpon(victim, victim);
else if(StrEqual(troll.name, "Inface Special")) {
ShowInstaSpecialChooser(activator, GetClientUserId(victim), 1);
return false;
} else if(StrEqual(troll.name, "Insta Special")) {
ShowInstaSpecialChooser(activator, GetClientUserId(victim), 0);
return false;
} else if(StrEqual(troll.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")) {
L4D_StaggerPlayer(victim, victim, NULL_VECTOR);
} else if(StrEqual(troll.name, "Voice Mute")) {
BaseComm_SetClientMute(victim, toActive);
} else if(StrEqual(troll.name, "Spicy Gas")) {
SDKHook(victim, SDKHook_WeaponCanUse, Event_ItemPickup);
} else if(StrEqual(troll.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.");
return false;
}
} else if(flags & 2) {
if(!SpawnCarToPlayer(victim, 450.0)) {
ReplyToCommand(activator, "Could not find a suitable area to spawn a car. Requires space ahead of victim");
return false;
}
} else if(flags & 4) {
if(!SpawnCarToPlayer(victim, -450.0)) {
ReplyToCommand(activator, "Could not find a suitable area to spawn a car. Requires space behind victim");
return false;
}
}
} else if(StrEqual(troll.name, "Instant Commons")) {
if(modifier & TrollMod_Instant) {
float pos[3];
GetHorizontalPositionFromClient(victim, flags & 1 ? -40.0 : 40.0, pos);
int victimId = GetClientUserId(victim);
for(int i = 0; i < 30; i++) {
int c = L4D_SpawnCommonInfected(pos);
L4D2_RunScript("CommandABot({cmd=0,bot=EntIndexToHScript(%i),target=GetPlayerFromUserID(%i)})", c, victimId);
SetEntPropEnt(c, Prop_Send, "m_hTargetEntity", victim);
}
}
} else if(StrEqual(troll.name, "Randomize Clip Ammo")) {
if(modifier & TrollMod_Instant) {
int primaryWpn = GetPlayerWeaponSlot(victim, 0);
if(primaryWpn > 0) {
int maxCap = GetEntProp(primaryWpn, Prop_Send, "m_iClip1");
SetEntProp(primaryWpn, Prop_Send, "m_iClip", GetRandomInt(0, maxCap));
}
}
} else if(~modifier & TrollMod_Constant) {
PrintToServer("[FTT] Warn: Possibly invalid troll, no apply action defined for \"%s\"", troll.name);
#if defined DEBUG
ReplyToCommand(activator, "[FTT/Debug] If nothing occurs, this troll possibly was not implemented correctly. ");
#endif
}
return true;
}

View file

@ -15,7 +15,6 @@ GlobalForward g_PlayerMarkedForward;
Handle g_hWitchAttack;
Handle hThrowTimer;
ConVar hVictimsList;
ConVar hThrowItemInterval;
ConVar hAutoPunish;
ConVar hMagnetChance;
@ -30,15 +29,13 @@ ConVar hBotDefendChance;
bool g_bPendingItemGive[MAXPLAYERS+1];
int g_iAmmoTable; //Loads the ammo table to get max ammo for weapons
int autoPunished = -1;
int autoPunishMode;
int lastButtonUser;
int lastCrescendoUser;
int g_iAttackerTarget[MAXPLAYERS+1];
int g_iSpecialAttackFlags[MAXPLAYERS+1];
int g_PendingBanTroll[MAXPLAYERS+1];
float iLastInSpit[MAXPLAYERS+1];
float fLastInSpit[MAXPLAYERS+1];
bool hasSpitTimer[MAXPLAYERS+1];
char steamids[MAXPLAYERS+1][64];
@ -61,6 +58,16 @@ enum SpecialInternalFlags {
SPI_AlwaysTarget = 2
}
int healTargetPlayer;
bool isTargettingHealer[MAXPLAYERS+1];
float healTargetPos[3];
bool wasSbFixEnabled;
ConVar hSbFixEnabled;
ConVar hAbmAutoHard;
int wasAbmAutoHard;
#define MODEL_CAR "models/props_vehicles/cara_95sedan.mdl"
#include <feedthetrolls/base>

View file

@ -29,6 +29,7 @@ public Plugin myinfo =
url = ""
};
//TODO: Trolls: Force take pills, Survivor Bot Magnet
@ -72,16 +73,18 @@ public void OnPluginStart() {
hBotDefendChance = CreateConVar("sm_ftt_bot_defend_chance", "0.75", "% Chance bots will defend themselves.", FCVAR_NONE, true, 0.0, true, 1.0);
hSbFriendlyFire = FindConVar("sb_friendlyfire");
hSbFixEnabled = FindConVar("sb_fix_enabled");
hAbmAutoHard = FindConVar("abm_autohard");
if(hBotReverseFFDefend.IntValue > 0) hSbFriendlyFire.BoolValue = true;
hBotReverseFFDefend.AddChangeHook(Change_BotDefend);
RegAdminCmd("sm_ftl", Command_ListTheTrolls, ADMFLAG_KICK, "Lists all the trolls currently ingame.");
RegAdminCmd("sm_ftl", Command_ListTheTrolls, ADMFLAG_GENERIC, "Lists all the trolls currently ingame.");
RegAdminCmd("sm_ftm", Command_ListModes, ADMFLAG_KICK, "Lists all the troll modes and their description");
RegAdminCmd("sm_ftr", Command_ResetUser, ADMFLAG_KICK, "Resets user of any troll effects.");
RegAdminCmd("sm_ftr", Command_ResetUser, ADMFLAG_GENERIC, "Resets user of any troll effects.");
RegAdminCmd("sm_fta", Command_ApplyUser, ADMFLAG_KICK, "Apply a troll mod to a player, or shows menu if no parameters.");
RegAdminCmd("sm_ftas", Command_ApplyUserSilent, ADMFLAG_CHEATS, "Apply a troll mod to a player, or shows menu if no parameters.");
RegAdminCmd("sm_ftt", Command_FeedTheTrollMenu, ADMFLAG_KICK, "Opens a list that shows all the commands");
RegAdminCmd("sm_ftas", Command_ApplyUserSilent, ADMFLAG_ROOT, "Apply a troll mod to a player, or shows menu if no parameters.");
RegAdminCmd("sm_ftt", Command_FeedTheTrollMenu, ADMFLAG_GENERIC, "Opens a list that shows all the commands");
RegAdminCmd("sm_mark", Command_MarkPendingTroll, ADMFLAG_KICK, "Marks a player as to be banned on disconnect");
RegAdminCmd("sm_ftp", Command_FeedTheCrescendoTroll, ADMFLAG_KICK, "Applies a manual punish on the last crescendo activator");
RegAdminCmd("sm_ftc", Command_ApplyComboTrolls, ADMFLAG_KICK, "Applies predefined combinations of trolls");
@ -92,6 +95,7 @@ public void OnPluginStart() {
RegAdminCmd("sm_inface", Command_InstaSpecialFace, ADMFLAG_KICK, "Spawns a special that targets them, right in their face.");
RegAdminCmd("sm_bots_attack", Command_BotsAttack, ADMFLAG_CHEATS, "Instructs all bots to attack a player until they have X health.");
RegAdminCmd("sm_scharge", Command_SmartCharge, ADMFLAG_CHEATS, "Auto Smart charge");
RegAdminCmd("sm_healbots", Command_HealTarget, ADMFLAG_CHEATS, "Make bots heal a player");
HookEvent("player_spawn", Event_PlayerSpawn);
HookEvent("player_disconnect", Event_PlayerDisconnect);
@ -105,8 +109,9 @@ public void OnPluginStart() {
HookEvent("pills_used", Event_SecondaryHealthUsed);
HookEvent("entered_spit", Event_EnteredSpit);
HookEvent("bot_player_replace", Event_BotPlayerSwap);
HookEvent("heal_success", Event_HealSuccess);
AddNormalSoundHook(view_as<NormalSHook>(SoundHook));
AddNormalSoundHook(SoundHook);
AutoExecConfig(true, "l4d2_feedthetrolls");
@ -195,40 +200,3 @@ bool IsPlayerFarDistance(int client, float distance) {
PrintToConsoleAll("Flow Check | Player2=%N Flow2=%f", secondClient, secondHighestFlow);
return client == farthestClient && difference > distance;
}
stock int GetPrimaryReserveAmmo(int client) {
int weapon = GetPlayerWeaponSlot(client, 0);
if(weapon > 0) {
return GetEntProp(client, Prop_Send, "m_iAmmo", _, GetEntProp(weapon, Prop_Send, "m_iPrimaryAmmoType"));
}
return -1;
}
stock bool SetPrimaryReserveAmmo(int client, int amount) {
int weapon = GetPlayerWeaponSlot(client, 0);
if(weapon > -1) {
SetEntProp(client, Prop_Send, "m_iAmmo", amount, _, GetEntProp(weapon, Prop_Send, "m_iPrimaryAmmoType"));
}
return false;
}
stock void SendChatToAll(int client, const char[] message) {
static char nameBuf[MAX_NAME_LENGTH];
for (int i = 1; i <= MaxClients; i++) {
if (IsClientInGame(i) && IsFakeClient(i)) {
FormatActivitySource(client, i, nameBuf, sizeof(nameBuf));
PrintToChat(i, "\x03 %s : \x01%s", nameBuf, message);
}
}
}
stock float GetTempHealth(int client) {
if(client <= 0 || !IsValidEntity(client) || !IsClientInGame(client)|| !IsPlayerAlive(client) || IsClientObserver(client)) return -1.0;
if(GetClientTeam(client) != 2) return 0.0;
float buffer = GetEntPropFloat(client, Prop_Send, "m_healthBuffer");
if(buffer <= 0.0) return 0.0;
float difference = GetGameTime() - GetEntPropFloat(client, Prop_Send, "m_healthBufferTime");
float decay = FindConVar("pain_pills_decay_rate").FloatValue;
return buffer - (difference / (1.0 / decay));
}