Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Linq;
- using Oxide.Core;
- using Oxide.Core.Plugins;
- using Oxide.Game.Rust.Cui;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- namespace Oxide.Plugins
- {
- [Info("QuestSystem", "SeuNome", "1.4.1")]
- [Description("Sistema de missões com divisão por mercadores")]
- public class QuestSystem : RustPlugin
- {
- #region Configuration
- private class QuestConfig
- {
- public List<Quest> Quests { get; set; } = new List<Quest>();
- }
- private class Quest
- {
- public string Id { get; set; }
- public string Merchant { get; set; }
- public string Title { get; set; }
- public string Description { get; set; }
- public Objective Objective { get; set; }
- public Reward Reward { get; set; }
- public int CooldownHours { get; set; } = 1;
- }
- private class Objective
- {
- public string Target { get; set; }
- public int RequiredAmount { get; set; }
- }
- private class Reward
- {
- public Dictionary<string, int> Items { get; set; } = new Dictionary<string, int>();
- public int Scrap { get; set; }
- }
- private QuestConfig config;
- #endregion
- #region Data
- private class PlayerQuestData
- {
- public Dictionary<string, int> Progress { get; set; } = new Dictionary<string, int>();
- public Dictionary<string, DateTime> Cooldowns { get; set; } = new Dictionary<string, DateTime>();
- }
- private Dictionary<ulong, PlayerQuestData> playerData = new Dictionary<ulong, PlayerQuestData>();
- #endregion
- #region Localization
- protected override void LoadDefaultMessages()
- {
- lang.RegisterMessages(new Dictionary<string, string>
- {
- ["UI.Title"] = "MISSÕES DOS MERCADORES",
- ["UI.Active"] = "EM PROGRESSO",
- ["UI.Accept"] = "ACEITAR",
- ["UI.Complete"] = "COMPLETAR",
- ["UI.Cooldown"] = "EM COOLDOWN",
- ["UI.Close"] = "FECHAR",
- ["Quest.Started"] = "Missão '{0}' iniciada! Objetivo: {1}",
- ["Quest.Progress"] = "Missão '{0}': {1}/{2}",
- ["Quest.Completed"] = "Missão '{0}' completada! Recompensas recebidas.",
- ["Quest.Cooldown"] = "Esta missão está em cooldown. Disponível em: {0}",
- ["Error.NotFound"] = "Missão não encontrada.",
- ["Error.NeedShotgun"] = "Você precisa ter uma shotgun no inventário para aceitar esta missão.",
- ["Error.NeedSyringes"] = "Você precisa de 2 Seringas Médicas no inventário (Separadas caso esteja juntas) para finalizar esta missão."
- }, this);
- }
- private string GetMessage(string key, BasePlayer player = null) => lang.GetMessage(key, this, player?.UserIDString);
- #endregion
- #region Oxide Hooks
- protected override void LoadDefaultConfig()
- {
- Config.WriteObject(new QuestConfig
- {
- Quests = new List<Quest>
- {
- new Quest
- {
- Id = "deliver_mp5_holo",
- Merchant = "Mecânico Lencer",
- Title = "Upgrade Óptico",
- Description = "Entregue uma MP5 com Mira Holográfica acoplada (no inventário)",
- Objective = new Objective { Target = "smg.mp5", RequiredAmount = 1 },
- Reward = new Reward
- {
- Scrap = 600,
- Items = new Dictionary<string, int>
- {
- ["smg.2"] = 1
- }
- },
- CooldownHours = 2
- },
- new Quest
- {
- Id = "deliver_syringes",
- Merchant = "Serafist Médica",
- Title = "Para o Bem Maior",
- Description = "Entregue 2 Seringas Médicas (Coloque no Inventário)",
- Objective = new Objective { Target = "syringe.medical", RequiredAmount = 2 },
- Reward = new Reward
- {
- Scrap = 300,
- Items = new Dictionary<string, int>
- {
- ["smg.2"] = 1 // Submetralhadora como exemplo de recompensa
- }
- },
- CooldownHours = 2
- },
- new Quest
- {
- Id = "deliver_healing_tea",
- Merchant = "Serafist Médica",
- Title = "Remédio Natural",
- Description = "Entregue 5 Chás de Cura Puro (Coloque no Inventário)",
- Objective = new Objective { Target = "tea.advanced.healing", RequiredAmount = 5 },
- Reward = new Reward
- {
- Scrap = 250,
- Items = new Dictionary<string, int>
- {
- ["syringe.medical"] = 2,
- ["bandage"] = 5
- }
- },
- CooldownHours = 3
- },
- new Quest
- {
- Id = "wolf_hunter",
- Merchant = "Caçador Spike",
- Title = "Caçador de Lobos",
- Description = "Mate 5 lobos para receber recompensas",
- Objective = new Objective { Target = "wolf", RequiredAmount = 5 },
- Reward = new Reward
- {
- Items = new Dictionary<string, int>
- {
- ["rifle.bolt"] = 1,
- ["ammo.rifle"] = 64
- },
- Scrap = 250
- },
- CooldownHours = 2
- },
- new Quest
- {
- Id = "bear_slayer",
- Merchant = "Caçador Spike",
- Title = "Matador de Ursos",
- Description = "Elimine 3 ursos para provar sua coragem",
- Objective = new Objective { Target = "bear", RequiredAmount = 3 },
- Reward = new Reward
- {
- Items = new Dictionary<string, int>
- {
- ["rifle.ak"] = 1,
- ["ammo.rifle"] = 128
- },
- Scrap = 500
- },
- CooldownHours = 4
- },
- new Quest
- {
- Id = "deliver_shotgun",
- Merchant = "Mecânico Lencer",
- Title = "PUMP! PUMP!",
- Description = "Entregue uma Escopeta de Repetição (Coloque no Inventário)",
- Objective = new Objective { Target = "shotgun.pump", RequiredAmount = 1 },
- Reward = new Reward
- {
- Scrap = 500,
- Items = new Dictionary<string, int>
- {
- ["pistol.eoka"] = 1
- }
- },
- CooldownHours = 1
- }
- }
- }, true);
- }
- void Init()
- {
- config = Config.ReadObject<QuestConfig>();
- LoadDefaultMessages();
- }
- void OnServerInitialized()
- {
- Puts($"Sistema de missões carregado com {config.Quests.Count} missões disponíveis");
- }
- void Unload()
- {
- foreach (var player in BasePlayer.activePlayerList)
- {
- CuiHelper.DestroyUi(player, "QuestUI");
- }
- }
- #endregion
- #region Quest Logic
- private void StartQuest(BasePlayer player, Quest quest)
- {
- if (!playerData.TryGetValue(player.userID, out var data))
- {
- data = new PlayerQuestData();
- playerData[player.userID] = data;
- }
- data.Progress[quest.Id] = 0;
- SendReply(player, string.Format(GetMessage("Quest.Started", player), quest.Title, quest.Description));
- }
- private void CompleteQuest(BasePlayer player, Quest quest, PlayerQuestData data)
- {
- foreach (var item in quest.Reward.Items)
- {
- var itemObj = ItemManager.CreateByName(item.Key, item.Value);
- player.GiveItem(itemObj);
- }
- if (quest.Reward.Scrap > 0)
- {
- var scrap = ItemManager.CreateByName("scrap", quest.Reward.Scrap);
- player.GiveItem(scrap);
- }
- data.Progress.Remove(quest.Id);
- data.Cooldowns[quest.Id] = DateTime.Now.AddHours(quest.CooldownHours);
- SendReply(player, string.Format(GetMessage("Quest.Completed", player), quest.Title));
- CuiHelper.DestroyUi(player, "QuestUI");
- ShowQuestUI(player, quest.Merchant);
- }
- #endregion
- #region UI
- [ConsoleCommand("quest.open")]
- private void OpenQuestUI(ConsoleSystem.Arg arg)
- {
- var player = arg.Player();
- if (player == null) return;
- string merchant = arg.Args.Length > 0 ? string.Join(" ", arg.Args).Trim('"') : "Caçador Spike";
- ShowQuestUI(player, merchant);
- }
- [ChatCommand("quest")]
- private void QuestCommand(BasePlayer player, string command, string[] args)
- {
- string merchant = args.Length > 0 ? string.Join(" ", args) : "Caçador Spike";
- ShowQuestUI(player, merchant);
- }
- [ConsoleCommand("quest.accept")]
- private void AcceptQuest(ConsoleSystem.Arg arg)
- {
- var player = arg.Player();
- if (player == null) return;
- string questId = arg.GetString(0);
- var quest = config.Quests.FirstOrDefault(q => q.Id == questId);
- if (quest == null)
- {
- SendReply(player, GetMessage("Error.NotFound", player));
- return;
- }
- if (!playerData.TryGetValue(player.userID, out var data))
- {
- data = new PlayerQuestData();
- playerData[player.userID] = data;
- }
- if (data.Cooldowns.TryGetValue(questId, out var cooldownEnd))
- {
- if (cooldownEnd > DateTime.Now)
- {
- var remaining = cooldownEnd - DateTime.Now;
- SendReply(player, string.Format(GetMessage("Quest.Cooldown", player),
- $"{remaining.Hours}h {remaining.Minutes}m"));
- return;
- }
- else
- {
- data.Cooldowns.Remove(questId);
- }
- }
- if (quest.Id == "deliver_shotgun")
- {
- var shotgun = player.inventory.containerMain
- .itemList.FirstOrDefault(i => i.info.shortname == "shotgun.pump");
- if (shotgun == null)
- {
- SendReply(player, GetMessage("Error.NeedShotgun", player));
- return;
- }
- shotgun.RemoveFromContainer();
- shotgun.Remove();
- CompleteQuest(player, quest, data);
- CuiHelper.DestroyUi(player, "QuestUI");
- ShowQuestUI(player, quest.Merchant);
- return;
- }
- else if (quest.Id == "deliver_syringes")
- {
- var syringes = player.inventory.containerMain
- .itemList.Where(i => i.info.shortname == "syringe.medical").ToList();
- int total = syringes.Sum(i => i.amount);
- if (total < quest.Objective.RequiredAmount)
- {
- SendReply(player, GetMessage("Error.NeedSyringes", player));
- return;
- }
- int needed = quest.Objective.RequiredAmount;
- foreach (var syringe in syringes)
- {
- if (needed <= 0) break;
- if (syringe.amount <= needed)
- {
- needed -= syringe.amount;
- syringe.RemoveFromContainer();
- syringe.Remove();
- }
- else
- {
- syringe.UseItem(needed);
- needed = 0;
- }
- }
- CompleteQuest(player, quest, data);
- CuiHelper.DestroyUi(player, "QuestUI");
- ShowQuestUI(player, quest.Merchant);
- return;
- }
- else if (quest.Id == "deliver_healing_tea")
- {
- var teas = player.inventory.containerMain
- .itemList.Where(i => i.info.shortname == "tea.advanced.healing").Take(quest.Objective.RequiredAmount).ToList();
- if (teas.Count < quest.Objective.RequiredAmount)
- {
- SendReply(player, "Você precisa de 5 Chás de Cura Puro no inventário para completar esta missão.");
- return;
- }
- foreach (var tea in teas)
- {
- tea.UseItem(1);
- tea.RemoveFromContainer();
- tea.Remove();
- }
- CompleteQuest(player, quest, data);
- CuiHelper.DestroyUi(player, "QuestUI");
- ShowQuestUI(player, quest.Merchant);
- return;
- }
- else if (quest.Id == "deliver_mp5_holo")
- {
- var mp5WithHolo = player.inventory.containerMain.itemList.FirstOrDefault(item =>
- {
- // Verifica se o item é uma MP5
- if (item.info.shortname != "smg.mp5") return false;
- // Verifica se o item tem 'contents' e se há um mod de mira holográfica
- if (item.contents != null)
- {
- foreach (var mod in item.contents.itemList)
- {
- if (mod.info.shortname == "weapon.mod.holosight")
- {
- return true; // Encontrou a mira holográfica
- }
- }
- }
- return false; // Não encontrou o mod de mira holográfica
- });
- if (mp5WithHolo == null)
- {
- SendReply(player, "Você precisa de uma MP5 com Mira Holográfica acoplada no inventário para completar esta missão.");
- return;
- }
- mp5WithHolo.RemoveFromContainer();
- mp5WithHolo.Remove();
- CompleteQuest(player, quest, data);
- CuiHelper.DestroyUi(player, "QuestUI");
- ShowQuestUI(player, quest.Merchant);
- return;
- }
- StartQuest(player, quest);
- CuiHelper.DestroyUi(player, "QuestUI");
- ShowQuestUI(player, quest.Merchant);
- }
- [ConsoleCommand("quest.close")]
- private void CloseQuestUI(ConsoleSystem.Arg arg)
- {
- var player = arg.Player();
- if (player == null) return;
- CuiHelper.DestroyUi(player, "QuestUI");
- }
- void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
- {
- if (entity == null || info?.InitiatorPlayer == null) return;
- var player = info.InitiatorPlayer;
- var prefab = entity.ShortPrefabName;
- if (!playerData.TryGetValue(player.userID, out var data)) return;
- foreach (var quest in config.Quests)
- {
- if (quest.Objective.Target == prefab && data.Progress.TryGetValue(quest.Id, out var progress))
- {
- data.Progress[quest.Id] = ++progress;
- if (progress >= quest.Objective.RequiredAmount)
- {
- CompleteQuest(player, quest, data);
- }
- else
- {
- SendReply(player, string.Format(GetMessage("Quest.Progress", player),
- quest.Title, progress, quest.Objective.RequiredAmount));
- }
- break;
- }
- }
- }
- private string EscapeQuotes(string input)
- {
- return "\"" + input.Replace("\"", "\\\"") + "\"";
- }
- private void ShowQuestUI(BasePlayer player, string selectedMerchant)
- {
- Puts($"[DEBUG] selectedMerchant recebido: '{selectedMerchant}'");
- CuiHelper.DestroyUi(player, "QuestUI");
- var container = new CuiElementContainer();
- var merchants = config.Quests.Select(q => q.Merchant).Distinct().ToList();
- string panel = container.Add(new CuiPanel
- {
- Image = { Color = "0.1 0.1 0.1 0.97" },
- RectTransform = { AnchorMin = "0.25 0.15", AnchorMax = "0.75 0.85" },
- CursorEnabled = true
- }, "Overlay", "QuestUI");
- // Título
- container.Add(new CuiLabel
- {
- Text = { Text = "<size=16>" + GetMessage("UI.Title", player) + "</size>", FontSize = 14, Align = TextAnchor.MiddleCenter },
- RectTransform = { AnchorMin = "0.05 0.93", AnchorMax = "0.95 0.98" }
- }, panel);
- // Criação dos botões de mercadores no topo
- float buttonWidth = 1f / merchants.Count;
- for (int i = 0; i < merchants.Count; i++)
- {
- string merchant = merchants[i];
- bool isSelected = merchant == selectedMerchant;
- container.Add(new CuiButton
- {
- Button =
- {
- Color = isSelected ? "0.3 0.6 0.3 1" : "0.2 0.2 0.2 1",
- Command = $"quest.open {EscapeQuotes(merchant)}"
- },
- Text = { Text = merchant, FontSize = 12, Align = TextAnchor.MiddleCenter },
- RectTransform =
- {
- AnchorMin = $"{i * buttonWidth} 0.86",
- AnchorMax = $"{(i + 1) * buttonWidth} 0.93"
- }
- }, panel);
- }
- bool hasData = playerData.TryGetValue(player.userID, out var data);
- float yPos = 0.8f;
- float questHeight = 0.15f;
- float spacing = 0.02f;
- // Filtrar missões do mercador selecionado
- var selectedQuests = config.Quests
- .Where(q => string.Equals(q.Merchant, selectedMerchant, StringComparison.OrdinalIgnoreCase))
- .ToList();
- if (selectedQuests.Count == 0)
- {
- // Mensagem de "em breve"
- container.Add(new CuiLabel
- {
- Text = { Text = "<color=#FFA500>Em breve...</color>", FontSize = 14, Align = TextAnchor.MiddleCenter },
- RectTransform = { AnchorMin = "0.1 0.4", AnchorMax = "0.9 0.6" }
- }, panel);
- }
- else
- {
- foreach (var quest in selectedQuests)
- {
- string questPanel = container.Add(new CuiPanel
- {
- Image = { Color = "0.2 0.2 0.2 0.9" },
- RectTransform = { AnchorMin = $"0.05 {yPos - questHeight}", AnchorMax = $"0.95 {yPos}" }
- }, panel);
- container.Add(new CuiLabel
- {
- Text = { Text = $"<color=#00FF00>{quest.Title}</color>\n{quest.Description}", FontSize = 12, Align = TextAnchor.MiddleLeft },
- RectTransform = { AnchorMin = "0.05 0.2", AnchorMax = "0.7 0.8" }
- }, questPanel);
- string buttonText;
- string buttonColor;
- string buttonCommand;
- if (hasData && data.Cooldowns.TryGetValue(quest.Id, out var cooldown))
- {
- if (cooldown > DateTime.Now)
- {
- buttonText = GetMessage("UI.Cooldown", player);
- buttonColor = "0.5 0.5 0.5 1";
- buttonCommand = "";
- }
- else
- {
- buttonText = GetMessage("UI.Accept", player);
- buttonColor = "0.2 0.7 0.2 1";
- buttonCommand = $"quest.accept {quest.Id}";
- }
- }
- else if (hasData && data.Progress.TryGetValue(quest.Id, out var progress))
- {
- buttonText = $"{progress}/{quest.Objective.RequiredAmount}";
- buttonColor = "0.2 0.5 0.8 1";
- buttonCommand = "";
- }
- else
- {
- buttonText = GetMessage("UI.Accept", player);
- buttonColor = "0.2 0.7 0.2 1";
- buttonCommand = $"quest.accept {quest.Id}";
- }
- container.Add(new CuiButton
- {
- Button = { Color = buttonColor, Command = buttonCommand },
- Text = { Text = buttonText, FontSize = 12, Align = TextAnchor.MiddleCenter },
- RectTransform = { AnchorMin = "0.75 0.3", AnchorMax = "0.9 0.7" }
- }, questPanel);
- yPos -= questHeight + spacing;
- }
- }
- // Botão de Fechar
- container.Add(new CuiButton
- {
- Button = { Color = "0.7 0.1 0.1 1", Command = "quest.close" },
- Text = { Text = GetMessage("UI.Close", player), FontSize = 14, Align = TextAnchor.MiddleCenter },
- RectTransform = { AnchorMin = "0.3 0.02", AnchorMax = "0.7 0.07" }
- }, panel);
- CuiHelper.AddUi(player, container);
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement