C#:
using Newtonsoft.Json;
using Oxide.Core;
using Rust;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using Network;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using System.Collections;
using System.Text;
namespace Oxide.Plugins {
[Info("XDQuest", "DezLife", "2.0.5")]
[Description("Расширенная квест система для вашего сервера!")]
public class XDQuest : RustPlugin {
#region Var
private const string AuthorContact = "DezLife#1480 \nvk.com/dezlife";
private const string filename = "XDQuestHouseNPC";
private static XDQuest Instance;
MonumentInfo monument;
HashSet<Item> ItemForce = new HashSet<Item>();
private BasePlayer npc;
private List<BaseEntity> HouseNPC = new List<BaseEntity>();
private Dictionary<string, string> ImageUI = new Dictionary<string, string>() {
{
"MAINFON", "https://i.imgur.com/sV7tvFE.png"
}
, {
"QUESTFON", "https://i.imgur.com/3yfcpYV.png"
}
, {
"DOWNBTN", "https://i.imgur.com/VYdpOFv.png"
}
, {
"UPBTN", "https://i.imgur.com/3E9KNpZ.png"
}
, {
"BluePrint", "https://i.imgur.com/b48U2XA.png"
}
, {
"InProcces", "https://i.imgur.com/IKE6USt.png"
}
, {
"CloseUI", "https://i.imgur.com/7oInHGR.png"
}
}
;
#region Ref
[PluginReference]
Plugin CopyPaste, ImageLibrary, IQChat, Friends, Clans, Battles, Duel;
public void SendChat(BasePlayer player, string Message, ConVar.Chat.ChatChannel channel = ConVar.Chat.ChatChannel.Global) {
if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, Message, config.settingsIQChat.prifix, config.settingsIQChat.SteamID);
else player.SendConsoleCommand("chat.add", channel, 0, Message);
}
public bool IsFriends(ulong userID, ulong targetID) {
if (Friends) return (bool)Friends?.Call("HasFriend", userID, targetID);
else return false;
}
public bool IsClans(ulong userID, ulong targetID) {
if (Clans) return (bool)Clans?.Call("HasFriend", userID, targetID);
else return false;
}
public bool IsDuel(ulong userID) {
if (Battles) return (bool)Battles?.Call("IsPlayerOnBattle", userID);
else if (Duel) return (bool)Duel?.Call("IsPlayerOnActiveDuel", BasePlayer.FindByID(userID));
else return false;
}
public string GetImage(string shortname, ulong skin = 0) => (string)ImageLibrary?.Call("GetImage", shortname, skin);
public bool AddImage(string url, string shortname, ulong skin = 0) => (bool)ImageLibrary?.Call("AddImage", url, shortname, skin);
public void SendImage(BasePlayer player, string imageName, ulong imageId = 0) => ImageLibrary?.Call("SendImage", player, imageName, imageId);
#endregion
#endregion
#region Lang
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["QUEST_ACTIVE"]
= "Your active tasks: {0}", ["NOT_QUEST_ACTIVE"] = "You have no active tasks", ["QUEST_Insufficient_resources"] = "You don't have {0}, you should definitely bring this to Sidorovich", ["QUEST_not_resources"] = "You don't have enough {0}, you need {1}", ["QUEST_ACTIVE_COMPLITE"] = "{0}\nQuests completed!\nDo not forget to hand it over to Sidorovich.", ["NOT_QUEST_ACTIVE_COMPLITE"] = "<size=9>{0}</size>\nLeft: {1}\n{2}", ["AVAILABLE_MISSIONS"] = "<b>AVAILABLE JOBS</b><size=14>({0})</size>", ["ACTIVE_MISSIONS"] = "<b>ACTIVE JOBS</B><size=14>({0})</size>", ["NOT_AVAILABLE_MISSIONS"] = "You have no tasks available :(", ["REWARD_FOR_QUESTIONS"] = "<b>REWARD FOR COMPLETING THE MISSION</b>", ["CAN"] = "can", ["CAN'T"] = "can't", ["absent's"] = "absent", ["QUEST_ACTIVE_LIMIT"] = "You have too much <color=#4286f4>unfinished</color> assignments!", ["QUEST_ACTIVE_COLDOWN"] = "You cannot take this quest at the moment", ["QUEST_took_tasks"] = "You already <color=#4286f4>have taken</color> this task!", ["QUEST_completed_tasks"] = "You already <color=#4286f4>performed</color> this task!", ["QUEST_completed_took"] = "You <color=#4286f4>successfully</color> took the task {0}", ["QUEST_tasks_completed"] = "Thanks, keep your <color=#4286f4>reward</color>!", ["QUEST_no_place"] = "Hey wait, you're everything <color=#4286f4>you won't take</color>, make room!", ["QUEST_did_not_cope"] = "Sorry that you <color=#4286f4>did not cope</color> with the task!\n" + $"Anyway, you can try again!", ["QUEST_done"] = "Performed!", ["QUEST_take"] = "TAKE", ["QUEST_turn"] = "Hand over", ["QUEST_REFUSE"] = "REFUSE", ["QUEST_Finished"] = "You have completed the task: <color=#4286f4>{0}</color>", ["QUEST_DONTREPEAT"] = "You have already completed this quest.!", ["QUEST_target"] = "Need to: {0}\n" + "Re-take {1}\n" + "CD to re-take : {2}", ["QUEST_targetrtho"] = "Need to: {0}\n" + "Progress: {1}/{2}\n" + "Re-take {3}\n" + "CD to re-take : {4}",
}
, this);
lang.RegisterMessages(new Dictionary<string, string> {
["QUEST_ACTIVE"]
= "Ваши активные задачи: {0}", ["NOT_QUEST_ACTIVE"] = "У вас нет активных задач", ["QUEST_Insufficient_resources"] = "У вас нету {0}, нужно обязательно принести это сидоровичу", ["QUEST_not_resources"] = "У вас не достаточно {0}, нужно {1}", ["QUEST_ACTIVE_COMPLITE"] = "{0}\nЗадания выполнено!\nНе забудьте сдать его сидоровичу.", ["NOT_QUEST_ACTIVE_COMPLITE"] = "<size=9>{0}</size>\nПрогресс: {1}/{2}\n{3}", ["AVAILABLE_MISSIONS"] = "<b>ДОСТУПНЫЕ ЗАДАНИЯ</b><size=14>({0})</size>", ["ACTIVE_MISSIONS"] = "<b>АКТИВНЫЕ ЗАДАНИЯ</B><size=14>({0})</size>", ["NOT_AVAILABLE_MISSIONS"] = "У вас нет доступных задач :(", ["REWARD_FOR_QUESTIONS"] = "<b>НАГРАДА ЗА ВЫПОЛНЕНИЯ ЗАДАНИЯ</b>", ["CAN"] = "можно", ["CAN'T"] = "нельзя", ["absent's"] = "отсутствует", ["QUEST_ACTIVE_LIMIT"] = "У тебя слишком много <color=#4286f4>не законченных</color> заданий!", ["QUEST_ACTIVE_COLDOWN"] = "В данный момент вы не можете взять этот квест", ["QUEST_took_tasks"] = "Вы уже <color=#4286f4>взяли</color> это задание!", ["QUEST_completed_tasks"] = "Вы уже <color=#4286f4>выполняли</color> это задание!", ["QUEST_completed_took"] = "Вы <color=#4286f4>успешно</color> взяли задание {0}", ["QUEST_tasks_completed"] = "Спасибо, держи свою <color=#4286f4>награду</color>!", ["QUEST_no_place"] = "Эй, погоди, ты всё <color=#4286f4>не унесёшь</color>, освободи место!", ["QUEST_did_not_cope"] = "Жаль что ты <color=#4286f4>не справился</color> с заданием!\n" + $"В любом случае, ты можешь попробовать ещё раз!", ["QUEST_done"] = "Выполнено!", ["QUEST_take"] = "ВЗЯТЬ", ["QUEST_turn"] = "СДАТЬ", ["QUEST_REFUSE"] = "ОТКАЗАТЬСЯ", ["QUEST_Finished"] = "Вы закончили задание: <color=#4286f4>{0}</color>", ["QUEST_DONTREPEAT"] = "Вы уже выполняли этот квест!", ["QUEST_target"] = "Нужно: {0}\n" + "Повторно брать {1}\n" + "Кд на повторное взятие: {2}", ["QUEST_targetrtho"] = "Нужно: {0}\n" + "Прогресс: {1}/{2}\n" + "Повторно брать {3}\n" + "Кд на повторное взятие: {4}",
}
, this, "ru");
}
#endregion
#region Configuration
public static Configuration config = new Configuration();
public class Configuration {
public class itemsNpc {
[JsonProperty("ShortName")]
public string ShortName;
[JsonProperty("SkinId")]
public ulong SkinId;
}
public class Settings {
[JsonProperty("Колличевство единовременно взятых квестов")]
public int questCount;
[JsonProperty("Голосовое оповещение при выполнении задания")]
public bool SoundEffect;
[JsonProperty("Эфект")]
public string Effect;
[JsonProperty("Названия файла с квестами")]
public string questListDataName;
[JsonProperty("Названия файла с Аудио для NPC(Не менять!!!)")]
public string audioDataPath;
[JsonProperty("Команда для открытия квест листа с прогрессом")]
public string questListProgress;
[JsonProperty("Идентификатор вашей постройки")]
public string buildid;
}
public class SettingsNpc {
[JsonProperty("Имя нпс")]
public string Name;
[JsonProperty("id npc (От его ид зависит его внешность)")]
public ulong userId;
[JsonProperty("Одежда нпс")]
public List<itemsNpc> Wear = new List<itemsNpc>();
}
public class SettingsIQChat {
[JsonProperty("Префикс в чате")]
public string prifix;
[JsonProperty("SteamID - Для аватарки из профиля стим")]
public string SteamID;
}
[JsonProperty("Настройки NPC")]
public SettingsNpc settingsNpc;
[JsonProperty("Настройки")]
public Settings settings;
[JsonProperty("Настройки IQChat (Если есть)")]
public SettingsIQChat settingsIQChat;
public static Configuration GetNewConfiguration() {
return new Configuration {
settingsIQChat = new SettingsIQChat {
prifix = "Сидорович:", SteamID = "21"
}
, settings = new Settings {
questCount = 3, SoundEffect = true, Effect = "assets/prefabs/locks/keypad/effects/lock.code.lock.prefab", questListDataName = "Quest", audioDataPath = "Audio", questListProgress = "qlist", buildid = "1"
}
, settingsNpc = new SettingsNpc {
Name = "Сидорович\n", userId = 21, Wear = new List<itemsNpc> {
new itemsNpc {
ShortName = "pants", SkinId = 960252273,
}
, new itemsNpc {
ShortName = "hoodie", SkinId = 959641236,
}
, new itemsNpc {
ShortName = "shoes.boots", SkinId = 962503020,
}
}
}
,
}
;
}
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
}
catch {
PrintWarning("Ошибка чтения конфигурации 'oxide/config/', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
if(config.settings.audioDataPath == null) {
config.settings.audioDataPath = "Audio";
}
if (config.settings.buildid == null) {
config.settings.buildid = "1";
}
if (!BuildingList.ContainsKey(config.settings.buildid)) {
PrintWarning("Вы указали неверный Идентификатор, Спавн стандартной постройки...");
config.settings.buildid = "1";
}
path = "XDQuest/" + config.settings.audioDataPath;
LoadDataSound();
NextTick(SaveConfig);
}
protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
protected override void SaveConfig() => Config.WriteObject(config, true);
#endregion
#region QuestData
private class PlayerQuest {
public Quest parentQuest;
public ulong UserID;
public bool Finished;
public int Count;
public void AddCount(int amount = 1) {
Count += amount;
BasePlayer player = BasePlayer.FindByID(UserID);
if (parentQuest.Amount <= Count) {
if (player != null && player.IsConnected) {
if (config.settings.SoundEffect) Instance.RunEffect(player, config.settings.Effect);
Instance.SendChat(player, Instance.GetLang("QUEST_Finished", player.UserIDString, parentQuest.DisplayName));
Interface.CallHook("QuestCompleted", player, Instance.GetLang("QUEST_Finished", player.UserIDString, parentQuest.DisplayName));
}
Finished = true;
}
if (Instance.openQuestPlayers.Contains(UserID)) {
CuiHelper.DestroyUi(player, QuestListLAYER);
Instance.UI_QuestList(player);
}
}
public int LeftAmount() => parentQuest.Amount - Count;
}
public enum QuestType {
IQPlagueSkill, IQHeadReward, IQCases, OreBonus, XDChinookIvent, Добыть, Убить, Скрафтить, Изучить, Залутать, УлучшитьПостройку, ИспользоватьКарточкуДоступа, установить,
}
public enum PrizeType {
Предмет, Чертёж, КастомПредмет, Команда
}
private class Quest {
internal class Prize {
public string nameprize;
public PrizeType type;
public string ShortName;
public int Amount;
public string Name;
public ulong SkinID;
public string Command;
public string Url;
}
public string DisplayName;
public string Description;
public string Missions;
public QuestType QuestType;
public string Target;
public int Amount;
public bool UseRepeat;
public int Cooldown;
public List<Prize> PrizeList = new List<Prize>();
}
#endregion
#region MetodsBuildingAndNpc
private class Building {
public string name;
public float Deg2Rad;
public Vector3 pos;
}
private Dictionary<string, Building> BuildingList = new Dictionary<string, Building> {
["1"]
= new Building {
name = "XDQuestHouseNPCNew", Deg2Rad = 4.72f, pos = new Vector3(-3.86f, 3.32f, 43.99f)
}
, ["2"] = new Building {
name = "XDQuestHouseNPCNewYear", Deg2Rad = 4.76f, pos = new Vector3(-3.86f, 3.34f, 43.99f)
}
}
;
void GenerateBuilding() {
ClearEnt();
Subscribe("OnPasteFinished");
var options = new List<string> {
"stability", "true", "deployables", "true", "autoheight", "false", "entityowner", "false"
}
;
Vector3 resultVector = GetResultVector();
var success = CopyPaste.Call("TryPasteFromVector3", resultVector, (monument.transform.rotation.eulerAngles * Mathf.Deg2Rad).y - BuildingList[config.settings.buildid].Deg2Rad, BuildingList[config.settings.buildid].name, options.ToArray());
if (success is string) {
PrintWarning("Ошибка #1 \nПлагин не будет работать, Обратитесь к разработчику" + AuthorContact);
Unsubscribe("OnPasteFinished");
return;
}
GravityItemAdd();
timer.Once(5f, () => {
CrategravityItems();
InitializeNPC(resultVector);
}
);
}
public void InitializeNPC(Vector3 pos) {
npc = GameManager.server.CreateEntity("assets/prefabs/player/player.prefab", pos) as BasePlayer;
if (npc == null) {
Interface.Oxide.LogError($"Initializing NPC failed! NPC Component == null #3");
return;
}
npc.userID = config.settingsNpc.userId;
npc.name = config.settingsNpc.Name;
npc.displayName = npc.name;
npc.Spawn();
npc.SendNetworkUpdate();
List<BaseChair> chairs = new List<BaseChair>();
Vis.Entities(npc.transform.position, 2f, chairs);
foreach (var chair in chairs.Distinct().ToList()) {
chair.MountPlayer(npc);
npc.OverrideViewAngles(chair.mountAnchor.transform.rotation.eulerAngles);
npc.eyes.NetworkUpdate(chair.mountAnchor.transform.rotation);
npc.ClientRPCPlayer(null, npc, "ForcePositionTo", npc.transform.position);
chair.SetFlag(BaseEntity.Flags.Busy, true);
break;
}
ZoneTrigger zone = new GameObject().AddComponent<ZoneTrigger>();
zone.Activate(pos, 4.6f);
#region Одеваем нпс
if (config.settingsNpc.Wear.Count > 0) for (int i = 0; i < config.settingsNpc.Wear.Count; i++) ItemManager.Create(ItemManager.FindItemDefinition(config.settingsNpc.Wear[i].ShortName), 1, config.settingsNpc.Wear[i].SkinId).MoveToContainer(npc.inventory.containerWear);
#endregion
}
private void ClearEnt() {
BasePlayer findplayer = FindMyBot(config.settingsNpc.userId);
if (findplayer != null) findplayer.KillMessage();
List<BaseEntity> obj = new List<BaseEntity>();
Vis.Entities(GetResultVector(), 10f, obj, LayerMask.GetMask("Construction", "Deployable", "Deployed", "Debris"));
foreach (BaseEntity item in obj?.Where(x => x.OwnerID == 1893562145)) {
if (item == null) continue;
item.Kill();
}
}
void OnPasteFinished(List<BaseEntity> pastedEntities) {
try {
HouseNPC = pastedEntities;
foreach (BaseEntity item in HouseNPC) {
item.OwnerID = 1893562145;
if (item as BuildingBlock) {
var build = item as BuildingBlock;
build.SetFlag(BaseEntity.Flags.Reserved1, false);
build.SetFlag(BaseEntity.Flags.Reserved2, false);
}
if (item is BaseChair) continue;
if (item.name.Contains("woodenbox")) {
var box = item as BaseCombatEntity;
box.pickup.enabled = false;
continue;
}
else if (item.name.Contains("light") || item.name.Contains("lantern")) {
item.enableSaving = true;
item.SendNetworkUpdate();
item.SetFlag(BaseEntity.Flags.Reserved8, true);
item.SetFlag(BaseEntity.Flags.On, true);
}
item.SetFlag(BaseEntity.Flags.Busy, true);
item.SetFlag(BaseEntity.Flags.Locked, true);
}
PrintWarning($"Постройка обработана успешно {HouseNPC.Count}");
Unsubscribe("OnPasteFinished");
}
catch (Exception ex) {
PrintError("Ошибка при загрузке постройки! Подробности в лог файле!!\nОбратитесь к разработчику" + AuthorContact);
Log(ex.Message, "LogError");
}
}
#endregion
#region Hooks
#region QuestHook
#region Type Upgrade
object OnStructureUpgrade(BaseCombatEntity entity, BasePlayer player, BuildingGrade.Enum grade) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.УлучшитьПостройку && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return null;
for (int i = 0; i < playerQuests.Count; i++) {
if ((int)grade == Convert.ToInt16(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
return null;
}
#endregion
#region IQPlagueSkill
void StudySkill(BasePlayer player, string name) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.IQPlagueSkill && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.Target == name || playerQuests[i].parentQuest.Target == "0") {
playerQuests[i].AddCount();
}
}
}
#endregion
#region HeadReward
void KillHead(BasePlayer player) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.IQHeadReward && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
playerQuests[i].AddCount();
}
}
#endregion
#region IqCase
void OpenCase(BasePlayer player, string name) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.IQCases && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.Target == name || playerQuests[i].parentQuest.Target == "0") {
playerQuests[i].AddCount();
}
}
}
#endregion
#region OreBonus
void RadOreGive(BasePlayer player, Item item) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.OreBonus && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.Target == item.info.shortname || playerQuests[i].parentQuest.Target == "0") {
playerQuests[i].AddCount(item.amount);
}
}
}
#endregion
#region Chinook
void LootHack(BasePlayer player) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.XDChinookIvent && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
playerQuests[i].AddCount();
}
}
#endregion
#region Добыть
private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item) {
NextTick(() => {
BasePlayer player;
if (entity is BasePlayer) {
player = entity as BasePlayer;
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Добыть && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (item.info.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount(item.amount);
}
}
}
}
);
}
void OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item) => OnDispenserGather(dispenser, entity, item);
void OnCollectiblePickup(Item item, BasePlayer player) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Добыть && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (item.info.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount(item.amount);
}
}
}
#endregion
#region Скрафтить
void OnItemCraftFinished(ItemCraftTask task, Item item) {
var player = task.owner;
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Скрафтить && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (task.blueprint.targetItem.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount(item.amount);
}
}
}
#endregion
#region Изучить
void OnItemResearch(ResearchTable table, Item targetItem, BasePlayer player) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Изучить && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (targetItem.info.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
}
#endregion
#region установить
private void OnEntityBuilt(Planner plan, GameObject go) {
BasePlayer player = plan?.GetOwnerPlayer();
if (player == null || go == null || plan.GetItem() == null) return;
BaseEntity ent = go.ToBaseEntity();
if (ent == null) return;
if (ent.skinID == 11543256361) return;
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.установить && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (plan.GetItem().info.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
}
object CanPickupEntity(BasePlayer player, BaseCombatEntity entity) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.установить && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return null;
for (int i = 0; i < playerQuests.Count; i++) {
if (entity.pickup.itemTarget.shortname.Contains(playerQuests[i].parentQuest.Target)) {
entity.skinID = 11543256361;
}
}
return null;
}
#endregion
#region Залутать
private void OnLootEntity(BasePlayer player, LootContainer entity) {
if (entity.OwnerID == 133722822222222 || entity.OwnerID >= 7656000000 || entity == null) return;
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Залутать && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
for (int u = 0; u < entity.inventory.itemList.Count();
u++) {
if (entity.inventory.itemList[u].info.shortname.Contains(playerQuests[i].parentQuest.Target)) playerQuests[i].AddCount(entity.inventory.itemList[u].amount);
}
}
entity.OwnerID = 133722822222222;
}
private void OnContainerDropItems(ItemContainer container) {
if (container == null) return;
BaseEntity entity = container.entityOwner;
if (entity == null) return;
if (!entity.ShortPrefabName.Contains("barrel")) return;
foreach (Item lootitem in container.itemList) lootitem.SetFlag(global : : Item.Flag.Placeholder, true);
}
object OnItemPickup(Item item, BasePlayer player) {
if (item == null) return null;
if (!item.HasFlag(global : : Item.Flag.Placeholder)) return null;
item.SetFlag(global : : Item.Flag.Placeholder, false);
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Залутать && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return null;
for (int i = 0; i < playerQuests.Count; i++) {
if (item.info.shortname.Contains(playerQuests[i].parentQuest.Target)) playerQuests[i].AddCount(item.amount);
}
return null;
}
#endregion
#region Использовать карточку доступа
private void OnCardSwipe(CardReader cardReader, Keycard card, BasePlayer player) {
List<PlayerQuest> playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.ИспользоватьКарточкуДоступа && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (card.GetItem().info.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
}
#endregion
#region Убить/взорвать/уничтожить что либо
void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
try {
if (entity == null || info == null) return;
List<PlayerQuest> playerQuests = null;
string entname = entity?.ShortPrefabName;
if (entname == "testridablehorse") {
entname = "horse";
}
if (entname.Contains("servergibs")) return;
BasePlayer player = null;
if (info.InitiatorPlayer != null) player = info.InitiatorPlayer;
else if (entity.GetComponent<BaseHelicopter>() != null) {
PatrolHelicopterAI helicopterAI = entity?.GetComponent<PatrolHelicopterAI>();
if (helicopterAI == null) return;
player = helicopterAI._targetList[helicopterAI._targetList.Count - 1].ply;
}
if (player != null) {
if (entity.ToPlayer() != null && entity.ToPlayer() == player) return;
if (entity.ToPlayer() != null) {
if (IsFriends(player.userID, entity.ToPlayer().userID)) return;
if (IsClans(player.userID, entity.ToPlayer().userID)) return;
if (IsDuel(player.userID)) return;
}
playerQuests = storedData.players[player.userID].PlayerQuestsAll.Values.Where(x => x.parentQuest.QuestType == QuestType.Убить && x.Finished == false).ToList();
if (playerQuests == null || playerQuests.Count == 0) return;
for (int i = 0; i < playerQuests.Count; i++) {
if (entity.PrefabName.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
}
}
catch (Exception ex) {
}
}
void OnEntityTakeDamage(BaseCombatEntity victim, HitInfo info) {
try {
if (info.damageTypes.Has(Rust.DamageType.Decay)) {
if (victim?.OwnerID == 1893562145) {
info.damageTypes.Scale(DamageType.Decay, 0);
}
}
}
catch (NullReferenceException) {
}
}
#endregion
#endregion
object CanLootEntity(BasePlayer player, StorageContainer container) {
if (container.skinID == 1195832261) {
UI_DrawInterface(player);
return false;
}
return null;
}
object CanAffordUpgrade(BasePlayer player, BuildingBlock block, BuildingGrade.Enum grade) {
if (block.OwnerID == 1893562145) return false;
else return null;
}
void Init() {
LoadDataPlayer();
LoadDataQuestList(ref QuestList);
Unsubscribe("OnPasteFinished");
}
private void OnServerInitialized() {
monument = TerrainMeta.Path.Monuments.FirstOrDefault(p => p.name.ToLower() == "assets/bundled/prefabs/autospawn/monument/medium/compound.prefab");
Instance = this;
if (!CopyPaste) {
PrintError("Проверьте установлен ли у вас плагин 'CopyPaste'");
Interface.Oxide.UnloadPlugin(Name);
return;
}
else if (CopyPaste.Version < new VersionNumber(4, 1, 26)) {
PrintError("У вас старая версия CopyPaste!\nПожалуйста обновите плагин до последней версии (4.1.26 или выше) - https://umod.org/plugins/copy-paste");
Interface.Oxide.UnloadPlugin(Name);
return;
}
if (monument == null) {
PrintError("Походу у вас отсутствует 'Город НПС' !\nПожалуйста обратитесь к разработчику" + AuthorContact);
Interface.Oxide.UnloadPlugin(Name);
return;
}
cmd.AddChatCommand(config.settings.questListProgress, this, nameof(UI_QuestList));
ServerMgr.Instance.StartCoroutine(DownloadImages());
foreach (var player in BasePlayer.activePlayerList) OnPlayerConnected(player);
LoadDataCopyPaste();
}
void OnPlayerConnected(BasePlayer player) {
if (!storedData.players.ContainsKey(player.userID)) {
storedData.players.Add(player.userID, new PlayerData());
}
else {
foreach (var item in storedData.players[player.userID].PlayerQuestsAll) {
var curentQuest = QuestList.FirstOrDefault(p => p.Value.DisplayName == item.Value.parentQuest.DisplayName);
if(curentQuest.Value == null) {
NextTick(() => {
storedData.players[player.userID].PlayerQuestsAll.Remove(item.Key);
}
);
}
}
}
foreach (var item in ImageUI) SendImage(player, item.Key);
PlayersTime.Add(player.userID, null);
}
private void OnPlayerDisconnected(BasePlayer d) {
if (openQuestPlayers.Contains(d.userID)) openQuestPlayers.Remove(d.userID);
if (PlayersTime.ContainsKey(d.userID)) {
if (PlayersTime[d.userID] != null) ServerMgr.Instance.StopCoroutine(PlayersTime[d.userID]);
PlayersTime.Remove(d.userID);
}
}
void Unload() {
SaveData();
DestroyAll<ZoneTrigger>();
for (int i = 0; i < HouseNPC.Count; i++) {
if (!HouseNPC[i].IsDestroyed) HouseNPC[i]?.Kill();
}
npc?.KillMessage();
foreach (var items in ItemForce) items?.RemoveFromWorld();
foreach(BasePlayer p in BasePlayer.activePlayerList) {
if (PlayersTime.ContainsKey(p.userID)) {
if(PlayersTime[p.userID] != null) ServerMgr.Instance.StopCoroutine(PlayersTime[p.userID]);
PlayersTime.Remove(p.userID);
}
CuiHelper.DestroyUi(p, Layers);
CuiHelper.DestroyUi(p, QuestListLAYER);
}
ServerMgr.Instance.StopCoroutine(DownloadImages());
}
#endregion
#region Летающии итемы
public class GravityItem {
public string Shortname;
public Vector3 vector;
public Quaternion quaternion;
}
List<GravityItem> gravityItems = new List<GravityItem>();
private void GravityItemAdd() {
gravityItems.Add(new GravityItem {
Shortname = "map", vector = monument.transform.position + monument.transform.rotation * new Vector3(-4.96f, 3.32f, 46.66f), quaternion = new Quaternion(1.99f, 0.0f, 0, 2),
}
);
gravityItems.Add(new GravityItem {
Shortname = "rifle.ak", vector = monument.transform.position + monument.transform.rotation * new Vector3(-5.56f, 2.68f, 44.95f), quaternion = new Quaternion(0f, -1.0f, 0, 2),
}
);
gravityItems.Add(new GravityItem {
Shortname = "targeting.computer", vector = monument.transform.position + monument.transform.rotation * new Vector3(-5.73f, 2.68f, 46.15f), quaternion = new Quaternion(0, -1.39f, 0, 2),
}
);
}
public void CrategravityItems() {
for (int i = 0; i < gravityItems.Count; i++) {
Item Item = ItemManager.CreateByName(gravityItems[i].Shortname, 1);
Item.Drop(gravityItems[i].vector, Vector3.up, monument.transform.rotation * gravityItems[i].quaternion);
var Items = Item.GetWorldEntity() as DroppedItem;
Items.allowPickup = false;
Items.CancelInvoke(Items.IdleDestroy);
var rigidbody = Item.GetWorldEntity().GetComponent<Rigidbody>();
rigidbody.useGravity = false;
rigidbody.isKinematic = true;
ItemForce.Add(Item);
}
}
#endregion
#region TriggerNpc
System.Random rnd = new System.Random();
private class ZoneTrigger : MonoBehaviour {
private float ZoneRadius;
private Vector3 Position;
private SphereCollider sphereCollider;
private void Awake() {
gameObject.layer = (int)Layer.Reserved1;
gameObject.name = "ZoneTrigger";
enabled = false;
}
public void Activate(Vector3 pos, float radius) {
Position = pos;
ZoneRadius = radius;
transform.position = Position;
transform.rotation = new Quaternion();
UpdateCollider();
gameObject.SetActive(true);
enabled = true;
}
private void OnTriggerEnter(Collider col) {
BasePlayer player = col.GetComponentInParent<BasePlayer>();
if (player != null) {
int mIndex = Instance.rnd.Next(Instance._Data.Hey.Length);
Instance.API_NPC_SendToAll(Instance._Data.Hey[mIndex]);
}
}
private void OnTriggerExit(Collider col) {
BasePlayer player = col.GetComponentInParent<BasePlayer>();
if (player != null) {
int mIndex = Instance.rnd.Next(Instance._Data.Bye.Length);
Instance.API_NPC_SendToAll(Instance._Data.Bye[mIndex]);
player.SendConsoleCommand("Close_Layer");
}
}
private void OnDestroy() {
Destroy(gameObject);
CancelInvoke();
}
private void UpdateCollider() {
sphereCollider = gameObject.GetComponent<SphereCollider>();
{
if (sphereCollider == null) {
sphereCollider = gameObject.AddComponent<SphereCollider>();
sphereCollider.isTrigger = true;
sphereCollider.name = "ZoneTrigger";
}
sphereCollider.radius = ZoneRadius;
}
}
}
#endregion
#region SoundNpc
public class AudioData {
public String Name;
public Single Length = 0;
public List<VoicePacket> VoicePacketList = new List<VoicePacket>();
public class VoicePacket {
public Single TimeOffset;
public Byte[] Stream;
}
}
public class BotSpeakerData {
public Dictionary<string, AudioData> AudioClips = new Dictionary<string, AudioData>();
public string[] Hey;
public string[] Bye;
}
public string path = string.Empty;
private BotSpeakerData _Data;
private DynamicConfigFile DataFile;
private void LoadDataSound() {
if(String.IsNullOrWhiteSpace(path)) {
PrintError("Ошибка при загрузке звуков! Плагин будет перезагружен " + AuthorContact);
return;
}
DataFile = Interface.Oxide.DataFileSystem.GetFile(path);
if (Interface.GetMod().DataFileSystem.ReadObject<BotSpeakerData>(path).AudioClips.Count == 0) {
PrintWarning("Загрузка звуков для NPC...");
webrequest.Enqueue($"http://utilite.skyplugins.ru/xdquest/{config.settings.audioDataPath}.json", null, (i, s) => {
if (i == 200) WriteToData(s);
else {
PrintError("Ошибка при загрузке звуков!\nОбратитесь к разработчику " + AuthorContact);
Log(i.ToString(), "LogError");
}
}
, this, RequestMethod.GET);
;
}
_Data = DataFile.ReadObject<BotSpeakerData>();
}
void WriteToData(string calback) {
_Data = JsonConvert.DeserializeObject<BotSpeakerData>(calback);
DataFile.WriteObject(_Data);
}
public HashSet<uint> BotAlerts = new HashSet<uint>();
void API_NPC_SendToAll(string clipName) {
try {
if (BotAlerts.Contains(npc.net.ID)) return;
else BotAlerts.Add(npc.net.ID);
AudioData audio;
if (_Data.AudioClips.TryGetValue(clipName, out audio)) {
var clip = _Data.AudioClips[clipName];
timer.Once(clip.Length, () => BotAlerts.Remove(npc.net.ID));
audio.VoicePacketList.ForEach(packet => {
timer.Once(packet.TimeOffset, () => {
if (Net.sv.write.Start()) {
Net.sv.write.PacketID(Message.Type.VoiceData);
Net.sv.write.UInt32(npc.net.ID);
Net.sv.write.BytesWithSize(packet.Stream);
var write = Net.sv.write;
var sendInfo = new SendInfo() {
connections = BasePlayer.activePlayerList.Select(player => player.Connection).ToList(), priority = Priority.Immediate
}
;
write.Send(sendInfo);
}
}
);
}
);
}
}
catch(NullReferenceException ex) {
PrintError($"Ошибка загрузки звуков! Попробуйте перезагрузить плагин удалив в дате файли {config.settings.audioDataPath}\nИли свяжитесь с разработчиком + {AuthorContact}");
}
}
#endregion
#region HelpMetods
void RunEffect(BasePlayer player, string path) {
Effect effect = new Effect();
effect.Init(Effect.Type.Generic, player.transform.position, player.transform.forward, (Connection)null);
effect.pooledString = path;
EffectNetwork.Send(effect, player.net.connection);
}
public static class TimeHelper {
public static string FormatTime(TimeSpan time, int maxSubstr = 5, string language = "ru") {
string result = string.Empty;
switch (language) {
case "ru" : int i = 0;
if (time.Days != 0 && i < maxSubstr) {
if (!string.IsNullOrEmpty(result)) result += " ";
result += $"{Format(time.Days, "д", "д", "д")}";
i++;
}
if (time.Hours != 0 && i < maxSubstr) {
if (!string.IsNullOrEmpty(result)) result += " ";
result += $"{Format(time.Hours, "ч", "ч", "ч")}";
i++;
}
if (time.Minutes != 0 && i < maxSubstr) {
if (!string.IsNullOrEmpty(result)) result += " ";
result += $"{Format(time.Minutes, "м", "м", "м")}";
i++;
}
if (time.Days == 0) {
if (time.Seconds != 0 && i < maxSubstr) {
if (!string.IsNullOrEmpty(result)) result += " ";
result += $"{Format(time.Seconds, "с", "с", "с")}";
i++;
}
}
break;
case "en" : result = string.Format("{0}{1}{2}{3}", time.Duration().Days > 0 ? $"{time.Days:0} day{(time.Days == 1 ? String.Empty : "s")}, " : string.Empty, time.Duration().Hours > 0 ? $"{time.Hours:0} hour{(time.Hours == 1 ? String.Empty : "s")}, " : string.Empty, time.Duration().Minutes > 0 ? $"{time.Minutes:0} minute{(time.Minutes == 1 ? String.Empty : "s")}, " : string.Empty, time.Duration().Seconds > 0 ? $"{time.Seconds:0} second{(time.Seconds == 1 ? String.Empty : "s")}" : string.Empty);
if (result.EndsWith(", ")) result = result.Substring(0, result.Length - 2);
if (string.IsNullOrEmpty(result)) result = "0 seconds";
break;
}
return result;
}
private static string Format(int units, string form1, string form2, string form3) {
var tmp = units % 10;
if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9) return $"{units}{form1}";
if (tmp >= 2 && tmp <= 4) return $"{units}{form2}";
// ... [Code preview truncated due to length. Full source in attached file] ...