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;
using Facepunch;
using System.Runtime.InteropServices;
namespace Oxide.Plugins {
[Info("Payback", "1928Tommygun", "2.0.17")]
[Description("Special Admin Commands To Mess With Cheaters")]
class Payback : RustPlugin {
[PluginReference]
Plugin Payback2;
//| reference to the original payback2
[PluginReference]
private Plugin ImageLibrary;
//| Optional reference to ImageLibrary
//| TUTORIAL:
//| admins require the permission payback.admin to use this plugin
//| use /payback in game to see the tutorial
//| =============================================
//| CHANGELOG
//| =============================================
//| 2.0.17
//| - update for Jan 12 2025, prevent players with sit from attacking and becoming hostile
//| 2.0.16
//| - update for nov 7
//| 2.0.15
//| - update for Oct 3 patch
//| 2.0.14
//| - fixed rocketman for May 2 2024 update
//| 2.0.13
//| - fixed rocketman sfx
//| - reduced damage on chicken
//| - fixed gestures
//| 2.0.12
//| - Fixed HigherGround
//| 2.0.11
//| - Fixed OnEntityTakeDamage NRE
//| 2.0.10
//| - Fixed OnBanned NRE
//| - Landmines can no longer be picked up
//| 2.0.9
//| - Fixed missing image links
//| 2.0.8
//| - Fixed console and chat binds when targeting a player with raycast
//| 2.0.7
//| - Updated missing image urls
//| 2.0.6
//| - Sit command now uses a toilet chair by default! Includes options for using other chairs
//| - Added config to disable showing UI to admins while commands are active
//| - Updated License : you are allowed to use this plugin on multiple servers as long as you are the owner of the servers without purchasing additional copies.Please consider tipping!
//| 2.0.5
//| - Restored rocketman to its former glory with the return of the invisible chair!
//| 2.0.4
//| - Added a temporary fix for rocketman and other broken commands, next month Facepunch will update the game and it will work just like before!
//| - Added ability to for commands to persist between server restarts
//| 2.0.3
//| - Jan 2023 patch basemounteable
//| 2.0.2
//| - Prevent [MASOCHIST] targets from killing themselves with fall damage
//| 2.0.1
//| - General improvements
//| 2.0.0
//| - Added ability to log admins using payback to discord
//| - Added UI - Shows which commands are currently active
//| - Improved support for conflicting commands
//| 1.9.8
//| - Updated for Jan 28 new year content
//| - Added auto-ban functionality for temp-bans.//| =========
//| ===================
//| ==============================================================================
//| TOMMYGUN'S EULA - BY USING THIS PLUGIN YOU AGREE TO THE FOLLOWING!
//| ==============================================================================
//|
//| Code contained in this file is not licensed to be copied, shared, resold, or modified in any way.//| You may copy the plugin freely to each server instance that your organization owns.I ask that you include an optional tip if you are a large server organization, the suggested amount is one copy for every 10 servers you are running.//| Do not share this plugin with other server organizations, they must purchase their own licenses.//|
//| =======================================
//| ===================
//| =========
//| TOMMYGUN
//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
//| ==============================================================
#region FNUTIL
List<Item> PooledList = new List<Item>();
List<Item> GetAllItems(BasePlayer player) {
player.inventory.GetAllItems(PooledList);
return PooledList;
}
#endregion
public enum Card {
Pacifism = 0, //zeros all outgoing damage from target player
Butterfingers = 1, //on dealing damage to any player, chance to drop current held weapon.InstantKarma = 4,//reflects damage back to the player
Dud = 5, //prevents damage to non-player entities
DogDoo = 6, //landmine under target player when the access stashes
BSOD = 7, //give target player fake BSOD
Sit = 8, //force player to sit
Naked = 9, //force player to drop everything they have in their inventory
Camomo = 10, //apply a combination of abilities Camomo has selected
HigherGround = 11, //target player is teleported 100m into the air
Thirsty = 12, //target player becomes thirsty very quickly
DrNo = 13, // target player no longer receives health from healing items
Dana = 14, // steal target player's inventory and place it in your own
Pinyata = 15, // target player's inventory explodes out of them when they die
Rocketman, // strap target player to a rocket and launch them!
NoRest, // No Rest For The Wicked! Force the player to respawn!
ChickenChaser, // Spawns a horde of chickens with super speed that only attack target player!
ViewLoot, // View target entities loot
Burn, // Gives a player a flamethrower that will make his foes scream and burn
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
Shocker, // Shocker - Shock target player to death.Affects nearby players so be careful.Make sure to disable it after use.//Cowboy, // Cowboy - Ride target player like a wild hog -> couldn't get this to work
Masochist, // Masochist - Stop player from F1 killing themselves
Emote, // Emote - options:
Shark, // Jaws - shark comes to eat the cheater
}
Dictionary<Card, string> descriptions = new Dictionary<Card, string>() {
{
Card.Butterfingers, "% chance for target player to drop their weapon when damaging an enemy"
}
, {
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.DogDoo, "landmine under target player when the access stashes"
}
, {
Card.BSOD, "target player receives a fake blue-screen-of-death"
}
, {
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.add 'beach' or 'gamer' to the end of the command to change the chair prefab!"
}
, {
Card.Naked, "force player to drop everything they have in their inventory"
}
, {
Card.Camomo, "apply a combination of abilities Camomo has selected [pf,bf,in,dog,dud,dr]"
}
, {
Card.HigherGround, "target player is teleported 100m into the air"
}
, {
Card.Thirsty, "target player becomes thirsty very quickly"
}
, {
Card.DrNo, "target player can no longer heal"
}
, {
Card.Dana, "steal target player's inventory and place it in your own"
}
, {
Card.Pinyata, "target player's inventory explodes out of them when they die"
}
, {
Card.Rocketman, "strap target player to a rocket and launch them!"
}
, {
Card.NoRest, "No Rest For The Wicked! Force the player to respawn when they die!"
}
, {
Card.ChickenChaser, "Spawns a horde of chickens with super speed that only attack target player! add 'wolf' 'stag' 'bear' or 'boar' after the command to change the animal"
}
, {
Card.ViewLoot, "View target player's loot"
}
, {
Card.Burn, "Gives a player a flamethrower that will make his foes scream and burn"
}
, {
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.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"
}
, {
Card.Shocker, "Shock target player to death.Affects nearby players so be careful.Make sure to disable it after use."
}
, //{Card.Cowboy, "Cowboy - Ride target player like a wild hog" },
{
Card.Masochist, "Masochist - Stop player from F1 killing themselves"
}
, {
Card.Emote, "Emote - force player to do an emote."
}
, {
Card.Shark, "shark comes to eat the cheater"
}
,
}
;
Dictionary<string, Card> cardAliases = new Dictionary<string, Card>() {
{
"bf", Card.Butterfingers
}
, {
"dud", Card.Dud
}
, {
"in", Card.InstantKarma
}
, {
"pf", Card.Pacifism
}
, {
"dog", Card.DogDoo
}
, {
"bs", Card.BSOD
}
, {
"nk", Card.Naked
}
, {
"cumnum", Card.Camomo
}
, {
"hg", Card.HigherGround
}
, {
"th", Card.Thirsty
}
, {
"dr", Card.DrNo
}
, {
"dana", Card.Dana
}
, {
"steal", Card.Dana
}
, {
"pin", Card.Pinyata
}
, {
"rm", Card.Rocketman
}
, {
"nr", Card.NoRest
}
, {
"res", Card.NoRest
}
, {
"ch", Card.ChickenChaser
}
, {
"loot", Card.ViewLoot
}
, {
"bu", Card.Burn
}
, {
"ham", Card.Hammer
}
, {
"bg", Card.Bag
}
, {
"sh", Card.Shocker
}
, //{ "cow", Card.Cowboy},
{
"ms", Card.Masochist
}
, {
"em", Card.Emote
}
, {
"jaws", Card.Shark
}
,
}
;
HashSet<Card> cardsWhichCauseConflicts = new HashSet<Card>() {
Card.Sit, Card.Rocketman, Card.Shark,
}
;
HashSet<Card> cardsWhichCanPersist = new HashSet<Card>() {
Card.Butterfingers, Card.Dud, Card.InstantKarma, Card.Pacifism, Card.DogDoo, Card.BSOD, Card.Thirsty, Card.DrNo, Card.NoRest, Card.ChickenChaser, Card.Masochist,
}
;
//| ==============================================================
//| Giving
//| ==============================================================
public void GiveCard(ulong userID, Card card, string[] args = null, BasePlayer admin = null) {
BasePlayer player = BasePlayer.FindByID(userID);
if (cardsWhichCauseConflicts.Contains(card)) {
ResolveConflictingCommands(player, admin, (int)card);
}
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}");
if (player != null) {
if (card == Card.BSOD) {
bool playPublic = args.Contains("public");
DoBSOD(player, playPublic);
}
else if (card == Card.Sit) {
DoSitCommand(player, admin, args);
}
else if (card == Card.Naked) {
DoNakedCommand(player);
}
else if (card == Card.Camomo) {
DoCamomoCommand(player);
}
else if (card == Card.HigherGround) {
DoHigherGround(player);
}
else if (card == Card.Thirsty) {
DoThirsty(player);
}
else if (card == Card.Dana) {
DoDana(player, admin);
}
else if (card == Card.Pacifism) {
silentPacifism = false;
if (args != null) {
if (args.Contains("silent")) {
silentPacifism = true;
}
}
}
else if (card == Card.Rocketman) {
RocketManTarget(player);
}
else if (card == Card.NoRest) {
if (player.IsDead()) {
player.Respawn();
}
}
else if (card == Card.ChickenChaser) {
AdminSpawnChickens(admin, player, args);
TakeCard(player, Card.ChickenChaser);
}
else if (card == Card.ViewLoot) {
ViewTargetPlayerInventory(player, admin);
TakeCard(player, Card.ViewLoot);
}
else if (card == Card.Burn) {
GivePlayerFlamethrower(player);
}
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.Shocker) {
DoShocker(player, args, admin);
}
else if (card == Card.Emote) {
DoEmote(player, args, admin);
}
else if (card == Card.Shark) {
DoShark(player, args, admin);
}
if (config.logPaybackCommands) {
SendToDiscordWebhook(new Dictionary<string, string>() {
{
"Admin", $"{admin?.displayName} | {admin?.userID}"
}
, {
$"{card.ToString()}", $"{player.displayName} | {player?.userID}"
}
,
}
, $"{ConVar.Server.hostname}");
}
//| if we are saving commands and this command can be saved, do the saving
if (config.persistentCommands && cardsWhichCanPersist.Contains(card)) {
HashSet<Card> persistentCards = null;
if (!paybackData.persistentCommandMap.TryGetValue(player.userID, out persistentCards)) {
persistentCards = new HashSet<Card>();
paybackData.persistentCommandMap[player.userID] = persistentCards;
}
persistentCards.Add(card);
}
}
}
bool silentPacifism = false;
#region VISUALIZATION
string url_payback_logo = "http://na.fragmod.com/fragimages/dec2023/payback_logo_broad.png";
string url_payback_logo_raised = "http://na.fragmod.com/fragimages/dec2023/payback_logo_broad_down.png";
List<BasePlayer> admins = new List<BasePlayer>();
float ts_admin = 0;
//| ===================================================
HashSet<ulong> adminsNoUI = new HashSet<ulong>();
[ConsoleCommand("paybacknoui")]
void Console_Payback_NoUI(ConsoleSystem.Arg arg) {
var player = arg.Connection?.player as BasePlayer;
if (player != null) {
if (!IsAdmin(player)) return;
if (!adminsNoUI.Contains(player.userID)) {
adminsNoUI.Add(player.userID);
PrintToPlayer(player, $"paybackui disabled : {adminsNoUI.Count}");
UpdateAdminUI(player);
}
else {
adminsNoUI.Remove(player.userID);
PrintToPlayer(player, $"paybackui enabled : {adminsNoUI.Count}");
UpdateAdminUI(player);
}
}
}
//| ===================================================
void CacheAdmins() {
if (Time.realtimeSinceStartup - ts_admin > 3) {
ts_admin = Time.realtimeSinceStartup;
admins.Clear();
foreach (var player in BasePlayer.activePlayerList) {
if (IsAdmin(player)) {
admins.Add(player);
}
}
}
}
int currentActiveCardCount = 0;
IEnumerator AdminVisualizationCo() {
while (config.showUI) {
var allCards = GetActiveCards();
currentActiveCardCount = allCards.Count;
if (Payback2 != null) {
var otherCards = Payback2.Call("GetActiveCardsStrings") as List<string>;
currentActiveCardCount += otherCards.Count;
}
if (cachedCards != currentActiveCardCount) {
animState = 1;
animationFlag = true;
}
else {
if (animState != 0) {
animationFlag = true;
}
animState = 0;
}
foreach (var admin in admins) {
if (admin == null) continue;
UpdateAdminUI(admin);
}
animationFlag = false;
cachedCards = currentActiveCardCount;
CacheAdmins();
yield return new WaitForSeconds(0.3f);
}
}
HashSet<Card> GetActiveCards() {
HashSet<Card> allCards = new HashSet<Card>();
foreach (var userid in cardMap.Keys.ToArray()) {
var target = BasePlayer.FindByID(userid);
if (target == null) continue;
var cards = cardMap[userid];
if (cards == null || cards.Count == 0) continue;
allCards.UnionWith(cards);
}
return allCards;
}
//| Bridge to other Payback
List<string> GetActiveCardsStrings() {
List<string> cards = new List<string>();
foreach (var card in GetActiveCards()) {
cards.Add(card.ToString());
}
return cards;
}
int cachedCards = 0;
int animState = 0;
bool animationFlag = false;
HashSet<ulong> activePaybackUIS = new HashSet<ulong>();
void UpdateAdminUI(BasePlayer player) {
//| disable showing the UI
if (!config.showUI) {
return;
}
//| ===================================
//| BASE UI SETUP
//| ===================================
if (player.net.connection == null) return;
string guid = "guid_admin";
UI2.guids.Add(guid);
var elements = new CuiElementContainer();
if (currentActiveCardCount == 0 || (adminsNoUI.Contains(player.userID))) {
CuiHelper.DestroyUi(player, guid);
activePaybackUIS.Remove(player.userID);
return;
}
if (animState == 1) {
CuiHelper.DestroyUi(player, "payback_logo");
}
if (animState == 0) {
CuiHelper.DestroyUi(player, "payback_logo_raised");
}
//| refresh the commands
CuiHelper.DestroyUi(player, "commands");
//| ===================================
//| Bounds definitions
//| ===================================
float width = 0.4f;
//float height = 0.2f;
float logoWidth = 0.125f;
Vector4 mainBounds = new Vector4(0.5f - width / 2f, 0.5f, 0.5f + width / 2f, 0.9f);
Vector4 logoBounds = new Vector4(0.5f - logoWidth / 2f, 0.90f, 0.5f + logoWidth / 2f, 1f);
string output = "";
var allCards = GetActiveCards();
foreach (var card in allCards) {
output += $"{UI2.ColorText("•", "#B00101")} {card.ToString()}" + "\n";
}
if (Payback2 != null) {
var otherCards = Payback2.Call("GetActiveCardsStrings") as List<string>;
foreach (var card in otherCards) {
output += $"{UI2.ColorText("•", "#B00101")} {card.ToString()}" + "\n";
}
}
bool updateLogo = false;
if (!activePaybackUIS.Contains(player.userID)) {
UI2.CreatePanel(elements, "Under", guid, "1 1 1 0", UI2.vectorFullscreen, null, false);
activePaybackUIS.Add(player.userID);
updateLogo = true;
}
if (animationFlag) {
updateLogo = true;
}
if (updateLogo) {
if (ImageLibrary != null) {
if (animState == 0) {
UI2.CreatePanel(elements, guid, "payback_logo", "1 1 1 1", logoBounds, GetImage(url_payback_logo), false, 0.0f, 0.0f, true);
}
else if (animState == 1) {
UI2.CreatePanel(elements, guid, "payback_logo_raised", "1 1 1 1", logoBounds, GetImage(url_payback_logo_raised), false, 0.0f, 0.0f, true);
}
}
else {
if (animState == 0) {
UI2.CreatePanel(elements, guid, "payback_logo", "1 1 1 1", logoBounds, GetImage(url_payback_logo), false, 0.0f, 0.0f, false);
}
else if (animState == 1) {
UI2.CreatePanel(elements, guid, "payback_logo_raised", "1 1 1 1", logoBounds, GetImage(url_payback_logo_raised), false, 0.0f, 0.0f, false);
}
}
}
UI2.CreateOutlineLabel(elements, guid, "commands", output, "1 1 1 1", 28, mainBounds, TextAnchor.UpperCenter);
//| ===================================
//| CONDITIONAL UI UPDATES
//| ===================================
//send the ui updates
if (elements.Count > 0) {
CuiHelper.AddUi(player, elements);
}
}
#endregion
//| ==============================================================
//| COMMAND Implementation
//| ==============================================================
void DoShark(BasePlayer player, string[] args, BasePlayer admin = null) {
Worker.StaticStartCoroutine(SharkCo2(player, args, admin));
}
IEnumerator SharkCo2(BasePlayer player, string[] args, BasePlayer admin = null) {
TakeCard(player, Card.Shark);
////| KILL ALL EXISTING SHARKS FOR DEBUGGING
//SimpleShark[] sharks = GameObject.FindObjectsOfType<SimpleShark>();
//foreach (var s in sharks)
//{
// s.Kill();
//}
//| SPAWN THE SHARK
SimpleShark shark;
string sharkPrefab = "assets/rust.ai/agents/fish/simpleshark.prefab";
BaseEntity entity = GameManager.server.CreateEntity(sharkPrefab, player.transform.position + new Vector3(-100, -100, -100));
shark = entity as SimpleShark;
entity.Spawn();
shark.enabled = false;
Vector3 playerForward = player.eyes.HeadForward();
playerForward.y = 0;
playerForward.Normalize();
shark.transform.LookAt(player.transform.position + Vector3.up * 100 + playerForward);
yield return Worker.StaticStartCoroutine(MoveSharkCo(shark, player));
}
string sfx_bloodHit = "assets/bundled/prefabs/fx/impacts/stab/flesh/fleshbloodimpact.prefab";
string sfx_watersplash = "assets/bundled/prefabs/fx/explosions/water_bomb.prefab";
IEnumerator MoveSharkCo(SimpleShark shark, BasePlayer player) {
float duration = 4f;
//float duration = 20f;
float ts = Time.realtimeSinceStartup;
Vector3 sharkStartPos = player.transform.position + Vector3.down * 30f;
Vector3 playerStartPosition = player.transform.position;
Vector3 playerForward = player.eyes.HeadForward();
playerForward.y = 0;
playerForward.Normalize();
bool didSit = false;
BaseEntity chair = null;
//bool didEmote = false;
float p;
float y;
while (Time.realtimeSinceStartup - ts < duration && player != null && shark != null) {
p = (Time.realtimeSinceStartup - ts) / duration;
y = Mathf.Sin(p * Mathf.PI);
//if (p < 0.34)
if (p < 0.24) {
//playerStartPosition = player.transform.position + Vector3.up * 4f;//|V2
playerStartPosition = player.transform.position + Vector3.up * 10f;
shark.transform.LookAt(player.transform.position + Vector3.up * 100 + playerForward);
}
else {
if (!didSit) {
//| PLAY SFX
//PlaySound(sfx_bloodHit, player, false, player.transform.position + Vector3.up);
//PlaySound(sfx_watersplash, player, false, player.transform.position);
global : : Effect.server.Run(shark.bloodCloud.resourcePath, player.transform.position + Vector3.up, Vector3.forward, null, false);
global : : Effect.server.Run(sfx_watersplash, player.transform.position + Vector3.up, Vector3.forward, null, false);
timer.Once(0.2f, () => {
if (player == null) return;
PlayGesture(player, "friendly");
}
);
//| Dismount the player if mounted
if (HasCard(player.userID, Card.Sit)) {
TakeCard(player.userID, Card.Sit);
}
Vector3 playerFacing = player.eyes.HeadForward();
playerFacing.y = 0;
playerFacing.Normalize();
//| Sit the player
chair = InvisibleSit(player);
chair.SetParent(shark, true, true);
//| V2
chair.transform.LookAt(chair.transform.position + playerFacing);
didSit = true;
}
if (chair != null) {
//chair.transform.position = shark.transform.position + shark.transform.forward * 0.88f + shark.transform.up * 0.15f;
chair.transform.position = shark.transform.position + shark.transform.forward * 0.88f + shark.transform.up * 0.19f;
//chair.transform.LookAt(shark.transform.up * -1 + shark.transform.position + Vector3.up * 0.25f);
chair.transform.LookAt(shark.transform.position + shark.transform.up * -1 + Vector3.up * 0.15f);
}
}
shark.transform.position = Vector3.Lerp(sharkStartPos, playerStartPosition, y);
shark.transform.LookAt(player.transform.position + Vector3.up * 100 + playerForward);
shark.transform.Rotate(shark.transform.right, -15f);
yield return new WaitForFixedUpdate();
}
if (shark != null) {
shark.transform.position += Vector3.down * 100000;
shark.SendNetworkUpdate();
}
yield return null;
player?.GetMounted()?.DismountPlayer(player, true);
chair?.Kill();
player?.Die();
shark?.Kill();
}
void DoEmote(BasePlayer player, string[] args, BasePlayer admin = null) {
if (player == null) return;
string gesture = "wave";
if (args.Length > 1) {
gesture = args[1];
var g = GestureCollection.Instance.StringToGesture(gesture);
if (g == null) {
string output = "\n";
foreach (var gg in GestureCollection.Instance.AllGestures) {
output += gg.convarName + "\n";
}
PrintToPlayer(admin, $"Gesture not found: {gesture}\nAvailable Gestures:{output}");
}
}
else {
PrintToPlayer(admin, $"to see all emotes use: /emote <target> list");
}
PlayGesture(player, gesture);
TakeCard(player, Card.Emote);
}
bool? CanUseGesture(BasePlayer player, GestureConfig gesture) {
if (HasAnyCard(player.userID)) return true;
return null;
}
void ResolveConflictingCommands(BasePlayer player, BasePlayer admin = null, int ignoreCard = (int)Card.NoRest, bool fromExternalPlugin = false) {
//Puts($"Payback | ResolveConflictingCommands | HasAnyCard : {HasAnyCard(player.userID)} | Payback2 : {Payback2 != null} | IgnoreCard: {(int)ignoreCard}");
if (HasCard(player.userID, Card.Sit) && ignoreCard != (int)Card.Sit) {
TakeCard(player, Card.Sit);
}
if (HasCard(player.userID, Card.Rocketman) && ignoreCard != (int)Card.Rocketman) {
TakeCard(player, Card.Rocketman);
}
if (HasCard(player.userID, Card.Shark) && ignoreCard != (int)Card.Shark) {
TakeCard(player, Card.Shark);
}
if (Payback2 != null && !fromExternalPlugin) {
Payback2.CallHook("ResolveConflictingCommands", player, admin, ignoreCard, true);
}
if (player.isMounted) {
var car = player.GetMountedVehicle();
if (car != null) {
car.Kill(BaseNetworkable.DestroyMode.Gib);
}
var mount = player.GetMounted();
if (mount != null) {
mount.DismountPlayer(player, true);
}
}
}
//object CanNetworkTo(BaseNetworkable entity, BasePlayer target)
//{
// if (cowboynetworkables.ContainsKey(target.userID) && cowboynetworkables[target.userID].Contains(entity))
// {
// PrintToChat($"CanNetworkTo: {entity.ShortPrefabName} {target.displayName}");
// return true;
// }
// return null;
//}
//Dictionary<ulong, List<BaseNetworkable>> cowboynetworkables = new Dictionary<ulong, List<BaseNetworkable>>();
//void DoCowboy(BasePlayer player, string[] args, BasePlayer admin = null) {
// //disabled for testing
// if (player == null) return;
// if (HasCard(admin.userID, Card.Cowboy))
// {
// List<BaseNetworkable> existing;
// if (cowboynetworkables.TryGetValue(admin.userID, out existing))
// {
// if (existing != null)
// {
// existing.ForEach(x => x.Kill());
// existing.Clear();
// }
// cowboynetworkables.Remove(admin.userID);
// }
// }
// //down target player
// //disabled for testing
// player.BecomeWounded();
// player.ProlongWounding(100000000000);
// ResolveConflictingCommands(player, admin);
// //|====================================================
// //| create the chair for the person to ride
// //string innertube = "assets/prefabs/misc/summer_dlc/inner_tube/innertube.deployed.prefab";
// var chair = GameManager.server.CreateEntity(invisibleChairPrefab, player.transform.position + Vector3.up * 0.5f);
// //var chair = GameManager.server.CreateEntity(chairPrefab, player.transform.position + Vector3.up * 0.5f);
// //var chair = GameManager.server.CreateEntity(innertube, player.transform.position + Vector3.up * 0.75f);
// var mount = chair as BaseMountable;
// chair.Spawn();
// GameObject.DestroyImmediate(chair.GetComponentInChildren<DestroyOnGroundMissing>());
// GameObject.DestroyImmediate(chair.GetComponentInChildren<GroundWatch>());
// chair.GetComponentInChildren<Collider>().enabled = false;
// //|====================================================
// //| create something for the chair to parent to
// Item muzzle = ItemManager.CreateByPartialName("muzzlebrake");
// var dropped = muzzle.Drop(player.transform.position, Vector2.zero);
// DroppedItem droppedItem = dropped as DroppedItem;
// droppedItem.allowPickup = false;
// droppedItem.GetComponent<Rigidbody>().collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
// droppedItem.GetComponent<Rigidbody>().isKinematic = true;
// droppedItem.GetComponent<Rigidbody>().useGravity = false;
// SetDespawnDuration(droppedItem, 60 * 15);
// //|====================================================
// //| Do the parenting
// dropped.transform.position += Vector3.up * 0.5f;
// //chair.SetParent(dropped, true, true);
// //now we can either parent to the player, or we need to run a coroutine to bind the chair to the player
// //may need to replace this with something to track a downed player instead of rocket
// //Worker.StaticStartCoroutine(AccelerateRocketOverTime(projectile));
// //dropped.SetParent(player, true, true);
// //chair.SetParent(player, true, true);
// //timer.Once (3f, () => {
// // //chair.limitNetworking = true;
// //});
// //timer.Once(0.25f, () => {
// // if (chair != null && admin != null)
// // {
// // PrintToChat("on");
// // chair.net.SwitchGroup(Net.sv.visibility.Get(13371));
// // admin.net.SwitchGroup(Net.sv.visibility.Get(13371));
// // //admin.net.AddVisibleFromNear(Net.sv.visibility.GetGroup(admin.transform.position), new List<Network.Visibility.Group>());
// // admin.net.subscriber.Subscribe(Net.sv.visibility.GetGroup(player.transform.position));
// // }
// //});
// //timer.Once(15f, () => {
// // if (chair != null && admin != null)
// // {
// // //chair.limitNetworking = true;
// // PrintToChat("off");
// // chair.net.SwitchGroup(Net.sv.visibility.GetGroup(admin.transform.position));
// // admin.net.SwitchGroup(Net.sv.visibility.GetGroup(admin.transform.position));
// // }
// //});
// //chair._limitedNetworking = true;
// Worker.StaticStartCoroutine(MoveCowboyOverTime(player, chair));
// //mount.MountPlayer(admin);
// cowboynetworkables[admin.userID] = new List<BaseNetworkable>() { chair };
//}
//IEnumerator MoveCowboyOverTime(BasePlayer player, BaseEntity entity)
//{
// Vector3 offset = entity.transform.position - player.transform.position;
// ulong userid = player.userID;
// while (HasCard(player.userID, Card.Cowboy))
// {
// if (player != null && player.net.connection != null)
// {
// //entity.transform.position += Vector3.forward * 0.01f;
// entity.transform.position = player.transform.position + offset;
// var forward = player.eyes.HeadForward();
// forward.y = 0;
// entity.transform.LookAt(entity.transform.position + forward);
// entity.SendNetworkUpdateImmediate();
// yield return new WaitForFixedUpdate();
// } else
// {
// break;
// }
// }
// if (entity != null)
// {
// entity?.Kill();
// }
// TakeCard(userid, Card.Cowboy);
//}
Dictionary<ulong, BaseEntity> coilMap = new Dictionary<ulong, BaseEntity>();
void DoShocker(BasePlayer player, string[] args, BasePlayer admin = null) {
if (player == null) return;
BaseEntity coilEnt;
if (coilMap.TryGetValue(player.userID, out coilEnt)) {
if (coilEnt != null) {
coilEnt.Kill();
}
coilMap.Remove(player.userID);
return;
}
TeslaCoil coil = GameManager.server.CreateEntity("assets/prefabs/deployable/playerioents/teslacoil/teslacoil.deployed.prefab", player.transform.position) as TeslaCoil;
coil.transform.position += Vector3.down * 1;
coil.Spawn();
coil.SetFlag(BaseEntity.Flags.Reserved8, true);
coil.UpdateFromInput(7, 0);
coilMap.Add(player.userID, coil);
coil.SetParent(player, true, true);
coil.SendNetworkUpdateImmediate();
var los = coil.GetComponentInChildren<TargetTrigger>();
los.losEyes = null;
los.OnEntityEnter(player);
DestroyGroundCheck(coil);
Timer t = null;
t = timer.Every(0.2f, () => {
if (coil == null || player == null) {
t.Destroy();
return;
}
else {
if (Vector3.Distance(player.transform.position, coil.transform.position) < 5) {
los.OnEntityEnter(player);
}
else {
los.OnEntityLeave(player);
}
}
}
);
}
void DoBagSearch(ulong userID, string[] args, BasePlayer admin = null) {
if (userID == 0) return;
TakeCard(userID, Card.Bag);
if (args.Contains("discord")) {
Worker.StaticStartCoroutine(BagSearchCo(userID, true, admin));
}
else {
Worker.StaticStartCoroutine(BagSearchCo(userID, false, admin));
}
}
IEnumerator BagSearchCo(ulong userID, bool logToDiscord = false, BasePlayer admin = null) {
yield return null;
float timestamp = Time.realtimeSinceStartup;
float maxTimeBetweenFrames = 1 / 20f;
//| Get bags owned by player
var allBags = BaseNetworkable.serverEntities.OfType<SleepingBag>();
//var deployedByTargetBags = new List<SleepingBag>();
var useridsBaggedByTarget = new HashSet<ulong>();
var useridsWhoBaggedTarget = new HashSet<ulong>();
//find the bags that target placed
foreach (var bag in allBags) {
//| ==============================================================
if (Time.realtimeSinceStartup - timestamp > maxTimeBetweenFrames) {
yield return null;
timestamp = Time.realtimeSinceStartup;
}
//| ==============================================================
ulong ownerid = 0;
var creator = bag.creatorEntity;
if (creator != null) {
var player = creator as BasePlayer;
if (player != null) {
ownerid = player.userID;
}
}
else {
ownerid = bag.OwnerID;
}
//target bagged someone else
if (ownerid == userID && bag.deployerUserID != userID) {
//deployedByTargetBags.Add(bag);
useridsBaggedByTarget.Add(bag.deployerUserID);
}
//someone bagged in target
if (userID == bag.deployerUserID && ownerid != userID) {
useridsWhoBaggedTarget.Add(ownerid);
}
}
var messageData = new Dictionary<string, string>();
string targetInfo = $"{TryGetDisplayName(userID)}";
string baggedByString = "";
string output = $"Players bagged by {targetInfo}:";
foreach (var userid in useridsBaggedByTarget) {
var displayname = TryGetDisplayName(userid);
output += $"\n{userid} : {displayname}";
baggedByString += $"{userid} : {displayname}\n";
}
if (baggedByString.Length > 0) {
messageData.Add($"Players bagged by {targetInfo}", baggedByString);
}
else {
messageData.Add($"Players bagged by {targetInfo}", "none");
}
output += $"\nSteamids who bagged in {targetInfo}:";
string baggedInString = "";
foreach (var userid in useridsWhoBaggedTarget) {
var displayname = TryGetDisplayName(userid);
output += $"\n{userid} : {displayname}";
baggedInString += $"\n{userid} : {displayname}";
}
if (baggedInString.Length > 0) {
messageData.Add($"Players who bagged in {targetInfo}", baggedInString);
}
else {
messageData.Add($"Players who bagged in {targetInfo}", "none");
}
PrintToPlayer(admin, $"{output}");
if (logToDiscord) {
SendToDiscordWebhook(messageData, $"Bag Search [{userID}]");
}
}
bool flag_kill_no_loot = false;
void GiveAdminHammer(BasePlayer admin) {
if (admin == null) return;
var item = ItemManager.CreateByName("hammer", 1, 2375073548);
if (item != null) {
GiveItemOrDrop(admin, item, false);
}
}
object OnStructureRepair(BaseCombatEntity entity, BasePlayer player) {
if (HasCard(player.userID, Card.Hammer)) {
Worker.StaticStartCoroutine(DeleteByCo(entity.OwnerID, player.transform.position, player));
}
return null;
}
IEnumerator DeleteByCo(ulong steamid, Vector3 position, BasePlayer admin = null) {
yield return null;
if (steamid == 0UL) {
yield break;
}
float maxTimeBetweenFrames = 1 / 60f;
int maxEntitiesPerFrame = 1;
float delayBetweenFrames = 1 / 20f;
float time
// ... [Code preview truncated due to length. Full source in attached file] ...