C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Collections;
using System;
using Oxide.Game.Rust.Cui;
using UnityEngine.Events;
using Oxide.Core.Plugins;
using Oxide.Core;
using System.Linq;
namespace Oxide.Plugins {
[Info("PersonalNPC", "walkinrey", "1.6.41")]
[Description("This plugin was fixed by Инкуб to order [Rust Plugin Sliv]: https://discord.gg/pFgKw6Dyyq")]
public class PersonalNPC : RustPlugin {
public static PersonalNPC Instance;
[PluginReference]
private Plugin ImageLibrary, VehicleDeployedLocks, MarkerManager, PNPCAddonHeli, ZoneManager;
private Dictionary<ulong, PlayerBotController> _existsControllers = new Dictionary<ulong, PlayerBotController>();
private Dictionary<ulong, BotOwnerComponent> _existsBots = new Dictionary<ulong, BotOwnerComponent>();
private List<string> _permissionKeys = new List<string>();
private List<ulong> _pendingSpawnBots = new List<ulong>();
private Dictionary<ulong, DateTime> _cooldownInfo = new Dictionary<ulong, DateTime>();
private static string _noCooldownPermission = "personalnpc.nocooldown";
public OnControllerCreatedEvent OnControllerCreated = new OnControllerCreatedEvent();
#region Config
private Configuration _config;
public class Configuration {
[JsonProperty("Control setup")]
public ControlsSetup controls = new ControlsSetup();
[JsonProperty("GUI customization")]
public GUIOptions gui = new GUIOptions();
[JsonProperty("Bot settings by permission")]
public Dictionary<string, BotSetup> permissionBot = new Dictionary<string, BotSetup>();
[JsonProperty("Bot install by item")]
public List<ItemInfo> installItem = new List<ItemInfo>();
[JsonProperty("How many seconds will the bot update the information? (affects the performance and operation of the bot)")]
public float mainProcessTimer = 0.01f;
[JsonProperty("Spawn a backpack with his items when a bot dies? (otherwise his corpse will spawn)")]
public bool enableBackpackOnDeath = false;
[JsonProperty("List of prefabs that the bot can loot (useful if the bot attacks loot instead of looting it)")]
public List<string> allowedLootPrefabs = new List<string>();
public struct ItemInfo {
[JsonProperty("Item name")]
public string name;
[JsonProperty("Item shortname")]
public string shortname;
[JsonProperty("Item skin")]
public ulong skin;
[JsonProperty("Bot info")]
public BotSetup bot;
}
public class ControlsSetup {
[JsonIgnore]
public BUTTON controlButton = BUTTON.FIRE_THIRD;
[JsonProperty("Which button will assign tasks to the bot, kill/get/collect, etc.(MIDDLE_MOUSE, SECOND_MOUSE, E, RELOAD, SPRINT)")]
public string mainControlButton = "MIDDLE_MOUSE";
[JsonProperty("Range of the task assignment button")]
public float rayLength = 25f;
[JsonProperty("Display 3D arrows over a target?")]
public bool enableArrowView = true;
[JsonProperty("Arrow display duration")]
public int arrowViewDuration = 2;
[JsonProperty("Distance between owner and bot in follow state")]
public float followDistance = 2f;
[JsonProperty("Distance between owner and bot to recover")]
public float recoverDistance = 3f;
[JsonProperty("Distance between bot and collectable entity to pickup")]
public float collectableDistance = 2f;
[JsonProperty("Distance between bot and item to pickup")]
public float itemPickupDistance = 2f;
[JsonProperty("Distance between bot and loot container to loot")]
public float lootContainerDistance = 2f;
[JsonProperty("Distance between bot and tree/ore to gather")]
public float gatherDistance = 3f;
[JsonProperty("Distance between bot and seat to mount")]
public float mountDistance = 3f;
[JsonProperty("Distance between bot and enemy")]
public float enemyDistance = 3f;
[JsonProperty("Maximum distance bot will remember target")]
public float maxDistanceRemember = 30f;
[JsonProperty("Spawn personal bot on player connect?")]
public bool spawnOnConnect = false;
[JsonProperty("Block bot spawn in safezones")]
public bool blockBotSpawnSafezone = false;
[JsonProperty("Cooldown on PNPC commands")]
public float pnpcCommandsCooldown = 0.5f;
[JsonProperty("Block bot spawn in ZoneManager zones (enter zone id belove)")]
public List<string> blockBotZoneManager = new List<string>();
[JsonProperty("Chat commands to execute on player connect (works only if you have enabled spawn personal bot on connect)")]
public List<string> chatCommandsOnConnect = new List<string>();
[JsonProperty("Chat commands to execute on /pnpc (on personal npc spawn)")]
public List<string> chatCommandsOnSpawn = new List<string>();
}
public class GUIOptions {
[JsonProperty("How many seconds to update the GUI?")]
public float guiRefreshTime = 6f;
[JsonProperty("Panel layer (Hud, Overlay, Overall, Hud.Menu, Under)")]
public string panelLayer = "Overlay";
[JsonProperty("Send commands to local chat? (required for hardcore mode, where global chat is disabled)")]
public bool useLocal = false;
[JsonProperty("Panel position adjustment")]
public CuiRectTransformComponent panelPosition = new CuiRectTransformComponent();
[JsonProperty("1 panel color")]
public string panelColor1 = "#7f8c8d";
[JsonProperty("2 panel color")]
public string panelColor2 = "#bdc3c7";
[JsonProperty("Health bar color")]
public string panelHealthColor = "#2ecc71";
[JsonProperty("Show shortcut buttons when bot is spawned?")]
public bool showShortcutButtons = false;
[JsonProperty("Lock shortcut buttons?")]
public bool lockShortcutButtons = false;
[JsonProperty("Hide (minimize) GUI on bot spawn?")]
public bool autoMinimize = false;
[JsonProperty("Shortcut buttons")]
public List<AccessButton> accessButtons = new List<AccessButton>();
public class AccessButton {
[JsonProperty("Text on button")]
public string text = "";
[JsonProperty("Executable chat commands")]
public string[] commands = new string[] {
}
;
public AccessButton(string btnText, string[] btnCommand) {
text = btnText;
commands = btnCommand;
}
}
}
public class BotSetup {
[JsonProperty("Bot spawn delay")]
public float cooldown = 300f;
[JsonProperty("The name of the bot to be selected through the command when spawning")]
public string spawnName = "bot1";
[JsonProperty("Bot name")]
public string name = "Personal Bot of player %OWNER_NAME%";
[JsonProperty("Bot appearance (0 - random)")]
public ulong skin = 0;
[JsonProperty("Maximum health")]
public float maxHealth = 150f;
[JsonProperty("Bot speed (slowest, slow, normal, fast)")]
public string speed = "normal";
[JsonProperty("Enable infinite ammo for the bot?")]
public bool infiniteAmmo = true;
[JsonProperty("Enable display of the bot on the map? (frankenstein icon)")]
public bool enableMapView = true;
[JsonProperty("Drop active item on death?")]
public bool dropActiveItem = false;
[JsonProperty("Can player open bot's inventory through '/pnpc inventory' command?")]
public bool inventoryCommand = false;
[JsonProperty("Can other players loot bot's corpse?")]
public bool canLootCorpse = false;
[JsonProperty("Teleport bot to owner when clicking follow?")]
public bool teleportFollow = false;
[JsonProperty("Steam ID for chat icon (leave 0 if not needed)")]
public string chatIconSteamID = "";
[JsonProperty("Start kit")]
public List<ItemSetup> startKit = new List<ItemSetup>();
[JsonProperty("Functions setup")]
public FunctionsSetup functions = new FunctionsSetup();
[JsonProperty("Gather setup")]
public GatherSetup gather = new GatherSetup();
[JsonProperty("Damage and interactions setup")]
public TargetSetup target = new TargetSetup();
[JsonProperty("Death Marker (marker will be only visible for owner)")]
public DeathMarkerSetup deathMarker = new DeathMarkerSetup();
[JsonProperty("Black list of items that cannot be put into the inventory of the bot")]
public string[] itemBlacklist = {
"rocket.launcher"
}
;
[JsonProperty("List of prefabs that the bot will ignore if they attack it")]
public string[] attackIgnore = {
"assets/prefabs/deployable/bear trap/beartrap.prefab"
}
;
public class DeathMarkerSetup {
[JsonProperty("Show marker on bot's death position?")]
public bool enableMarker = false;
[JsonProperty("Display name on map")]
public string displayName = "Bot's death marker";
[JsonProperty("Marker radius")]
public float radius = 0.35f;
[JsonProperty("Outline color (hex)")]
public string outline = "00FFFFFF";
[JsonProperty("Main color (hex)")]
public string main = "00FFFF";
[JsonProperty("Alpha")]
public float alpha = 0.5f;
[JsonProperty("Duration")]
public int duration = 20;
}
public class TargetSetup {
[JsonProperty("Bot damage rate")]
public float botDamageRate = 2f;
[JsonProperty("Bot recive damage rate")]
public float botHurtRate = 0.5f;
[JsonProperty("Can players damage the bot?")]
public bool enablePlayerDamage = true;
[JsonProperty("Can the bot damage players?")]
public bool enablePlayerHurt = true;
[JsonProperty("Can bot damage other personal npc bots?")]
public bool enablePersonalBotHurt = false;
[JsonProperty("Can turrets target and kill a bot? (all turrets will not be able to damage the bot)")]
public bool enableTurretTargeting = false;
[JsonProperty("Prevent bot owner turrets from aiming and killing the bot? (bot owner's turrets will not be able to damage the bot)")]
public bool blockOwnerTurretTargeting = true;
[JsonProperty("Cooldown before switching to another target (useful when bot is being attacked from multiple enemies)")]
public float switchTargetCooldown = 3f;
[JsonProperty("Attack aim offset")]
public Vector3 aimOffset = new Vector3(0, -0.5f, -0.3f);
[JsonProperty("Aim offset when player is wounded")]
public Vector3 aimWoundedOffset = new Vector3(0, 1f);
[JsonProperty("Blacklist of objects that the bot will ignore when owner selecting a target (short prefab name)")]
public string[] inputBlacklist = new string[] {
}
;
[JsonProperty("BossMonster names to prevent targeting them (if you've BossMonster plugin)")]
public string[] bossesNames = new string[] {
}
;
}
public class GatherSetup {
[JsonProperty("Shortname of items that can harvest trees")]
public List<string> toolForTrees = new List<string>();
[JsonProperty("Shortname of items that can mine stones and ore")]
public List<string> toolForStones = new List<string>();
[JsonProperty("Setting up mining rates")]
public Dictionary<string, float> gatherRates = new Dictionary<string, float>();
[JsonProperty("Radius to collect/gather resources in auto-mode")]
public float autoModeRadius = 50f;
}
public class FunctionsSetup {
[JsonProperty("Can a bot loot crates?")]
public bool canLootBoxes = true;
[JsonProperty("Can the bot mine trees and stones?")]
public bool canGatherResources = true;
[JsonProperty("Can the bot pick up resources? (wood, sulfur and metal ore, stones)")]
public bool canCollectResources = true;
[JsonProperty("Should the bot protect the owner?")]
public bool canProtectOwner = true;
[JsonProperty("Should the bot defend itself?")]
public bool canProtectSelf = true;
[JsonProperty("Can the bot travel by car/copter and other vehicles?")]
public bool canMount = true;
[JsonProperty("Ignore vehicle lock (VehicleDeployedLocks plugin)")]
public bool ignoreVehicleLock = true;
[JsonProperty("Can the bot pick up dropped items?")]
public bool canCollectDroppedItems = true;
[JsonProperty("Recover the owner from a wounded state")]
public RecoverSetup recoverSetup = new RecoverSetup();
[JsonProperty("PVP Mode (/pnpc pvp)")]
public PVPSetup pvpSetup = new PVPSetup();
[JsonProperty("Loot All (/pnpc loot-all)")]
public LootAllSetup lootAllSetup = new LootAllSetup();
[JsonProperty("Self Heal")]
public SelfHealSetup selfHeal = new SelfHealSetup();
[JsonProperty("Can the bot attack other people's buildings?")]
public bool canAttackEnemyBuildings = true;
[JsonProperty("Can a bot attack its owner's buildings?")]
public bool canAttackOwnerBuildings = false;
[JsonProperty("Can the bot collect resources within a radius of 50 meters? (/pnpc auto-pickup)")]
public bool canAutoPickup = true;
[JsonProperty("Can the bot farm resources within a radius of 50 meters? (/pnpc auto-farm)")]
public bool canAutoFarm = true;
[JsonProperty("Enable bot's inventory?")]
public bool enableBotInventory = true;
[JsonProperty("Lock bot's wear slots?")]
public bool blockWearSlots = false;
[JsonProperty("Lock bot's main slots?")]
public bool blockMainSlots = false;
[JsonProperty("Lock bot's equipment slots?")]
public bool blockEquipmentSlots = false;
[JsonProperty("Can the bot fly on helicopters? (PNPC Heli AI Addon plugin)")]
public bool enableHeliAddon = false;
[JsonProperty("Can the bot drive cars? (PNPC Addon Car AI plugin)")]
public bool enableCarAddon = false;
public class SelfHealSetup {
[JsonProperty("Should bot heal himself?")]
public bool enableHealing = false;
[JsonProperty("Bot will heal himself when his health is below this value")]
public float belowValue = 20f;
[JsonProperty("Items to heal (you can set list by priority)")]
public List<string> healItems = new List<string>();
}
public class LootAllSetup {
[JsonProperty("Enable Loot All command (/pnpc loot-all)")]
public bool enableLootAll = false;
[JsonProperty("Resources detect radius")]
public float radius = 15f;
[JsonProperty("Loot containers?")]
public bool lootContainers = true;
[JsonProperty("Loot corpses?")]
public bool lootCorpses = true;
[JsonProperty("Loot dropped items?")]
public bool lootDroppedItems = true;
}
public class PVPSetup {
[JsonProperty("Enable PVP mode (attack all bots and players in radius, /pnpc pvp)")]
public bool enablePVP = false;
[JsonProperty("Detect radius")]
public float radius = 10f;
[JsonProperty("Ignore bots?")]
public bool ignoreBots = false;
[JsonProperty("Ignore personal npc bots?")]
public bool ignorePersonalNPC = true;
[JsonProperty("Ignore players?")]
public bool ignorePlayers = true;
[JsonProperty("Ignore by short prefab name")]
public List<string> ignorePrefabs = new List<string>();
}
public class RecoverSetup {
[JsonProperty("Can the bot recover the owner if he is in a wounded state?")]
public bool canRecover = true;
[JsonProperty("Recover time")]
public float _recoverTime = 6f;
}
}
public class ItemSetup {
[JsonProperty("Item name")]
public string name = "";
[JsonProperty("Item shortname")]
public string shortname = "";
[JsonProperty("Item skin")]
public ulong skin = 0;
[JsonProperty("Item amount")]
public int amount = 1;
[JsonProperty("In which container to place? (belt, main, wear)")]
public string container = "main";
}
}
}
protected override void LoadDefaultConfig() {
_config = new Configuration();
_config.allowedLootPrefabs.Add("vehicle_parts");
_config.permissionBot.Add("personalnpc.bot1", new Configuration.BotSetup {
name = "Personal bot of player %OWNER_NAME%", startKit = new List<Configuration.BotSetup.ItemSetup> {
new Configuration.BotSetup.ItemSetup {
shortname = "shoes.boots", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "pants", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "hoodie", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "mask.bandana", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "hat.boonie", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "sunglasses", container = "wear"
}
}
, gather = new Configuration.BotSetup.GatherSetup {
toolForTrees = new List<string> {
"hatchet", "chainsaw", "hammer.salvaged", "stonehatchet", "axe.salvaged"
}
, toolForStones = new List<string> {
"pickaxe", "stone.pickaxe", "hammer.salvaged", "jackhammer", "icepick.salvaged"
}
, gatherRates = new Dictionary<string, float> {
["stones"]
= 2f, ["wood"] = 5f
}
}
, target = new Configuration.BotSetup.TargetSetup {
inputBlacklist = new string[] {
"barricade.sandbags"
}
}
, functions = new Configuration.BotSetup.FunctionsSetup {
selfHeal = new Configuration.BotSetup.FunctionsSetup.SelfHealSetup {
healItems = new List<string> {
"largemedkit", "syringe.medical", "bandage",
}
}
}
}
);
_config.installItem.Add(new Configuration.ItemInfo {
name = "PersonalNPC", shortname = "furnace", skin = 2741314889, bot = new Configuration.BotSetup {
name = "Personal bot of player %OWNER_NAME%", startKit = new List<Configuration.BotSetup.ItemSetup> {
new Configuration.BotSetup.ItemSetup {
shortname = "shoes.boots", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "pants", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "hoodie", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "mask.bandana", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "hat.boonie", container = "wear"
}
, new Configuration.BotSetup.ItemSetup {
shortname = "sunglasses", container = "wear"
}
}
, gather = new Configuration.BotSetup.GatherSetup {
toolForTrees = new List<string> {
"hatchet", "chainsaw", "hammer.salvaged", "stonehatchet", "axe.salvaged"
}
, toolForStones = new List<string> {
"pickaxe", "stone.pickaxe", "hammer.salvaged", "jackhammer", "icepick.salvaged"
}
, gatherRates = new Dictionary<string, float> {
["stones"]
= 2f, ["wood"] = 5f
}
}
, target = new Configuration.BotSetup.TargetSetup {
inputBlacklist = new string[] {
"barricade.sandbags"
}
}
}
}
);
_config.gui.panelPosition = new CuiRectTransformComponent {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-170 -104", OffsetMax = "-10 -10"
}
;
_config.gui.accessButtons.Add(new Configuration.GUIOptions.AccessButton("Auto-Farm: Wood", new string[] {
"pnpc auto-farm wood", "pnpc auto-farm enable"
}
));
_config.gui.accessButtons.Add(new Configuration.GUIOptions.AccessButton("Auto-Farm: Stone", new string[] {
"pnpc auto-farm stone", "pnpc auto-farm enable"
}
));
_config.gui.accessButtons.Add(new Configuration.GUIOptions.AccessButton("Auto-Pickup: Wood", new string[] {
"pnpc auto-pickup wood", "pnpc auto-pickup enable"
}
));
_config.gui.accessButtons.Add(new Configuration.GUIOptions.AccessButton("Auto-Pickup: Stone", new string[] {
"pnpc auto-pickup stone", "pnpc auto-pickup enable"
}
));
}
protected override void LoadConfig() {
base.LoadConfig();
try {
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
SaveConfig();
}
catch (Exception ex) {
PrintError("{0}", ex);
LoadDefaultConfig();
}
}
protected override void SaveConfig() => Config.WriteObject(_config);
#endregion
#region Loc
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["ChatCommand_Success_Despawn"]
= "Ваш персональный бот успешно задеспавнен!", ["ChatCommand_Success_Spawn"] = "Ваш персональный бот успешно заспавнен!", ["ChatCommand_Notice_Ignore_Activated"] = "Бот теперь игнорирует тех, кто атакует его и хозяина", ["ChatCommand_Notice_Ignore_Deactivated"] = "Бот теперь не игнорирует тех, кто атакует его и хозяина", ["ChatCommand_Notice_Combat_Activated"] = "Бот теперь атакует тех, кого атакует хозяин", ["ChatCommand_Notice_Combat_Deactivated"] = "Бот теперь не атакует тех, кого атакует хозяин", ["ChatCommand_Notice_PVP_Activated"] = "Бот теперь атакует всех ботов и игроков которых нет в команде хозяин", ["ChatCommand_Notice_PVP_Deactivated"] = "Бот больше не атакует всех ботов и игроков которых нет в команде хозяина", ["ChatCommand_Notice_Cooldown"] = "Вам нужно подождать {0} секунд, прежде чем повторно заспавнить бота!", ["ChatCommand_Notice_Location"] = "Ваш бот находится в квадрате: {0}, расстояние до бота: {1}", ["ChatCommand_Notice_Health"] = "Здоровье вашего бота: {0}/{1}", ["ChatCommand_Notice_Follow"] = "Бот теперь следует за вами!", ["ChatCommand_Notice_AvailableBots"] = "<size=16>Доступные боты:</size>\n{BOTS}\n\nВведите /pnpc [короткое название бота], чтобы заспавнить!", ["ChatCommand_Error_AutoPickup"] = "<size=16>Авто-подбор ресурсов</size>\n\nБот начнет собирать все ресурсы в радиусе 50 метров от его первоначальной точки.\n\nДоступные режимы: all, wood, stone, metal, sulfur, hemp, berries, pumpkin, mushroom, corn\nОтключить - /pnpc auto-pickup disable", ["ChatCommand_Error_AutoFarm"] = "<size=16>Авто-фарм ресурсов</size>\n\nБот начнет фармить все ресурсы в радиусе 50 метров от его первоначальной точки.\n\nДоступные режимы: all, wood, stone, metal, sulfur\nОтключить - /pnpc auto-farm disable", ["ChatCommand_Error_NoPermission"] = "У вас нет разрешения на спавн персонального бота", ["ChatCommand_Error_CannotUse"] = "Ваш бот не обладает такой функцией, вы не можете ее использовать!", ["ChatCommand_Error_NoBot"] = "У вас нет персонального бота!", ["ChatCommand_Error_NotFounded"] = "Бот не найден!", ["ChatCommand_Error_Blacklist"] = "Этот предмет добавлен в черный список, вы не можете дать его боту!", ["ChatCommand_Error_Contents_Blacklist"] = "У предмета есть содержимое, которое добавлено в черный список.Вы не можете дать этот предмет боту!", ["ChatCommand_Error_NoSpawnHere"] = "Вы не можете заспавнить персонального бота здесь!", ["ChatCommand_Notice_AutoPickup_Status"] = "Авто-подбор ресурсов: {0}\nРесурсы для сбора: {1}", ["ChatCommand_Notice_AutoFarm_Status"] = "Авто-фарм ресурсов: {0}\nРесурсы для фарма: {1}", ["ChatCommand_AutoMode_Resources_All"] = "все", ["ChatCommand_AutoMode_Resources_Wood"] = "дерево", ["ChatCommand_AutoMode_Resources_Stone"] = "камень", ["ChatCommand_AutoMode_Resources_Sulfur"] = "сера", ["ChatCommand_AutoMode_Resources_Metal"] = "металл", ["ChatCommand_AutoMode_Resources_Hemp"] = "ткань", ["ChatCommand_AutoMode_Resources_Berries"] = "ягоды", ["ChatCommand_AutoMode_Resources_Corn"] = "кукуруза", ["ChatCommand_AutoMode_Resources_Mushroom"] = "гриб", ["ChatCommand_AutoMode_Resources_Pumpkin"] = "тыква", ["ChatCommand_AutoMode_Resources_Barrels"] = "бочки", ["ChatCommand_AutoMode_Status_Disabled"] = "отключён", ["ChatCommand_AutoMode_Status_Enabled"] = "включён", ["Chat_Commands_TooFast"] = "Вы вводите команды слишком быстро, подождите немного!", ["Bot_Notice_Recover"] = "Поднял вас, возвращаюсь к заданию!", ["Bot_Notice_MissionCompleted"] = "Цель выполнена, возвращаюсь к вам!", ["Bot_Notice_GoingCollect"] = "Иду собирать ресурс!", ["Bot_Notice_GoingFarm"] = "Иду добывать ресурс!", ["Bot_Notice_GoingLootBox"] = "Иду лутать ящик!", ["Bot_Notice_Following"] = "Следую за вами!", ["Bot_Notice_Staying"] = "Стою на позиции.", ["Bot_Notice_StartedAttack"] = "Начинаю атаку!", ["Bot_Notice_GoingCollectItem"] = "Иду подбирать предмет!", ["Bot_Notice_GoingPosition"] = "Иду на позицию.", ["Bot_Notice_GoingLootCorpse"] = "Иду лутать труп!", ["Bot_Error_NoTool"] = "Нечем добывать ресурс!", ["Bot_Error_NoWeapon"] = "Нет оружия чтобы атаковать!", ["Bot_Error_PickupBrokenItem"] = "Нельзя подбирать сломанные вещи!", ["Bot_Error_NoAmmo"] = "Нет патрон у оружия чтобы атаковать!", ["Bot_Error_NoResourcesAround"] = "Нет ресурсов поблизости!", ["Bot_Error_Chainsaw_NoFuel"] = "Нет топлива в бензопиле!", ["Bot_Error_AutoFarm_NoResourcesAroundOrNoTool"] = "Нет ресурсов поблизости либо нет инструмента чтобы добыть ресурс!", ["Bot_Error_Dead_NotOwner"] = "Вы не являетесь владельцом этого бота и не можете его залутать!", ["Bot_Error_Loot_HackableCrate"] = "Ящик еще не взломан!", ["Bot_Error_FlyAddon_NoPlayerToFollow"] = "Игрок для слежки не найден!", ["GUI_Header"] = "Управление NPC", ["GUI_Follow"] = "Следовать", ["GUI_Kill"] = "Убить",
}
, this, "ru");
lang.RegisterMessages(new Dictionary<string, string> {
["ChatCommand_Success_Despawn"]
= "Your personal bot has been successfully deleted!", ["ChatCommand_Success_Spawn"] = "Your personal bot has been successfully spawned!", ["ChatCommand_Notice_Ignore_Activated"] = "The bot now ignores those who attack it and the owner", ["ChatCommand_Notice_Ignore_Deactivated"] = "The bot no longer ignores those who attack it and the owner", ["ChatCommand_Notice_Combat_Activated"] = "Bot now attacks those who are attacked by the owner", ["ChatCommand_Notice_Combat_Deactivated"] = "The bot no longer attacks those who are attacked by the owner", ["ChatCommand_Notice_PVP_Activated"] = "Bot now attacks all bots and players that aren't in owner's team", ["ChatCommand_Notice_PVP_Deactivated"] = "Bot no longer attacks all bots and players that aren't in owner's team", ["ChatCommand_Notice_Cooldown"] = "You need to wait {0} seconds before re-spawning the bot!", ["ChatCommand_Notice_Location"] = "Your bot is in the grid: {0}, distance to the bot: {1}", ["ChatCommand_Notice_Health"] = "Your bot health: {0} / {1}", ["ChatCommand_Notice_Follow"] = "The bot is now following you!", ["ChatCommand_Notice_AvailableBots"] = "<size=16>Available bots:</size>\n{BOTS}\n\nEnter /pnpc [short bot name] to spawn!", ["ChatCommand_Error_AutoPickup"] = "<size=16>Auto-collecting resources</size>\n\nThe bot will start collecting all resources within a radius of 50 meters from its original point.\n\nAvailable modes: all, wood, stone, metal, sulfur, hemp, berries, pumpkin, mushroom, corn\nDisable - /pnpc auto-pickup disable", ["ChatCommand_Error_AutoFarm"] = "<size=16>Auto-farm resources</size>\n\nThe bot will start farming all resources within a radius of 50 meters from its original point.\n\nAvailable modes: all, wood, stone, metal, sulfur\nDisable - /pnpc auto-farm disable", ["ChatCommand_Error_NoPermission"] = "You don't have permission to spawn a personal bot", ["ChatCommand_Error_CannotUse"] = "Your bot doesn't have this feature, you can't use it!", ["ChatCommand_Error_NoBot"] = "You don't have a personal bot!", ["ChatCommand_Error_NotFounded"] = "Bot not found!", ["ChatCommand_Error_Blacklist"] = "This item has been blacklisted, you cannot give it to the bot!", ["ChatCommand_Error_Contents_Blacklist"] = "This item has contents that has been blacklisted.You cannot give this item to a bot!", ["ChatCommand_Error_NoSpawnHere"] = "You can't spawn a personal bot here!", ["ChatCommand_Notice_AutoPickup_Status"] = "Auto-collect resources: {0}\nResources to collect: {1}", ["ChatCommand_Notice_AutoFarm_Status"] = "Auto-farm resources: {0}\nResources to farm: {1}", ["ChatCommand_AutoMode_Resources_All"] = "all", ["ChatCommand_AutoMode_Resources_Wood"] = "wood", ["ChatCommand_AutoMode_Resources_Stone"] = "stone", ["ChatCommand_AutoMode_Resources_Sulfur"] = "sulfur", ["ChatCommand_AutoMode_Resources_Metal"] = "metal", ["ChatCommand_AutoMode_Resources_Hemp"] = "hemp", ["ChatCommand_AutoMode_Resources_Berries"] = "berries", ["ChatCommand_AutoMode_Resources_Corn"] = "corn", ["ChatCommand_AutoMode_Resources_Mushroom"] = "mushroom", ["ChatCommand_AutoMode_Resources_Pumpkin"] = "pumpkin", ["ChatCommand_AutoMode_Resources_Barrels"] = "barrels", ["ChatCommand_AutoMode_Status_Disabled"] = "disabled", ["ChatCommand_AutoMode_Status_Enabled"] = "enabled", ["Chat_Commands_TooFast"] = "You're typing commands so fast, please wait a little!", ["Bot_Notice_Recover"] = "Recovered you, backing to mission!", ["Bot_Notice_MissionCompleted"] = "Mission сompleted, backing to you!", ["Bot_Notice_GoingCollect"] = "Going to collect resource!", ["Bot_Notice_GoingFarm"] = "Going to farm resource!", ["Bot_Notice_GoingLootBox"] = "Going to loot box!", ["Bot_Notice_Following"] = "Following you!", ["Bot_Notice_Staying"] = "Standing in position", ["Bot_Notice_StartedAttack"] = "Starting attack!", ["Bot_Notice_GoingCollectItem"] = "Going to pick up the item!", ["Bot_Notice_GoingPosition"] = "Going to the position.", ["Bot_Notice_GoingLootCorpse"] = "Going to loot corpse!", ["Bot_Error_NoTool"] = "There are no tools to mine the resource!", ["Bot_Error_NoWeapon"] = "There are no weapons to attack!", ["Bot_Error_PickupBrokenItem"] = "You cannot pickup broken items!", ["Bot_Error_NoAmmo"] = "There is no ammo for the weapon to attack!", ["Bot_Error_NoResourcesAround"] = "No resources nearby!", ["Bot_Error_AutoFarm_NoResourcesAroundOrNoTool"] = "No resources nearby or bot doesn't have any tools to farm resources!", ["Bot_Error_Chainsaw_NoFuel"] = "No fuel in chainsaw!", ["Bot_Error_Dead_NotOwner"] = "You are not the owner of this bot and you can not loot it!", ["Bot_Error_Loot_HackableCrate"] = "Crate is not hacked yet!", ["Bot_Error_FlyAddon_NoPlayerToFollow"] = "Player for follow is not found!", ["GUI_Header"] = "NPC Control", ["GUI_Follow"] = "Follow", ["GUI_Kill"] = "Kill",
}
, this, "en");
}
#endregion
#region Hooks
private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null || info?.Initiator == null || entity?.net == null) return null;
BaseEntity target = info.Initiator;
if (target == null || target?.net == null) return null;
var ownerComponent = GetOwnerComponent(entity.net.ID.Value);
if (ownerComponent != null) {
if (ownerComponent.controller != null) ownerComponent.controller.OnDamage();
}
var initiatorController = GetController(target.net.ID.Value);
if (initiatorController != null) {
initiatorController.OnOwnerAttack(entity);
return null;
}
var initiatorBotOwner = GetOwnerComponent(target.net.ID.Value);
if (initiatorBotOwner != null && initiatorBotOwner?.controller != null) {
info.damageTypes?.ScaleAll(initiatorBotOwner.controller.botSetup.target.botDamageRate);
if (!initiatorBotOwner.controller.botSetup.target.enablePlayerHurt) {
var victim = entity.ToPlayer();
if (victim != null) {
if (!IsBot(victim)) {
RemoveDamage(info);
return true;
}
}
}
if (!initiatorBotOwner.controller.botSetup.target.enablePersonalBotHurt) {
if (GetOwnerComponent(entity.net.ID.Value) != null) {
RemoveDamage(info);
return true;
}
}
}
var controller = GetController(entity.net.ID.Value);
if (controller != null && controller?.bot != null) {
if (target == controller.bot) {
RemoveDamage(info);
return true;
}
controller.OnAttacked(target, info, true);
return null;
}
if (ownerComponent != null && ownerComponent?.controller != null && ownerComponent?.controller?.owner != null) {
ownerComponent.controller.RenderMenu();
if (entity == ownerComponent.controller.owner) {
RemoveDamage(info);
return true;
}
info.damageTypes?.ScaleAll(ownerComponent.controller.botSetup.target.botHurtRate);
if (!ownerComponent.controller.botSetup.target.enablePlayerDamage) {
var player = target?.ToPlayer();
if (player != null) {
if (!IsBot(player)) {
RemoveDamage(info);
return true;
}
}
}
ownerComponent.controller.OnAttacked(target, info);
}
return null;
}
private object CanBeTargeted(BaseCombatEntity player, MonoBehaviour behaviour) {
if (player == null || behaviour == null || player?.net == null) return null;
BotOwnerComponent comp = GetOwnerComponent(player.net.ID.Value);
if (comp) {
if (comp.controller == null) return null;
BaseEntity ent;
if (comp.controller.botSetup.target.blockOwnerTurretTargeting && behaviour.TryGetComponent<BaseEntity>(out ent)) {
if (ent.OwnerID == comp.controller.owner.userID) return false;
}
if (!comp.controller.botSetup.target.enableTurretTargeting) return false;
}
return null;
}
private void OnPlayerDisconnected(BasePlayer player, string reason) => _pendingSpawnBots.Remove(player.userID);
private void OnPlayerRespawned(BasePlayer player) {
if (_pendingSpawnBots.Contains(player.userID)) OnPlayerConnected(player);
}
private void OnPlayerConnected(BasePlayer player) {
if (_config.controls.spawnOnConnect) {
var botSetup = GetBotSetup(player);
if (botSetup?.Count != 0) {
_pendingSpawnBots.Remove(player.userID);
if (player.IsAlive()) {
chatCommand(player, "pnpc", new string[] {
botSetup[0].spawnName
}
);
foreach (var command in _config.controls.chatCommandsOnConnect) {
string[] splitted = command.Split(' ');
if (splitted.Length == 1) chatCommand(player, splitted[0], new string[] {
}
);
else {
var splittedList = new List<string>(splitted);
splittedList.RemoveAt(0);
chatCommand(player, splitted[0], splittedList.ToArray());
}
}
}
else _pendingSpawnBots.Add(player.userID);
}
}
}
private object OnPlayerDeath(BasePlayer player, HitInfo info) {
if (player == null || player?.net == null) return null;
if (IsBot(player)) {
var botComponent = GetOwnerComponent(player.net.ID.Value);
if (botComponent != null) {
var controller = botComponent.controller;
if (controller != null) {
foreach (var item in player.inventory.containerMain.itemList) {
if (item == null) continue;
var held = item.GetHeldEntity();
if (held != null) EmptyContents(held);
}
foreach (var item in player.inventory.containerBelt.itemList) {
if (item == null) continue;
var held = item.GetHeldEntity();
if (held != null) EmptyContents(held);
}
if (controller.botSetup.dropActiveItem && controller.botSetup.functions.enableBotInventory && !player.inventory.containerBelt.IsLocked()) {
var activeItem = player.GetActiveItem();
if (activeItem != null) activeItem.DropAndTossUpwards(player.GetDropPosition());
}
DropLoot(player, controller, info);
player.Teleport(new Vector3(0, -1000, 0));
NextTick(() => {
if (player != null && !player.IsDestroyed) player.Kill();
}
);
return false;
}
}
}
return null;
}
private void Unload() {
var finded = _existsControllers.Values;
for (int i = finded.Count - 1; i >= 0; i--) {
var obj = new List<PlayerBotController>(_existsControllers.Values)[i];
if (obj.bot != null) OnPlayerDeath(obj.bot, null);
if (obj) UnityEngine.Object.Destroy(obj);
}
foreach (var player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, "PersonalNPC_ControlPanel");
}
private object CanMoveItem(Item item, PlayerInventory playerLoot, uint targetContainer, ItemContainerId param3, int targetSlot, int amount, ItemMoveModifier param6) {
if (item == null) return null;
var held = item.GetHeldEntity();
BaseProjectile projectile = null;
if (held is BaseProjectile) projectile = held as BaseProjectile;
if (projectile == null) return null;
var player = playerLoot?.containerMain?.GetOwnerPlayer();
if (player == null) return null;
var controller = GetController(player.net.ID.Value);
if (controller == null) return null;
if (controller != null) {
if (controller.bot.inventory.containerMain.uid.Value == targetContainer || controller.bot.inventory.containerBelt.uid.Value == targetContainer || controller.bot.inventory.containerWear.uid.Value == targetContainer) {
if (controller.botSetup.itemBlacklist.Contains(item.info.shortname)) {
SendMsg(player, "ChatCommand_Error_Blacklist");
return ItemContainer.CanAcceptResult.CannotAcceptRightNow;
}
if (item.contents != null) {
if (item.contents.itemList.Count != 0) {
foreach (var contentsItem in item.contents.itemList) {
if (controller.botSetup.itemBlacklist.Contains(contentsItem.info.shortname)) {
SendMsg(player, "ChatCommand_Error_Contents_Blacklist");
return ItemContainer.CanAcceptResult.CannotAcceptRightNow;
}
}
}
}
if (projectile.primaryMagazine.contents != 0) {
if (controller.botSetup.itemBlacklist.Contains(projectile.primaryMagazine.ammoType.shortname)) {
SendMsg(player, "ChatCommand_Error_Contents_Blacklist");
return ItemContainer.CanAcceptResult.CannotAcceptRightNow;
}
}
}
}
if (controller != null) {
if (controller.botSetup.infiniteAmmo) {
var looting = player.inventory.loot.entitySource;
if (looting != null) {
if (looting is LootableCorpse) {
var corpse = looting as LootableCorpse;
if (corpse.playerName == controller.bot?.displayName) {
if (playerLoot.containerMain.uid.Value == targetContainer || playerLoot.containerBelt.uid.Value == targetContainer || playerLoot.containerWear.uid.Value == targetContainer) {
if (player.inventory.loot.containers.Contains(item.parent)) EmptyContents(projectile);
return null;
}
if (projectile.primaryMagazine.contents > 0 && targetContainer != 0) {
if (controller.bot.inventory.containerMain.uid.Value == targetContainer || controller.bot.inventory.containerBelt.uid.Value == targetContainer || controller.bot.inventory.containerWear.uid.Value == targetContainer) {
var itemOwner = item.parent?.GetOwnerPlayer();
// ... [Code preview truncated due to length. Full source in attached file] ...