C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using System;
using System.Linq;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using Oxide.Core.Libraries.Covalence;
using Rust;
using Rust.Ai;
using Network;
namespace Oxide.Plugins {
[Info("Payback2", "1928Tommygun", "1.0")]
[Description("Special Admin Commands To Mess With Cheaters")]
class Payback2 : RustPlugin {
[PluginReference]
Plugin Payback;
//| reference to the original payback plugin
//| Hello!
//| This is Payback 2! To make sure you can use this plugin on its own, it comes with some essential features from Payback 1!
//| If you want to have classic admin commands like ROCKETMAN, JAWS, and BSOD, please purchase Payback 1 at https://payback.fragmod.com
//| TUTORIAL:
//| admins require the permission payback.admin to use this plugin
//| this oxide command works for that: oxide.grant group admin payback.admin
//| put 'payback' in the F1 or server console to see the tutorial!
//| =========
//| ===================
//| ==============================================================================
//| TOMMYGUN'S EULA - BY USING THIS PLUGIN YOU AGREE TO THE FOLLOWING!
//| ==============================================================================
//|
//| Code contained in this file is not licensed to be copied, resold, or modified in any way.//| You must purchase another copy of the plugin for each server instance you would like to deploy on.Migration is allowed.//| Do not copy any portion of this document.//| Do not share this plugin with other server organizations, they much purchase their own licenses.//|
//| =======================================
//| ===================
//| =========
//| 1928TOMMYGUN
//MMMMMMMMMMMMMMMMMMMMMMMMWNO::loll::kKKXXXXXXXXXXKXXKx;o000000KKKKNWWWWWWWWWWWWWWWWWWMMMMMMWWXxkNNNNN
//MMMMMMMMMMMMMMMMMMMMMMMMKc,.....................................'',,,,,,,,,,,,,,,,,;;;;;;;;:..,'''.//MMMMMMMMMMMMMMMMMMMMMMMMXc',,;;;;;;;;;;;;;;;;;;;,.',''',;:::::::::::::clldxxxxxxxxxxooocccc
//MMMMMMMMMMMMMMNXK00KXKOdc;'',;:;,,;lxddl::,;::;'.',..''.kWNNNK:...',,........'oXMMMMMMMMMMMMMMMMM
//MMMMWNX0Oxol:;'.......:Oc.xMMMKc....','.;ool,...OMMMMNxcdO0KKo.lNMMMMMMMMMMMMMMMMMM
//Odlc;'...:,';xNMMWk.;xoxXXx'..cXMMMMMMMMMWO:.;OMMMMMMMMMMMMMMMMMMM
//.';:clodxO0XWMMMXo..:x000KK0Ol..xMMMMMMMW0:..:0WWMMMMMMMMMMMMMMMMMMM
//..,lONMMMMMMMMMMMMMX: ,0WMMMMMMMMx.cXMMMMMMMK, 'kNWMMMMMMMMMMMMMMMMMMMMMMMM
//'.;o0NMMMMMMMMMMMMMMMMk..oWMMMMMMMMMx..OMMMMMMMMNl ,OWMMMMMMMMMMMMMMMMMMMMMMM
//'.:xKWMMMMMMMMMMMMMMMMMMMNd..oNMMMMMMMMMMx..OMMMMMMMMMNkl::kWMMMMMMMMMMMMMMMMMMMMMMMM
//..,lkXMMMMMMMMMMMMMMMMMMMMMMMMMXOdxXMMMMMMMMMMMx..OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
//..,lkKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXOkkONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
//:.l0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
//| ==============================================================
//| Definitions
//| ==============================================================
public enum Card {
Pacifism = 0, //zeros all outgoing damage from target player
InstantKarma = 4, //reflects damage back to the player
Dud = 5, //prevents damage to non-player entities
Sit = 8, //force player to sit
HigherGround = 11, //target player is teleported 100m into the air
NoRest, // No Rest For The Wicked! Force the player to respawn!
ViewLoot, // View target entities loot
Hammer, // hammer - gives target player a hammer that will destroy all the entities owned by the hammer's target
Bag, // Bag - Print all players that have bagged target player in, and print all players that have been bagged.Include "discord" after the command to log the results to discord
Woods, // Woods - If you go down to the woods today, be ready for big surprise!
PotatoMode, // PotatoMode - Target's frame rate will decrease dramatically over time - Warning, this is designed to eventually crash Rust
}
Dictionary<Card, string> descriptions = new Dictionary<Card, string>() {
{
Card.Dud, "target player deals no damage to NON-PLAYER entities.Also prevents farming / tool use"
}
, {
Card.InstantKarma, "target player deals no damage to enemies and 35% of the damage is reflected back to them"
}
, {
Card.Pacifism, "target player deals no player damage to non-teammates; add 'silent' to not send a message about it to other players."
}
, {
Card.Sit, "spawns a chair in front of you and forces the cheater to sit.Doesn't let them get up and will place them back in if they die."
}
, {
Card.HigherGround, "target player is teleported 100m into the air"
}
, {
Card.NoRest, "No Rest For The Wicked! Force the player to respawn when they die!"
}
, {
Card.ViewLoot, "View target player's loot"
}
, {
Card.Hammer, "Gives admin a hammer that will destroy all the entities owned by the hammer's target.Add -noloot to also delete the loot"
}
, {
Card.Woods, "Target will get attacked by a bear if he's farming wood or stone.Add -landmine to strap a bunch of landmines to the bear's face"
}
, {
Card.PotatoMode, "Target's frame rate will decrease dramatically over time.-- *Warning, this is designed to crash Rust*"
}
, {
Card.Bag, "Print all players that have bagged target player in, and print all players that have been bagged.Include \"discord\" after the command to log the results to discord"
}
,
}
;
Dictionary<string, Card> cardAliases = new Dictionary<string, Card>() {
{
"dud", Card.Dud
}
, {
"in", Card.InstantKarma
}
, {
"pf", Card.Pacifism
}
, {
"hg", Card.HigherGround
}
, {
"nr", Card.NoRest
}
, {
"res", Card.NoRest
}
, {
"loot", Card.ViewLoot
}
, {
"ham", Card.Hammer
}
, {
"bg", Card.Bag
}
, {
"bear", Card.Woods
}
, {
"potato", Card.PotatoMode
}
,
}
;
//| ==============================================================
//| Giving
//| ==============================================================
public void GiveCard(ulong userID, Card card, string[] args = null, BasePlayer admin = null) {
HashSet<Card> cards;
if (!cardMap.TryGetValue(userID, out cards)) {
cards = new HashSet<Card>();
cardMap[userID] = cards;
}
cards.Add(card);
//Puts($"Payback card {card} given to {userID}");
BasePlayer player = BasePlayer.FindByID(userID);
if (player != null) {
if (card == Card.Sit) {
DoSitCommand(player, admin);
}
else if (card == Card.HigherGround) {
DoHigherGround(player);
}
else if (card == Card.Pacifism) {
silentPacifism = false;
if (args != null) {
if (args.Contains("silent")) {
silentPacifism = true;
}
}
}
else if (card == Card.NoRest) {
if (player.IsDead()) {
player.Respawn();
}
}
else if (card == Card.ViewLoot) {
ViewTargetPlayerInventory(player, admin);
TakeCard(player, Card.ViewLoot);
}
else if (card == Card.Hammer) {
GiveAdminHammer(player);
if (args.Contains("noloot")) {
flag_kill_no_loot = true;
PrintToPlayer(admin, $"Hammer set to remove loot!");
}
else {
flag_kill_no_loot = false;
}
}
else if (card == Card.Woods) {
if (args.Contains("landmine")) {
woodsHasLandmines.Add(player.userID);
}
else {
woodsHasLandmines.Remove(player.userID);
}
}
else if (card == Card.PotatoMode) {
DoPotato(player, admin, args);
}
}
}
bool silentPacifism = false;
//| ==============================================================
//| COMMAND Implementation
//| ==============================================================
string guid_potato = "guid_potato";
Dictionary<ulong, int> currentFrameMap = new Dictionary<ulong, int>();
Dictionary<ulong, Coroutine> potatoCoRoutines = new Dictionary<ulong, Coroutine>();
void DoPotato(BasePlayer player, BasePlayer admin = null, string[] args = null, bool doRemove = false) {
Coroutine routine;
potatoCoRoutines.TryGetValue(player.userID, out routine);
if (doRemove) {
if (routine != null) {
Worker.GetSingleton().StopCoroutine(routine);
return;
}
//if (args.Contains("add")) {
// //| contiue to add to the lag
//} else
//{
// int existing = 0;
// currentFrameMap.TryGetValue(player.userID, out existing);
// for (int i = 0; i <= existing; i ++)
// {
// CuiHelper.DestroyUi(player, guid_BSOD + i);
// }
// currentFrameMap.Remove(player.userID);
// CuiHelper.DestroyUi(player, guid_BSOD);
// return;
//}
}
//if (!currentFrameMap.ContainsKey(player.userID))
//{
// UI2.guids.Add(guid_BSOD);
// var elements = new CuiElementContainer();
// UI2.CreatePanel(elements, "Under", guid_BSOD, "1 1 1 0", UI2.vectorFullscreen, null, false, 0, 0, false);
// CuiHelper.AddUi(player, elements);
//}
UI2.guids.Add(guid_potato);
var elements = new CuiElementContainer();
UI2.CreatePanel(elements, "Under", guid_potato, "1 1 1 0", UI2.vectorFullscreen, null, false, 0, 0, false);
CuiHelper.AddUi(player, elements);
routine = Worker.StaticStartCoroutine(DoPotatoCo(player, args));
potatoCoRoutines[player.userID] = routine;
}
IEnumerator DoPotatoCo(BasePlayer player, string[] args) {
int batch = 10;
//int totalFrames = 600;
int currentFrames = 0;
float rate = 100 / 1f;
//if (args.Contains("crash"))
//{
// intensity = 5;
// totalFrames = 5000;
//}
float ts = Time.realtimeSinceStartup;
float startTime = ts;
float elapsed;
float currentRate;
while (player != null && player.net != null && player.net.connection != null && player.net.connection.connected && HasCard(player.userID, Card.PotatoMode)) {
elapsed = Time.realtimeSinceStartup - startTime + Mathf.Epsilon;
currentRate = currentFrames / elapsed;
if (currentRate > rate) {
//Puts($"Paused: Current Frames: {currentFrames} rate {currentRate}");
yield return null;
}
else {
for (int j = 0; j < batch; j++) {
UI2.guids.Add(guid_potato + currentFrames);
var elements = new CuiElementContainer();
UI2.CreatePanel(elements, guid_potato, guid_potato + currentFrames, "1 1 1 0", UI2.vectorFullscreen, null, false, 0, 0, false);
CuiHelper.AddUi(player, elements);
currentFrames++;
}
}
//Puts($"Current Frames: {currentFrames} rate {currentRate}");
//| Ensure we take a break at least every 1/30s
if (Time.realtimeSinceStartup - ts > 1/30f) {
ts = Time.realtimeSinceStartup;
yield return null;
}
}
}
Dictionary<ulong, float> woodsTimestamps = new Dictionary<ulong, float>();
HashSet<ulong> woodsHasLandmines = new HashSet<ulong>();
void DoWoods(BasePlayer target) {
float ts = 0;
woodsTimestamps.TryGetValue(target.userID, out ts);
if (Time.realtimeSinceStartup - ts < 15) {
return;
}
woodsTimestamps[target.userID] = Time.realtimeSinceStartup;
//TakeCard(target, Card.Woods);
int layermask = 1 << 15 | 1 << 16 | 1 << 17 | 1 << 23 | 1 << 27 | 1 << 8 | 1 << 21 | 1 << 12 | 1 << 0 | 1 << 30;
bool foundSpot = false;
int iterations = 0;
while (!foundSpot && iterations < 100) {
var pos = target.transform.position + target.eyes.HeadRay().direction * -1 * 20;
pos += Vector3.up * 100;
var ray = new Ray(pos, Vector3.down);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000, layermask)) {
//var hits = Physics.SphereCastAll(hit.point, 1, Vector3.up);
var collliders = Physics.OverlapSphere(hit.point, 1);
bool tooClose = false;
if (collliders != null) {
foreach (var c in collliders) {
var ent = c.gameObject.GetComponent<BaseEntity>();
if (ent != null) {
tooClose = true;
}
}
}
if (!tooClose) {
foundSpot = true;
if (woodsHasLandmines.Contains(target.userID)) {
Worker.StaticStartCoroutine(AnimalAttackCo(target, hit.point + Vector3.up, new string[] {
"bear", "landmine"
}
));
}
else {
Worker.StaticStartCoroutine(AnimalAttackCo(target, hit.point + Vector3.up, new string[] {
"bear"
}
));
}
}
}
iterations++;
}
}
HashSet<BaseEntity> animals = new HashSet<BaseEntity>();
HashSet<BaseEntity> noDamageEntities = new HashSet<BaseEntity>();
IEnumerator AnimalAttackCo(BasePlayer player, Vector3 spawnposition, string[] args) {
//Ray ray = new Ray(UnityEngine.Random.Range(-5f, 5f) * Vector3.forward + UnityEngine.Random.Range(-5f, 5f) * Vector3.left + spawnposition + Vector3.up * 20, Vector3.down);
//Ray ray = new Ray(UnityEngine.Random.Range(-5f, 5f) * Vector3.forward + UnityEngine.Random.Range(-5f, 5f) * Vector3.left + spawnposition + Vector3.up * 20, Vector3.down);
//if (Physics.Raycast(ray, out hit))
//{
string aiPrefab = "assets/rust.ai/agents/chicken/chicken.prefab";
if (args.Contains("bear")) {
aiPrefab = "assets/rust.ai/agents/bear/bear.prefab";
}
else if (args.Contains("boar")) {
aiPrefab = "assets/rust.ai/agents/boar/boar.prefab";
}
else if (args.Contains("wolf")) {
aiPrefab = "assets/rust.ai/agents/wolf/wolf.prefab";
}
else if (args.Contains("stag")) {
aiPrefab = "assets/rust.ai/agents/stag/stag.prefab";
}
//assets/rust.ai/agents/wolf/wolf.prefab
var entity = GameManager.server.CreateEntity(aiPrefab, spawnposition + Vector3.up * 0.2f);
//var entity = GameManager.server.CreateEntity("assets/rust.ai/agents/wolf/wolf.prefab", hit.point + Vector3.up * 0.2f);
//var entity = GameManager.server.CreateEntity("assets/rust.ai/agents/bear/bear.prefab", hit.point + Vector3.up * 0.2f);
BaseAnimalNPC npc = entity as BaseAnimalNPC;
entity.Spawn();
var stats = npc.Stats;
npc.AttackRange = 3;
HashSet<BaseEntity> forceNetworkUpdates = new HashSet<BaseEntity>();
if (args.Contains("landmine")) {
for (int i = 0; i < 5; i ++) {
var mine = GameManager.server.CreateEntity("assets/prefabs/deployable/landmine/landmine.prefab", npc.transform.position + Vector3.up * 0.6f + npc.transform.forward * (1.3f - 0.1f * i));
Landmine landmine = mine as Landmine;
mine.Spawn();
landmine.Arm();
landmine.SendNetworkUpdateImmediate();
mine.transform.LookAt(npc.transform.position + npc.transform.up * 100);
mine.SetParent(entity, true);
noDamageEntities.Add(mine);
forceNetworkUpdates.Add(mine);
}
npc.AttackRange = 0.01f;
stats.Speed *= 2.4f;
npc.TargetSpeed *= 2.4f;
}
//chicken.Stats.Speed = 20;
//npc.Stats.Speed = 200;
stats.TurnSpeed = 100;
//npc.Stats.Acceleration = 50;
//npc.AttackDamage *= 2;
stats.VisionRange = 300;
animals.Add(npc);
npc.AttackTarget = player;
npc.ChaseTransform = player.transform;
stats.AggressionRange = 100000;
stats.DeaggroRange = 100000;
stats.IsAfraidOf = new BaseNpc.AiStatistics.FamilyEnum[0];
npc.Destination = player.transform.position;
stats.VisionCone = -1;
npc.Stats = stats;
yield return new WaitForSeconds(0.25f);
//chicken.LegacyNavigation = true;
//chicken.Stats.DistanceVisibility = AnimationCurve.Linear(0, 0, 1, 1);
npc.LegacyNavigation = true;
bool doLoop = true;
while (doLoop) {
foreach (var ent in forceNetworkUpdates) {
if (ent != null) {
if (ent.net.group.ID != npc.net.group.ID) {
ent.net.SwitchGroup(npc.net.group);
ent.SendNetworkGroupChange();
}
}
}
if (npc != null && player != null) {
if (player.IsDead()) {
if (npc != null) {
npc.Kill();
}
doLoop = false;
}
else {
if (npc.NavAgent != null && npc.NavAgent.isOnNavMesh) {
npc.ChaseTransform = player.transform;
npc.AttackTarget = player;
npc.Destination = player.transform.position;
npc.TargetSpeed = npc.Stats.Speed;
}
}
//Puts($"Attack target: {chicken.AttackTarget} Chase: {chicken.ChaseTransform} ARate: {chicken.AttackRate} CombatTarget: {chicken.CombatTarget}");
//chicken.TickNavigation();
}
else {
if (npc != null) {
npc.Kill();
}
doLoop = false;
}
yield return null;
//yield return new WaitForSeconds(0.25f);
}
timer.Once(120, () => {
if (npc != null) {
npc.Kill();
}
}
);
timer.Once(130f, () => {
animals.RemoveWhere(x => x == null);
}
);
//}
}
#region OxideHooks
//| ==============================================================
//| OXIDE HOOKS
//| ==============================================================
private object OnPlayerViolation(BasePlayer player, AntiHackType type) {
if (type == AntiHackType.InsideTerrain && HasAnyCard(player.userID)) return false;
return null;
}
object OnPlayerDeath(BasePlayer player, HitInfo hitinfo) {
if (HasAnyCard(player.userID)) {
if (player.isMounted) {
player.GetMounted().DismountPlayer(player, true);
//player.DismountObject();//for some reason this was required
}
if (HasCard(player.userID, Card.NoRest)) {
timer.Once(3f, () => {
if (player != null) {
if (player.IsDead()) {
player.Respawn();
}
}
}
);
}
}
return null;
}
void OnPlayerDisconnected(BasePlayer player, string reason) {
if (player != null && HasCard(player.userID, Card.Sit)) {
TakeCard(player, Card.Sit);
}
}
private void OnEntityTakeDamage(BaseEntity entity, HitInfo hitinfo) {
if (entity == null || hitinfo == null) return;
if (cardMap.Count == 0) return;
//early out for maximum perf
if (hitinfo != null) {
if (sitChairMap.Values.Contains(entity)) {
hitinfo.damageTypes.Clear();
hitinfo.DoHitEffects = false;
}
var player = entity as BasePlayer;
var attacker = hitinfo.InitiatorPlayer;
if (hitinfo.Initiator != null && noDamageEntities.Contains(hitinfo.Initiator)) {
if (player != null && HasAnyCard(player.userID) || entity is BaseNpc) {
//| damage ok
}
else {
//| no damage
hitinfo.damageTypes.Clear();
hitinfo.DoHitEffects = false;
}
}
if (attacker != null && HasAnyCard(attacker.userID)) {
var members = GetPlayerTeam(attacker.userID);
members.Remove(attacker.userID);
bool friendlyFire = false;
if (player != null) {
friendlyFire = members.Contains(player.userID);
}
bool isSuicide = hitinfo.damageTypes.GetMajorityDamageType() == Rust.DamageType.Suicide;
if (player != null && attacker != null && attacker != player) {
if (HasCard(attacker.userID, Card.InstantKarma)) {
if (!friendlyFire) {
float newHealth = attacker.health - hitinfo.damageTypes.Total() * 0.35f;
if (newHealth < 5) {
attacker.Die();
}
else {
attacker.SetHealth(newHealth);
attacker.metabolism.SendChangesToClient();
attacker.SendNetworkUpdateImmediate();
//PlaySound("assets/bundled/prefabs/fx/headshot.prefab", attacker, false);
PlaySound("assets/bundled/prefabs/fx/headshot_2d.prefab", attacker, true);
}
hitinfo.damageTypes.Clear();
hitinfo.DoHitEffects = false;
}
}
}
if (HasCard(attacker.userID, Card.Pacifism) && attacker != player && player != null) {
if (!friendlyFire) {
hitinfo.damageTypes.Clear();
hitinfo.DoHitEffects = false;
if (config.notifyCheaterAttacking && !silentPacifism) {
SendPlayerLimitedMessage(player.userID, $"You are being attacked by [{UI2.ColorText(attacker.displayName, "yellow")}] a known cheater!\n{UI2.ColorText("Tommygun's Payback Plugin", "#7A2E30")} has prevented all damage to you.");
}
//Puts($"{player.displayName} attacked by [{attacker.displayName}] a known cheater! Tommygun's Payback has prevented all damage from the cheater");
}
}
//
if (attacker != null && HasCard(attacker.userID, Card.Woods))
{
if (hitinfo.CanGather)
{
DoWoods(attacker);
}
}
//prevent damage to non-player entities
if (HasCard(attacker.userID, Card.Dud) && player == null)
{
hitinfo.damageTypes.Clear();
//hitinfo.DoHitEffects = false;
hitinfo.gatherScale = 0;
}
}
}
}
#endregion
#region PaybackIO
//| ==============================================================
//| INPUT OUTPUT FUNCTIONALITY
//| ==============================================================
Dictionary<ulong, float> playerMessageTimestamps = new Dictionary<ulong, float>();
void SendPlayerLimitedMessage(ulong userID, string message, float rate = 5)
{
float ts = float.NegativeInfinity;
if (playerMessageTimestamps.TryGetValue(userID, out ts))
{
if (Time.realtimeSinceStartup - ts > rate)
{
ts = Time.realtimeSinceStartup;
playerMessageTimestamps[userID] = ts;
SendReply(BasePlayer.FindByID(userID), message);
}
}
else
{
playerMessageTimestamps[userID] = ts;
SendReply(BasePlayer.FindByID(userID), message);
}
}
void AdminCommandToggleCard(BasePlayer admin, Card card, string[] args)
{
//| Special Commands
if (card == Card.Bag)
{
ulong userID;
if (!ulong.TryParse(args[0], out userID))
{
PrintToPlayer(admin, "usage : /bag <steamid>");
return;
}
DoBagSearch(userID, args, admin);
}
//| Requires target commands
if (args.Length == 0 && admin != null)
{
var entity = RaycastFirstEntity(admin.eyes.HeadRay(), 100);
if (entity is BasePlayer)
{
var targetPlayer = entity as BasePlayer;
AdminToggleCard(admin, targetPlayer, card, args);
}
else
{
//raycast target in front of you
//SendReply(admin, "did not find player from head raycast, either look at your target or do /<cardname> <playername>");
PrintToPlayer(admin, "did not find player from head raycast, either look at your target or do /<cardname> <playername>");
}
return;
}
if (args.Length >= 1)
{
var targetPlayer = GetPlayerWithName(args[0]);
if (targetPlayer != null)
{
if (args.Length == 2 && args[1] == "team")
{
var members = GetPlayerTeam(targetPlayer.userID);
string teamMatesPrintout = "";
foreach (var member in members)
{
BasePlayer p = BasePlayer.FindByID(member);
if (p != null && p.IsConnected)
{
teamMatesPrintout += p.displayName + " ";
}
}
PrintToPlayer(admin, $"Giving {
card
}
to team {
targetPlayer.displayName
}
- {
members.Count
}
team mates : {
teamMatesPrintout
}
");
foreach (var member in members)
{
BasePlayer p = BasePlayer.FindByID(member);
if (p != null && p.IsConnected)
{
AdminToggleCard(admin, p, card, args);
}
}
}
else
{
AdminToggleCard(admin, targetPlayer, card, args);
}
}
else
{
ulong userID;
if (ulong.TryParse(args[0], out userID))
{
targetPlayer = BasePlayer.FindByID(userID);
if (targetPlayer != null)
{
if (args.Length == 2 && args[1] == "team")
{
var members = GetPlayerTeam(targetPlayer.userID);
PrintToPlayer(admin, $"Giving {
card
}
to team {
targetPlayer.displayName
}
has {
members.Count
}
team mates");
foreach (var member in members)
{
BasePlayer p = BasePlayer.FindByID(member);
if (p != null && p.IsConnected)
{
AdminToggleCard(admin, p, card, args);
}
}
}
else
{
AdminToggleCard(admin, targetPlayer, card, args);
}
return;
}
else
{
}
}
else
{
}
PrintToPlayer(admin, $"could not find player : {
args[0]
}
");
}
}
}
void AdminToggleCard(BasePlayer admin, BasePlayer targetPlayer, Card card, string[] args)
{
if (HasCard(targetPlayer.userID, card))
{
TakeCard(targetPlayer.userID, card, args, admin);
PrintToPlayer(admin, $"Removed {
card
}
from {
targetPlayer.displayName
}
");
}
else
{
GiveCard(targetPlayer.userID, card, args, admin);
PrintToPlayer(admin, $"Gave {
card
}
to {
targetPlayer.displayName
}
");
}
}
[ConsoleCommand("payback2")]
void Console_Payback(ConsoleSystem.Arg arg)
{
var player = arg.Connection?.player as BasePlayer;
if (player != null) {
if (!IsAdmin(player)) return;
}
CommandPayback(player, "", arg.Args);
}
[ChatCommand("payback2")]
void ChatCommandPayback(BasePlayer player, string cmd, string[] args)
{
if (!IsAdmin(player)) return;
SendReply(player, "Check Payback2 output in F1 console!");
CommandPayback(player, cmd, args);
}
void CommandPayback(BasePlayer player, string cmd, string[] args)
{
if (player != null && !IsAdmin(player)) return;
// list all cards
if (args == null || args.Length == 0)
{
DoPaybackPrintout(player, args);
return;
}
List<string> argsList = new List<string>(args);
if (argsList.FirstOrDefault(x => x == "show") != null)
{
string output = "Active Cards : \n";
// show all active cards and players
foreach (var userid in cardMap.Keys)
{
var targetPlayer = BasePlayer.FindByID(userid);
string playername = "";
if (targetPlayer != null)
{
playername = targetPlayer.displayName;
}
HashSet<Card> cards = cardMap[userid];
output += $" {
userid
}
: {
playername
}
\n";
foreach (var card in cards)
{
output += $"\n {
card.ToString()
}
: {
UI2.ColorText(descriptions[card], "white")
}
";
}
output += "\n\n";
}
PrintToPlayer(player, output);
}
if (argsList.FirstOrDefault(x => x == "clear") != null)
{
foreach (var userid in new List<ulong>(cardMap.Keys))
{
var targetPlayer = BasePlayer.FindByID(userid);
string playername = "";
if (targetPlayer != null)
{
playername = targetPlayer.displayName;
}
if (player != null)
{
HashSet<Card> cards = cardMap[userid];
foreach (var card in new HashSet<Card>(cards))
{
TakeCard(player, card);
}
}
}
cardMap.Clear();
PrintToPlayer(player, "removed all cards from all players");
}
}
const string PAYBACK_VERSION = "Payback2";
void DoPaybackPrintout(BasePlayer player, string[] args)
{
Dictionary<Card, List<string>> cardToAliases = new Dictionary<Card, List<string>>();
foreach (var alias in cardAliases.Keys)
{
Card c = cardAliases[alias];
List<string> aliases;
if (!cardToAliases.TryGetValue(c, out aliases))
{
aliases = new List<string>();
cardToAliases[c] = aliases;
}
aliases.Add(alias);
}
var cards = Enum.GetValues(typeof(Card));
string output = "";
output += "\n" + "Add \"team\" after a command to apply the effect to target player's team as well as them.Example: /bear <steamid> team";
////output += "\n" + "/setdroppercent <1-100>% to change the chance butterfingers would drop";
output += "\n" + $"admins require the permisison {permission_admin} to use these commands!";
output += "\n" + $"use '/{PAYBACK_VERSION} show' to see which players have which cards";
output += "\n" + $"use '/{PAYBACK_VERSION} clear' to remove all cards from all players.";
output += "\n" + $"It is NOT necessary to remove effects from players when finished.";
//output += "\n" + $"Whitelist temp banned players with: bancheckexception <id>";
output += "\n\nPayback Cards:";
foreach (Card card in cards) {
string desc;
descriptions.TryGetValue(card, out desc);
List<string> aliases = cardToAliases[card];
string aliasesTogether = "";
aliases.ForEach(x => aliasesTogether += $"[ {UI2.ColorText(x, "yellow")} ] ");
output += "\n\n" + $"{aliasesTogether}: { UI2.ColorText(desc, "white")}";
}
if (Payback == null) {
output += "\n\n " + UI2.ColorText("Payback (the original) not detected, did you know there's even more Payback available at https://payback.fragmod.com?", "white");
}
PrintToPlayer(player, output);
}
//| ==============================================================
//| PAYBACK OPTIONS
//| ==============================================================
Dictionary<ulong, HashSet<Card>> cardMap = new Dictionary<ulong, HashSet<Card>>();
public bool HasAnyCard(ulong userID) {
HashSet<Card> cards = null;
if (cardMap.TryGetValue(userID, out cards)) {
if (cards.Count > 0) {
return true;
}
}
return false;
}
public bool HasCard(ulong userID, Card card) {
HashSet<Card> cards;
if (cardMap.TryGetValue(userID, out cards)) {
if (cards.Contains(card)) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
public void TakeCard(BasePlayer player, Card card, string[] args = null, BasePlayer admin = null) {
TakeCard(player.userID, card, args, admin);
}
public void TakeCard(ulong userID, Card card, string[] args = null, BasePlayer admin = null) {
HashSet<Card> cards;
if (!cardMap.TryGetValue(userID, out cards)) {
cards = new HashSet<Card>();
cardMap[userID] = cards;
}
cards.Remove(card);
var player = BasePlayer.FindByID(userID);
if (cards.Count == 0) {
cardMap.Remove(userID);
}
else if (card == Card.Sit) {
if (player != null) {
DoSitCommand(player, admin);
}
}
else if (card == Card.PotatoMode) {
DoPotato(player, null, args, true);
}
}
#endregion
#region DiscordEmbeds
void SendToDiscordWebhook(Dictionary<string, string> messageData, string title = "TEMP GAME BAN DETECTED") {
if (config.webhooks == null || config.webhooks.Count == 0) {
Puts($"Could not send Discord Webhook: webhook not configured");
return;
}
string discordEmbedTitle = title;
List<object> fields = new List<object>();
foreach (var key in messageData.Keys) {
string data = messageData[key];
fields.Add(new {
name = $"{key}", value = $"{data}", inline = false
}
);
}
object f = fields.ToArray();
foreach (var webhook in config.webhooks) {
SendWebhook(webhook, (string)discordEmbedTitle, f);
}
}
private void SendWebhook(string WebhookUrl, string title, object fields) {
if (string.IsNullOrEmpty(WebhookUrl)) {
Puts("Error: Someone tried to use a command but the WebhookUrl is not set!");
return;
}
//test
string json = new SendEmbedMessage(13964554, title, fields).ToJson();
webrequest.Enqueue(WebhookUrl, json, (code, response) => {
if (code == 429) {
Puts("Sending too many requests, please wait");
return;
}
if (code != 204) {
Puts(code.ToString());
}
if (code == 400) {
Puts(response + "\n\n" + json);
}
}
, this, Oxide.Core.Libraries.RequestMethod.POST, new Dictionary<string, string> {
["Content-Type"]
= "application/json"
}
);
}
private class SendEmbedMessage {
public SendEmbedMessage(int EmbedColour, string discordMessage, object _fields) {
object embed = new[] {
new {
title = discordMessage, fields = _fields, color = EmbedColour, thumbnail = new Dictionary<object, object>() {
{
"url", "https://i.imgur.com/ruy7N2Z.png"
}
}
,
}
}
;
Embeds = embed;
}
[JsonProperty("embeds")]
public object Embeds {
get;
set;
}
public string ToJson() => JsonConvert.SerializeObject(this);
}
#endregion
#region Initialize
// ... [Code preview truncated due to length. Full source in attached file] ...