C#:
using Newtonsoft.Json;
using Oxide.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using Graphics = System.Drawing.Graphics;
using System.IO;
using System.Linq;
using UnityEngine;
using Oxide.Core.Plugins;
using Color = UnityEngine.Color;
using System.Globalization;
using Oxide.Game.Rust.Cui;
using ProtoBuf;
using ConVar;
using Oxide.Core.Configuration;
namespace Oxide.Plugins {
[Info("QuestSystem", "DezLife", "3.9.3")]
public class QuestSystem : RustPlugin {
public static QuestSystem instance;
[PluginReference]
Plugin IQChat, RustMap, Friends, Clans, Battles, Duel;
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;
}
#region eNums
private enum QuestType {
убить, добыть, скрафтить, найти, улучшить
}
#endregion
#region Classes
private class Quest {
internal class Prize {
[JsonProperty("Это кастом предмет ? (Если это обычный предмет ставим false)")]
public bool CustomItem;
[JsonProperty("Отображаемое имя (Для кастом)")]
public string DisplayName;
[JsonProperty("Skin id (Для кастом но можно и для обычного предмета чтоб дать ему скин)")]
public ulong Skin;
[JsonProperty("Shortname выдаваемого предмета")]
public string Shortname;
[JsonProperty("количество")]
public int Amount;
[JsonProperty("Ссылка на картинку (Если используете команду для выдачи то обязательно!)")]
public string ExternalURL;
[JsonProperty("Команда")]
public string Command;
}
[JsonProperty("Названия квеста")]
public string DisplayName;
[JsonProperty("Описания")]
public string Description;
[JsonProperty("Кд на повторное взятия данного квеста (Если не нужно ставим 0)")]
public float Cooldown;
[JsonProperty("Тип квеста (0 - убить, 1 - добыть, 2 - скрафтить, 3 - найти, 4 - улучшить)")]
public QuestType QuestType;
[JsonProperty("То чего добыть (На русском)")]
public string NiceTarget;
[JsonProperty("В зависимости от квеста.Если убить человека то player.Если добыть дерева то wood; Если это улучшения то 1 - дерево, 2 - камень и тд")]
public string Target;
[JsonProperty("Количевство")]
public int Amount;
[JsonProperty("Настройка награды")]
public List<Prize> PrizeList = new List<Prize>();
public List<ulong> FinishedPlayers = new List<ulong>();
}
private class PlayerQuest {
public Quest parentQuest;
public ulong UserID;
public bool Finished;
public int Count;
public void AddCount(int amount = 1) {
Count += amount;
if (parentQuest.Amount <= Count) {
BasePlayer player = BasePlayer.FindByID(UserID);
if (player != null && player.IsConnected) {
if (config.SoundEff) instance.RunEffect(player, config.SoundEffPath);
instance.SendChat(instance.lang.GetMessage("QUEST", instance, player.UserIDString), String.Format(instance.lang.GetMessage("QUEST_Finished", instance, player.UserIDString), parentQuest.DisplayName), player);
}
Finished = true;
}
}
public int LeftAmount() => parentQuest.Amount - Count;
}
#endregion
#region Lang
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["QUEST_ACTIVE"]
= "<size=16>Your active tasks:</ size>", ["QUEST"] = "<size=16>Tasks:</size>", ["QUEST_ACTIVE_comp"] = "You <color=#4286f4>are absent</color> active tasks, take them to the city!", ["QUEST_ACTIVE_PROGRESS"] = "You can <color=#4286f4>to complete</color> the task!", ["QUEST_ACTIVE_PROGRESS_GO"] = "Left: {0} {1} {2}\n", ["QUEST_ACTIVE_LIMIT"] = "You have too much <color=#4286f4>not finished</color> tasks!", ["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 hold your <color=#4286f4>reward</color>!", ["QUEST_no_place"] = "Hey wait you everything <color=#4286f4>you will not carry away</color>, make room!", ["QUEST_did_not_cope"] = "Sorry you <color=#4286f4>did not cope</color> with the task!\n" + $"Anyway, you can try again!", ["QUEST_back"] = "FORWARD", ["QUEST_next"] = "BACK", ["QUEST_prize"] = "REWARD FOR PERFORMANCE OF THE TASK", ["QUEST_done"] = "DONE", ["QUEST_take"] = "TAKE", ["QUEST_turn"] = "FOR RENT", ["QUEST_REFUSE"] = "REFUSE", ["QUEST_Finished"] = "You have completed the task: <color=#4286f4>{0}</color>",
}
, this);
lang.RegisterMessages(new Dictionary<string, string> {
["QUEST_ACTIVE"]
= "<size=16>Ваши активные задачи:</size>", ["QUEST"] = "<size=16>Задания:</size>", ["QUEST_ACTIVE_comp"] = "У вас <color=#4286f4>отсутствуют</color> активные задачи, возьмите их в городе!", ["QUEST_ACTIVE_PROGRESS"] = "Вы можете <color=#4286f4>завершить</color> задачу!", ["QUEST_ACTIVE_PROGRESS_GO"] = "Осталось: {0} {1} {2}\n", ["QUEST_ACTIVE_LIMIT"] = "У тебя слишком много <color=#4286f4>не законченных</color> заданий!", ["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_back"] = "ВПЕРЕД", ["QUEST_next"] = "НАЗАД", ["QUEST_prize"] = "НАГРАДА ЗА ВЫПОЛНЕНИЕ ЗАДАНИЯ", ["QUEST_done"] = "ГОТОВО", ["QUEST_take"] = "ВЗЯТЬ", ["QUEST_turn"] = "СДАТЬ", ["QUEST_REFUSE"] = "ОТКАЗАТЬСЯ", ["QUEST_Finished"] = "Вы закончили задание: <color=#4286f4>{0}</color>",
}
, this, "ru");
}
#endregion
#region Configuration
private static Configuration config = new Configuration();
private class Configuration {
[JsonProperty("Можно ли повторно брать квесты ?")]
public bool QuestGo;
[JsonProperty("Картинка для доски заданий (Желательный размер 256 на 128)")]
public string ImageURL;
[JsonProperty("Максимум квестов которых игрок сможет взять за раз")]
public int MaxQuestAmount;
[JsonProperty("Оповестить игрока звуковым оповещением о том что он выполнил квест?")]
public bool SoundEff;
[JsonProperty("Эфект для проигрования")]
public string SoundEffPath;
[JsonProperty("Делать маркер на карте j?")]
public bool MapMarkers;
[JsonProperty("Сбрасывать прогрес квестов у игроков во время вайпа:?")]
public bool WipeData;
[JsonProperty("Включить прогресс бар для игроков ?")]
public bool ProgressBar;
[JsonProperty("Цвет кнопок (Вперед/Назад)")]
public string ColorButton;
public static Configuration GetNewConfiguration() {
return new Configuration {
QuestGo = true, ImageURL = "https://i.imgur.com/Zd10HwE.png", MaxQuestAmount = 3, SoundEff = true, SoundEffPath = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab", MapMarkers = false, WipeData = true, ProgressBar = true, ColorButton = "#5ede89d1"
}
;
}
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
}
catch {
PrintWarning("Ошибка #153" + $"чтения конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Variables
[PluginReference]
private Plugin ImageLibrary;
private BaseEntity Sign = null;
private BaseEntity Box = null;
private List<Quest> QuestList = new List<Quest> {
{
new Quest {
DisplayName = "Тупая железяка!!", Description = "Как же меня достал этот Танк,я не могу ходить в космодром!\nУничтожь танк и приходи за наградой", Cooldown = 0f, QuestType = QuestType.убить, NiceTarget = "танк", Target = "bradleyapc", Amount = 1, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "rifle.l96", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "weapon.mod.small.scope", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "jackhammer", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "", Amount = 1, ExternalURL = "https://i.imgur.com/9OJhuKj.png", Command = "emerald.give %STEAMID% Рубин 15",
}
,
}
}
}
, {
new Quest {
DisplayName = "Нужно срочно отстроить дом!", Description = "Нам нужно где то складывать свои ресурсы!\n Добудь 1000 камня и возвращайся за наградой", Cooldown = 7200f, QuestType = QuestType.добыть, NiceTarget = "камня", Target = "stones", Amount = 1000, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = true, DisplayName = "Радиактивная сера", Skin = 1681986132, Shortname = "glue", Amount = 10, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "supply.signal", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "door.hinged.toptier", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "", Amount = 1, ExternalURL = "https://i.imgur.com/9OJhuKj.png", Command = "emerald.give %STEAMID% Рубин 25",
}
,
}
}
}
, {
new Quest {
DisplayName = "Хммм...Нужно сделать гараж для мини-коптера!", Description = "Нужно побольше места для коптеров\nСкрафти 1 гаражных дверей", Cooldown = 30f, QuestType = QuestType.скрафтить, NiceTarget = "гаражных дверей", Target = "wall.frame.garagedoor", Amount = 1, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "", Amount = 1, ExternalURL = "https://i.imgur.com/PoeTa16.png", Command = "give_minicopter %STEAMID%",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "floor.ladder.hatch", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Shortname = "keycard_blue", Amount = 2, ExternalURL = "", Command = "",
}
,
}
}
}
, {
new Quest {
DisplayName = "Мне нужно больше изучений!", Description = "Мне нужно изучить множество вещей,но у меня не хватает скрапа\nНайди 100 скрапа и приходи за наградой!", Cooldown = 30f, QuestType = QuestType.найти, NiceTarget = "скрап(-а)", Target = "scrap", Amount = 100, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "smg.thompson", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "ammo.pistol.fire", Amount = 64, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "", Amount = 1, ExternalURL = "https://i.imgur.com/9OJhuKj.png", Command = "emerald.give %STEAMID% Рубин 15",
}
,
}
}
}
, {
new Quest {
DisplayName = "Нужно укрепить свою строения в камень!", Description = "Улучши 15 разных построек в камень", Cooldown = 30f, QuestType = QuestType.улучшить, NiceTarget = "раз в камень", Target = "2", Amount = 15, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "gates.external.high.stone", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "bed", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "furnace.large", Amount = 1, ExternalURL = "", Command = "",
}
,
}
}
}
, {
new Quest {
DisplayName = "Мой дом, моя крепость", Description = "Нужно лучше защитить свою базу\nСкрафти 10 заборов", Cooldown = 30f, QuestType = QuestType.скрафтить, NiceTarget = "забор(-ов)", Target = "wall.external.high.stone", Amount = 10, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "wall.window.glass.reinforced", Amount = 3, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "metal.fragments", Amount = 5000, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "", Amount = 1, ExternalURL = "https://i.imgur.com/JnPNvJi.png", Command = "givetool %STEAMID% pickaxe",
}
,
}
}
}
, {
new Quest {
DisplayName = "Мои любимые часы", Description = "Мои любимые часы барахлят,опять эти шестеренки..\nНайди 40 шестеренок и приходи за наградой!", Cooldown = 30f, QuestType = QuestType.найти, NiceTarget = "шестеренка(-ок)", Target = "gears", Amount = 40, PrizeList = new List<Quest.Prize> {
new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "autoturret", Amount = 1, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "supply.signal", Amount = 2, ExternalURL = "", Command = "",
}
, new Quest.Prize {
CustomItem = false, DisplayName = "", Skin = 0, Shortname = "", Amount = 1, ExternalURL = "https://i.imgur.com/9OJhuKj.png", Command = "emerald.give %STEAMID% Рубин 15",
}
,
}
}
}
,
}
;
private Dictionary<ulong, List<PlayerQuest>> PlayerQuests = new Dictionary<ulong, List<PlayerQuest>>();
#region Data
class PlayerData {
public List<string> PlayerQuestsFinish = new List<string>();
public Dictionary<string, double> PlayerQuestsCooldown = new Dictionary<string, double>();
}
class StoredData {
public Dictionary<ulong, PlayerData> players = new Dictionary<ulong, PlayerData>();
}
void SaveData() {
StatData.WriteObject(storedData);
}
void LoadData() {
string resultName = this.Name + $"/playersCooldown";
StatData = Interface.Oxide.DataFileSystem.GetFile(resultName);
try {
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(resultName);
}
catch {
storedData = new StoredData();
}
}
StoredData storedData;
private DynamicConfigFile StatData;
#endregion
#endregion
#region Метка на g карте
private void CreateMarker(Vector3 position, float refreshRate, string name, string displayName, float radius = 0.10f, string colorMarker = "ff60df", string colorOutline = "00FFFFFF") {
var marker = new GameObject().AddComponent<CustomMapMarker>();
marker.name = name;
marker.displayName = displayName;
marker.radius = radius;
marker.position = position;
marker.refreshRate = refreshRate;
ColorUtility.TryParseHtmlString($"#{colorMarker}", out marker.color1);
ColorUtility.TryParseHtmlString($"#{colorOutline}", out marker.color2);
}
private void RemoveMarkers() {
foreach (var marker in UnityEngine.Object.FindObjectsOfType<CustomMapMarker>()) {
UnityEngine.Object.Destroy(marker);
}
}
private const string genericPrefab = "assets/prefabs/tools/map/genericradiusmarker.prefab";
private const string vendingPrefab = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
#region Scripts
private class CustomMapMarker : MonoBehaviour {
private VendingMachineMapMarker vending;
private MapMarkerGenericRadius generic;
public BaseEntity parent;
private bool asChild;
public float radius;
public Color color1;
public Color color2;
public string displayName;
public float refreshRate;
public Vector3 position;
public bool placedByPlayer;
private void Start() {
transform.position = position;
asChild = parent != null;
CreateMarkers();
}
private void CreateMarkers() {
vending = GameManager.server.CreateEntity(vendingPrefab, position).GetComponent<VendingMachineMapMarker>();
vending.markerShopName = displayName;
vending.enableSaving = false;
vending.Spawn();
generic = GameManager.server.CreateEntity(genericPrefab).GetComponent<MapMarkerGenericRadius>();
generic.color1 = color1;
generic.color2 = color2;
generic.radius = radius;
generic.alpha = 1f;
generic.enableSaving = false;
generic.SetParent(vending);
generic.Spawn();
UpdateMarkers();
if (refreshRate > 0f) {
if (asChild) {
InvokeRepeating(nameof(UpdatePosition), refreshRate, refreshRate);
}
else {
InvokeRepeating(nameof(UpdateMarkers), refreshRate, refreshRate);
}
}
}
private void UpdatePosition() {
if (asChild == true) {
if (parent.IsValid() == false) {
Destroy(this);
return;
}
else {
var pos = parent.transform.position;
transform.position = pos;
vending.transform.position = pos;
}
}
UpdateMarkers();
}
private void UpdateMarkers() {
vending.SendNetworkUpdate();
generic.SendUpdate();
}
private void DestroyMakers() {
if (vending.IsValid()) {
vending.Kill();
}
if (generic.IsValid()) {
generic.Kill();
}
}
private void OnDestroy() {
DestroyMakers();
}
}
#endregion
#endregion
#region Initialization
private void Init() {
LoadData("Quest", ref QuestList, false);
LoadData("Players", ref PlayerQuests, true);
LoadData();
}
private void OnServerInitialized() {
if (!ImageLibrary) {
PrintError($"ERROR! Plugin ImageLibrary not found!");
Interface.Oxide.UnloadPlugin(Title);
}
instance = this;
foreach (var player in BasePlayer.activePlayerList) OnPlayerConnected(player);
for (int i = 0; i < QuestList.Count; i++) {
for (int u = 0; u < QuestList[i].PrizeList.Count; u++) {
ImageLibrary.Call("AddImage", QuestList[i].PrizeList[u].ExternalURL, QuestList[i].PrizeList[u].ExternalURL);
if (QuestList[i].PrizeList[u].Skin != 0) ImageLibrary.Call("AddImage", $"http://api.skyplugins.ru/api/getskin/{QuestList[i].PrizeList[u].Skin}", QuestList[i].PrizeList[u].Shortname, QuestList[i].PrizeList[u].Skin);
}
}
if (!TryPlaceSign()) {
PrintError($"ERROR! Plugin could not place sign!");
return;
}
}
void OnServerSave() {
SaveData();
}
#endregion
#region Functions
private bool TryPlaceSign() {
var monument = UnityEngine.Object.FindObjectsOfType<MonumentInfo>().FirstOrDefault(p => p.name.Contains("compound"));
if (monument == null) {
return false;
}
Vector3 resultVector = monument.transform.position + monument.transform.rotation * new Vector3(-5.4f, 0, -0.5f);
List<BaseEntity> baseEntities = new List<BaseEntity>();
Vis.Entities(resultVector, 3f, baseEntities);
if (baseEntities.Count > 0) {
foreach (var ent in baseEntities) {
if (ent.PrefabName.Contains("sign.post.town.roof") || ent.PrefabName.Contains("excavator_output_pile")) ent.Kill();
}
}
timer.Once(1, () => {
Sign = GameManager.server.CreateEntity("assets/prefabs/deployable/signs/sign.post.town.roof.prefab", resultVector, monument.transform.rotation);
Box = GameManager.server.CreateEntity("assets/content/structures/excavator/prefabs/excavator_output_pile.prefab", resultVector + Vector3.up, monument.transform.rotation);
Sign.SetFlag(BaseEntity.Flags.Locked, true);
Sign.SetFlag(BaseEntity.Flags.Busy, true);
Sign.Spawn();
Box.skinID = 1195832261;
Box.Spawn();
RemoveProblemComponents(Sign);
RemoveProblemComponents(Box);
if (config.MapMarkers) CreateMarker(Sign.transform.position, 5, "ЗАДАНИЯ", "ЗАДАНИЯ");
RustMap?.Call("AddTemporaryMarker", "https://i.imgur.com/UtXBFFQ.png", "ЗАДАНИЯ", Sign.transform.position);
ServerMgr.Instance.StartCoroutine(DownloadImage(config.ImageURL, Sign as Signage));
}
);
return true;
}
#endregion
#region Hooks
object CanLootEntity(BasePlayer player, StorageContainer container) {
if (container.skinID == 1195832261) {
player.SetFlag(BaseEntity.Flags.Reserved3, true);
UI_DrawInterface(player);
return false;
}
return null;
}
void OnNewSave(string filename) {
if (config.WipeData) {
PlayerQuests.Clear();
storedData.players.Clear();
PrintWarning("Обнаружен WIPE.Дата игроков сброшена");
}
}
private void Unload() {
for (int i = 0; i < BasePlayer.activePlayerList.Count; i++) {
var player = BasePlayer.activePlayerList[i];
if (UiOpen.Contains(player.userID)) {
UiOpen.Remove(player.userID);
}
CuiHelper.DestroyUi(player, Layer);
BasePlayer p = BasePlayer.activePlayerList[i];
p.SetFlag(BaseEntity.Flags.Reserved3, false);
}
Sign?.Kill();
Box?.Kill();
SaveData("Quest", QuestList, false);
SaveData("Players", PlayerQuests, false);
SaveData();
if (config.MapMarkers) RemoveMarkers();
}
void OnPlayerConnected(BasePlayer player) {
if (!PlayerQuests.ContainsKey(player.userID)) PlayerQuests.Add(player.userID, new List<PlayerQuest>());
if (!storedData.players.ContainsKey(player.userID)) {
storedData.players.Add(player.userID, new PlayerData());
}
}
#region Type Upgrade
object OnStructureUpgrade(BaseCombatEntity entity, BasePlayer player, BuildingGrade.Enum grade) {
List<PlayerQuest> playerQuests = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.улучшить && playerQuests[i].Finished == false) {
if ((int)grade == Convert.ToInt16(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
}
}
return null;
}
#endregion
#region Type death
void OnPlayerDeath(BasePlayer player, HitInfo info) {
if (player == null || info == null || player.userID < 2147483647) return;
List<PlayerQuest> playerQuests = null;
BasePlayer attacker = info.InitiatorPlayer;
if (attacker == null) return;
if (IsFriends(player.userID, attacker.userID) || IsClans(player.userID, attacker.userID) || IsDuel(attacker.userID) || player.userID == attacker.userID) return;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.убить && playerQuests[i].Finished == false) {
if (playerQuests[i].parentQuest.Target.Contains("player")) {
playerQuests[i].AddCount();
}
}
}
}
}
void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
try {
if (entity == null || info == null) return;
List<PlayerQuest> playerQuests = null;
string targetName = entity?.ShortPrefabName;
if (targetName.Contains("corpse") || targetName.Contains("servergibs") || targetName.Contains("player")) return;
if (targetName == "testridablehorse") {
targetName = "horse";
}
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 && !player.IsNpc && entity.ToPlayer() != player) {
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.убить && playerQuests[i].Finished == false) {
if (entity.PrefabName.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount();
}
}
}
}
}
}
catch (Exception ex) {
}
}
#endregion
#region Type loot
private void OnLootEntity(BasePlayer player, BaseEntity entity) {
if (entity.OwnerID == 1337228 || entity.OwnerID >= 7656000000 || entity.GetComponent<LootContainer>() == null) return;
List<PlayerQuest> playerQuests = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.найти && playerQuests[i].Finished == false) {
for (int u = 0; u < entity.GetComponent<LootContainer>().inventory.itemList.Count();
u++) {
if (entity.GetComponent<LootContainer>().inventory.itemList[u].info.shortname.Contains(playerQuests[i].parentQuest.Target)) playerQuests[i].AddCount(entity.GetComponent<LootContainer>().inventory.itemList[u].amount);
}
}
}
}
entity.OwnerID = 1337228;
}
private void OnLootEntity(BasePlayer player, NPCPlayerCorpse entity) {
if (entity.OwnerID == 133722822222222 || entity.OwnerID >= 7656000000 || entity == null) return;
List<PlayerQuest> playerQuests = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.найти && playerQuests[i].Finished == false) {
for (int u = 0; u < entity.containers[0].itemList.Count();
u++) {
if (entity.containers[0].itemList[u].info.shortname.Contains(playerQuests[i].parentQuest.Target) || entity.containers[0].itemList[u].skin.ToString() == playerQuests[i].parentQuest.Target) playerQuests[i].AddCount(entity.containers[0].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 = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.найти && playerQuests[i].Finished == false) {
if (item.info.shortname.Contains(playerQuests[i].parentQuest.Target) || item.skin.ToString() == playerQuests[i].parentQuest.Target) playerQuests[i].AddCount(item.amount);
}
}
}
return null;
}
#endregion
#region Type Gather
private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item) {
NextTick(() => {
BasePlayer player;
if (entity is BasePlayer) {
player = entity as BasePlayer;
List<PlayerQuest> playerQuests = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.добыть && playerQuests[i].Finished == false) {
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 = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.добыть && playerQuests[i].Finished == false) {
if (item.info.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount(item.amount);
}
}
}
}
}
#endregion
#region Type craft
void OnItemCraftFinished(ItemCraftTask task, Item item) {
var player = task.owner;
List<PlayerQuest> playerQuests = null;
if (player != null && PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
for (int i = 0; i < playerQuests.Count; i++) {
if (playerQuests[i].parentQuest.QuestType == QuestType.скрафтить && playerQuests[i].Finished == false) {
if (task.blueprint.targetItem.shortname.Contains(playerQuests[i].parentQuest.Target)) {
playerQuests[i].AddCount(item.amount);
}
}
}
}
}
#endregion
#endregion
#region Commands
[ChatCommand("quest")]
private void CmdChatQuest(BasePlayer player, string command, string[] args) {
List<PlayerQuest> playerQuests = null;
if (PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
if (args.Length > 0) {
switch (args[0].ToLower()) {
case "list" : {
if (playerQuests.Count == 0) {
SendChat(lang.GetMessage("QUEST_ACTIVE", this, player.UserIDString), lang.GetMessage("QUEST_ACTIVE_comp", this, player.UserIDString), player);
return;
}
else {
string message = "";
for (int i = 0; i < playerQuests.Count; i++) {
message += $"\n{i + 1}.{playerQuests[i].parentQuest.DisplayName}\n\n" + $"{playerQuests[i].parentQuest.Description}\n";
if (playerQuests[i].Finished) {
message += lang.GetMessage("QUEST_ACTIVE_PROGRESS", this, player.UserIDString);
}
else {
message += String.Format(lang.GetMessage("QUEST_ACTIVE_PROGRESS_GO", this, player.UserIDString), playerQuests[i].parentQuest.QuestType.ToString(), playerQuests[i].LeftAmount(), playerQuests[i].parentQuest.NiceTarget);
}
}
SendChat(lang.GetMessage("QUEST_ACTIVE", this, player.UserIDString), message, player);
break;
}
}
}
}
}
}
[ConsoleCommand("UI_Handler")]
private void CmdConsoleHandler(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
List<PlayerQuest> playerQuests = null;
if (player != null && args.HasArgs(1) && PlayerQuests.TryGetValue(player.userID, out playerQuests)) {
switch (args.Args[0]) {
case "get" : {
int questIndex;
if (args.HasArgs(2) && int.TryParse(args.Args[1], out questIndex)) {
var currentQuest = QuestList.ElementAtOrDefault(questIndex);
if (currentQuest != null) {
if (playerQuests.Count >= config.MaxQuestAmount) {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), lang.GetMessage("QUEST_ACTIVE_LIMIT", this, player.UserIDString), player);
return;
}
if (playerQuests.Any(p => p.parentQuest.DisplayName == currentQuest.DisplayName)) {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), lang.GetMessage("QUEST_took_tasks", this, player.UserIDString), player);
return;
}
if (!config.QuestGo && storedData.players[player.userID].PlayerQuestsFinish.Contains(currentQuest.DisplayName)) {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), lang.GetMessage("QUEST_completed_tasks", this, player.UserIDString), player);
return;
}
playerQuests.Add(new PlayerQuest() {
UserID = player.userID, parentQuest = currentQuest
}
);
if (currentQuest.Cooldown != 0) {
if (!storedData.players[player.userID].PlayerQuestsCooldown.ContainsKey(currentQuest.DisplayName)) {
storedData.players[player.userID].PlayerQuestsCooldown.Add(currentQuest.DisplayName, 0);
}
}
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), String.Format(lang.GetMessage("QUEST_completed_took", this, player.UserIDString), currentQuest.DisplayName), player);
UI_DrawInterface(player, 0, questIndex.ToString());
}
}
break;
}
case "page" : {
int pageIndex;
if (int.TryParse(args.Args[1], out pageIndex)) {
UI_DrawInterface(player, pageIndex);
}
break;
}
case "finish" : {
int questIndex;
if (args.HasArgs(2) && int.TryParse(args.Args[1], out questIndex)) {
var globalQuest = QuestList.ElementAtOrDefault(questIndex);
if (globalQuest != null) {
var currentQuest = playerQuests.FirstOrDefault(p => p.parentQuest.DisplayName == globalQuest.DisplayName);
if (currentQuest == null) return;
if (currentQuest.Finished) {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), lang.GetMessage("QUEST_tasks_completed", this, player.UserIDString), player);
if (24 - player.inventory.containerMain.itemList.Count < currentQuest.parentQuest.PrizeList.Count) {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), lang.GetMessage("QUEST_no_place", this, player.UserIDString), player);
return;
}
else {
currentQuest.Finished = false;
for (int i = 0; i < currentQuest.parentQuest.PrizeList.Count; i++) {
var check = currentQuest.parentQuest.PrizeList[i];
if (check.Shortname != "") {
if (check.CustomItem) {
Item newItem = ItemManager.CreateByPartialName(check.Shortname, check.Amount, check.Skin);
newItem.name = check.DisplayName;
newItem.MoveToContainer(player.inventory.containerMain);
}
else {
Item newItem = ItemManager.CreateByPartialName(check.Shortname, check.Amount);
if (check.Skin != 0) newItem.skin = check.Skin;
newItem.MoveToContainer(player.inventory.containerMain);
}
}
if (check.Command != "") {
Server.Command(check.Command.Replace("%STEAMID%", player.UserIDString));
}
}
}
if (!config.QuestGo && globalQuest.Cooldown == 0) {
storedData.players[player.userID].PlayerQuestsFinish.Add(globalQuest.DisplayName);
}
else {
storedData.players[player.userID].PlayerQuestsCooldown[globalQuest.DisplayName] = GetTimeStamp() + globalQuest.Cooldown;
}
playerQuests.Remove(currentQuest);
}
else {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), lang.GetMessage("QUEST_did_not_cope", this, player.UserIDString), player);
playerQuests.Remove(currentQuest);
}
UI_DrawInterface(player, 0, questIndex.ToString());
}
else {
SendChat(lang.GetMessage("QUEST", this, player.UserIDString), $"Вы <color=#4286f4>не брали</color> этого задания!", player);
}
}
break;
}
}
}
}
public List<ulong> UiOpen = new List<ulong>();
[ConsoleCommand("Close_UI")]
void CloseUiPlayer(ConsoleSystem.Arg arg) {
arg.Player().SetFlag(BaseEntity.Flags.Reserved3, false);
CuiHelper.DestroyUi(arg.Player(), Layer);
if (UiOpen.Contains(arg.Player().userID)) {
UiOpen.Remove(arg.Player().userID);
}
}
#endregion
private IEnumerator StartUpdate(BasePlayer player) {
while (player.HasFlag(BaseEntity.Flags.Reserved3)) {
for (int i = 0; i < QuestList.Count();
i++) {
var check = QuestList[i];
string questLayer = Layer + $".{i}";
if (storedData.players[player.userID].PlayerQuestsCooldown.ContainsKey(check.DisplayName)) {
if (storedData.players[player.userID]?.PlayerQuestsCooldown[check.DisplayName] >= GetTimeStamp()) {
CuiElementContainer container = new CuiElementContainer();
// ... [Code preview truncated due to length. Full source in attached file] ...