diff --git a/gamedata/feedthetrolls.txt b/gamedata/feedthetrolls.txt new file mode 100644 index 0000000..e9c3305 --- /dev/null +++ b/gamedata/feedthetrolls.txt @@ -0,0 +1,16 @@ +"Games" +{ + "left4dead2" + { + "Signatures" + { + "WitchAttack::WitchAttack" + { + /* 55 8B EC 53 56 8B F1 C7 46 04 ? ? ? ? C7 46 2C 01 00 00 00 33 DB 33 C0 89 46 20 33 C9 89 4E 24 57 33 D2 89 56 28 33 FF 89 5E 0C 89 5E 10 89 5E 14 89 5E 18 89 5E 1C 89 5E 08 66 89 5E 30 89 7E 2C C7 06 ? ? ? ? C7 46 04 ? ? ? ? 53 */ + + "windows" "\x55\x8B\xEC\x53\x56\x8B\xF1\xC7\x46\x04\x2A\x2A\x2A\x2A\xC7\x46\x2C\x01\x00\x00\x00\x33\xDB\x33\xC0\x89\x46\x20\x33\xC9\x89\x4E\x24\x57\x33\xD2\x89\x56\x28\x33\xFF\x89\x5E\x0C\x89\x5E\x10\x89\x5E\x14\x89\x5E\x18\x89\x5E\x1C\x89\x5E\x08\x66\x89\x5E\x30\x89\x7E\x2C\xC7\x06\x2A\x2A\x2A\x2A\xC7\x46\x04\x2A\x2A\x2A\x2A\x53" + "linux" "@_ZN11WitchAttackC2EP11CBaseEntity" + } + } + } +} \ No newline at end of file diff --git a/plugins/l4d2_feedthetrolls.smx b/plugins/l4d2_feedthetrolls.smx index d1064bf..e83f0fc 100644 Binary files a/plugins/l4d2_feedthetrolls.smx and b/plugins/l4d2_feedthetrolls.smx differ diff --git a/plugins/l4d2_witch_force_attack_cmd.smx b/plugins/l4d2_witch_force_attack_cmd.smx index f683833..599f950 100644 Binary files a/plugins/l4d2_witch_force_attack_cmd.smx and b/plugins/l4d2_witch_force_attack_cmd.smx differ diff --git a/plugins/tf2_botcaptcha.smx b/plugins/tf2_botcaptcha.smx deleted file mode 100644 index e542b3a..0000000 Binary files a/plugins/tf2_botcaptcha.smx and /dev/null differ diff --git a/scripting/include/feedthetrolls/commands.inc b/scripting/include/feedthetrolls/commands.inc index 022e694..6e40126 100644 --- a/scripting/include/feedthetrolls/commands.inc +++ b/scripting/include/feedthetrolls/commands.inc @@ -127,23 +127,23 @@ public Action Command_InstaSpecialFace(int client, int args) { public Action Command_WitchAttack(int client, int args) { if(args < 1) { - ReplyToCommand(client, "Usage: sm_witch_attack "); - } else { + ReplyToCommand(client, "Usage: sm_witch_attack [# of witches or 0 for all]"); + }else{ char arg1[32]; GetCmdArg(1, arg1, sizeof(arg1)); char target_name[MAX_TARGET_LENGTH]; - int target_list[MAXPLAYERS], target_count; + int target_list[1], target_count; bool tn_is_ml; if ((target_count = ProcessTargetString( - arg1, - client, - target_list, - 1, - COMMAND_FILTER_ALIVE | COMMAND_FILTER_NO_MULTI, /* Only allow alive players */ - target_name, - sizeof(target_name), - tn_is_ml)) <= 0 - ) { + arg1, + client, + target_list, + 1, + COMMAND_FILTER_ALIVE, /* Only allow alive players */ + 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; @@ -151,17 +151,24 @@ public Action Command_WitchAttack(int client, int args) { int target = target_list[0]; if(GetClientTeam(target) == 2) { + GetCmdArg(2, arg1, sizeof(arg1)); + + int maxCount = StringToInt(arg1); + if(maxCount < 0) maxCount = 0; + int count; + int witch = INVALID_ENT_REFERENCE; while ((witch = FindEntityByClassname(witch, "witch")) != INVALID_ENT_REFERENCE) { - SetWitchTarget(witch, target); + if(SetWitchTarget(witch, target)) { + ++count; + } + if(maxCount > 0 && count >= maxCount) break; } - ShowActivityEx(client, "[FTT] ", "set all witches to target %s", target_name); - LogAction(client, target, "\"%L\" set all witches to attack %s", client, target_name); + ShowActivity(client, "set %d witches to target %s", count, target_name); }else{ ReplyToTargetError(client, target_count); } } - return Plugin_Handled; } diff --git a/scripting/include/feedthetrolls/misc.inc b/scripting/include/feedthetrolls/misc.inc index 92d3d4a..7b1236a 100644 --- a/scripting/include/feedthetrolls/misc.inc +++ b/scripting/include/feedthetrolls/misc.inc @@ -16,18 +16,20 @@ void ActivateAutoPunish(int client) { } } -void SetWitchTarget(int witch, int target) { - #if defined _behavior_included - Behavior behavior = Behavior(witch, WITCH_QUERY); - BehaviorAction action = behavior.CurrentAction.Last; - - BehaviorAction newaction = view_as(AllocateMemory(18556)); - SDKCall(g_hWitchAttack, newaction, target); - - IActionResult result; result.Init(CHANGE_TO, newaction); - result.ToAction(action); +// NOTE: Only supports one target at a time, stored globally +bool SetWitchTarget(int witch, int target) { + #if defined _actions_included + g_iWitchAttackVictim = target; + BehaviorAction action = ActionsManager.GetAction(witch, "WitchBehavior"); + if(action == INVALID_ACTION) { + return false; + } + action = action.Child; + action.OnUpdate = OnWitchActionUpdate; + return true; #else - PrintToServer("[FTT] SetWitchTarget() called when behaviors plugin not found"); + PrintToServer("[FTT] SetWitchTarget() called when behaviors plugin not found"); + return false; #endif } diff --git a/scripting/include/feedthetrolls/trolls.inc b/scripting/include/feedthetrolls/trolls.inc index 566a6ea..30a500d 100644 --- a/scripting/include/feedthetrolls/trolls.inc +++ b/scripting/include/feedthetrolls/trolls.inc @@ -18,7 +18,7 @@ void SetupTrolls() { AddMagnetFlags(index); index = SetupTroll("Tank Magnet", "Attracts ALL tanks to any alive target with this troll enabled", TrollMod_Constant); AddMagnetFlags(index); - #if defined _behavior_included + #if defined _actions_included index = SetupTroll("Witch Magnet", "All witches when startled will target any player with this troll", TrollMod_Constant); #endif index = SetupTroll("Projectile Magnet", "Makes all projectiles (biles, molotovs, pipes, tank rocks) go to player", TrollMod_Constant); diff --git a/scripting/include/ftt.inc b/scripting/include/ftt.inc index c69c134..8abf562 100644 --- a/scripting/include/ftt.inc +++ b/scripting/include/ftt.inc @@ -13,6 +13,7 @@ enum L4D2Infected GlobalForward g_PlayerMarkedForward; Handle g_hWitchAttack; +int g_iWitchAttackVictim; Handle hThrowTimer; ConVar hThrowItemInterval; diff --git a/scripting/l4d2_feedthetrolls.sp b/scripting/l4d2_feedthetrolls.sp index bd34e75..f572f00 100644 --- a/scripting/l4d2_feedthetrolls.sp +++ b/scripting/l4d2_feedthetrolls.sp @@ -12,7 +12,7 @@ #include #include #tryinclude -#tryinclude +#tryinclude #include #include #include @@ -29,9 +29,6 @@ public Plugin myinfo = }; -//TODO: Trolls: Force take pills, Survivor Bot Magnet - - public void OnPluginStart() { EngineVersion g_Game = GetEngineVersion(); if(g_Game != Engine_Left4Dead2) { @@ -50,16 +47,13 @@ public void OnPluginStart() { g_spSpawnQueue = new ArrayList(sizeof(SpecialSpawnRequest)); // Witch target overwrite stuff: - - GameData data = new GameData("l4d2_behavior"); - + GameData data = new GameData("feedthetrolls"); StartPrepSDKCall(SDKCall_Raw); PrepSDKCall_SetFromConf(data, SDKConf_Signature, "WitchAttack::WitchAttack"); PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL | VDECODE_FLAG_ALLOWWORLD); g_hWitchAttack = EndPrepSDKCall(); - delete data; - + hThrowItemInterval = CreateConVar("sm_ftt_throw_interval", "30", "The interval in seconds to throw items. 0 to disable", FCVAR_NONE, true, 0.0); hThrowItemInterval.AddChangeHook(Change_ThrowInterval); hAutoPunish = CreateConVar("sm_ftt_autopunish_action", "0", "Setup automatic punishment of players. Add bits together\n0=Disabled, 1=Tank magnet, 2=Special magnet, 4=Swarm, 8=InstantVomit", FCVAR_NONE, true, 0.0); @@ -85,7 +79,9 @@ public void OnPluginStart() { 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"); + #if defined _actions_included RegAdminCmd("sm_witch_attack", Command_WitchAttack, ADMFLAG_CHEATS, "Makes all witches target a player"); + #endif RegAdminCmd("sm_insta", Command_InstaSpecial, ADMFLAG_KICK, "Spawns a special that targets them, close to them."); RegAdminCmd("sm_stagger", Command_Stagger, ADMFLAG_KICK, "Stagger a player"); RegAdminCmd("sm_inface", Command_InstaSpecialFace, ADMFLAG_KICK, "Spawns a special that targets them, right in their face."); @@ -197,3 +193,17 @@ bool IsPlayerFarDistance(int client, float distance) { PrintToConsoleAll("Flow Check | Player2=%N Flow2=%f", secondClient, secondHighestFlow); return client == farthestClient && difference > distance; } + +BehaviorAction CreateWitchAttackAction(int target = 0) { + BehaviorAction action = ActionsManager.Allocate(18556); + SDKCall(g_hWitchAttack, action, target); + return action; +} + +Action OnWitchActionUpdate(BehaviorAction action, int actor, float interval, ActionResult result) { + /* Change to witch attack */ + result.type = CHANGE_TO; + result.action = CreateWitchAttackAction(g_iWitchAttackVictim); + result.SetReason("FTT"); + return Plugin_Handled; +}