Failed to compile: 'PlayerInventory' does not contain a definition for 'AllItems' and no accessible extension method 'AllItems' accepting a first argument of type 'PlayerInventory' could be found (are you missing a using directive or an assembly reference?) | Line: 984, pos: 46
Broken after October Update
Same, broken
chatGPT suggested to change
if (player.inventory.AllItems().Count() >= 30)
to
if (player.inventory.containerMain.itemList.Count >= 30)
it compiled <shrug>
Hmm, worked for me
Same... so far. Thanks !
Lawnmorr
chatGPT suggested to change
if (player.inventory.AllItems().Count() >= 30)
to
if (player.inventory.containerMain.itemList.Count >= 30)it compiled <shrug>
lol what the heck do you use for prompts??? XD
theres 2 plugins i cant use because the dev went POOF for them.
broken
Merged post
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Facepunch;
// ToDo: ZLevels integration (waiting for ZLevels api implementation)
// ToDo: Add Cooldown option for Delivery
namespace Oxide.Plugins
{
[Info("Quests", "Gonzi", "2.4.3")]
[Description("Creates quests for players to go on to earn rewards, complete with a GUI menu")]
public class Quests : RustPlugin
{
#region Fields
[PluginReference] Plugin HumanNPC;
[PluginReference] Plugin ServerRewards;
[PluginReference] Plugin Economics;
[PluginReference] Plugin LustyMap;
[PluginReference] Plugin EventManager;
[PluginReference] Plugin HuntRPG;
[PluginReference] Plugin PlayerChallenges;
[PluginReference] Plugin BetterChat;
ConfigData configData;
QuestData questData;
PlayerData playerData;
NPCData vendors;
ItemNames itemNames;
private DynamicConfigFile Quest_Data;
private DynamicConfigFile Player_Data;
private DynamicConfigFile Quest_Vendors;
private DynamicConfigFile Item_Names;
private Dictionary<ulong, PlayerQuestData> PlayerProgress;
private Dictionary<QuestType, Dictionary<string, QuestEntry>> Quest;
private Dictionary<string, ItemDefinition> ItemDefs;
private Dictionary<string, string> DisplayNames = new Dictionary<string, string>();
private Dictionary<ulong, QuestCreator> ActiveCreations = new Dictionary<ulong, QuestCreator>();
private Dictionary<ulong, QuestCreator> ActiveEditors = new Dictionary<ulong, QuestCreator>();
private Dictionary<ulong, bool> AddVendor = new Dictionary<ulong, bool>();
private Dictionary<QuestType, List<string>> AllObjectives = new Dictionary<QuestType, List<string>>();
private Dictionary<NetworkableId, Dictionary<ulong, int>> HeliAttackers = new Dictionary<NetworkableId, Dictionary<ulong, int>>();
private Dictionary<ulong, List<string>> OpenUI = new Dictionary<ulong, List<string>>();
private Dictionary<ItemId, ulong> Looters = new Dictionary<ItemId, ulong>();
private List<ulong> StatsMenu = new List<ulong>();
private List<ulong> OpenMenuBind = new List<ulong>();
static string UIMain = "UIMain";
static string UIPanel = "UIPanel";
static string UIEntry = "UIEntry";
static string permission_manage = "quests.manage";
static string permission_use = "quests.use";
private string textPrimary;
private string textSecondary;
#endregion
#region Classes
class PlayerQuestData
{
public Dictionary<string, PlayerQuestInfo> Quests = new Dictionary<string, PlayerQuestInfo>();
public List<QuestInfo> RequiredItems = new List<QuestInfo>();
public ActiveDelivery CurrentDelivery = new ActiveDelivery();
}
class PlayerQuestInfo
{
public QuestStatus Status;
public QuestType Type;
public int AmountCollected = 0;
public bool RewardClaimed = false;
public double ResetTime = 0;
}
class QuestEntry
{
public string QuestName;
public string Description;
public string Objective;
public string ObjectiveName;
public int AmountRequired;
public int Cooldown;
public bool ItemDeduction;
public List<RewardItem> Rewards;
}
class NPCInfo
{
public float x;
public float z;
public string ID;
public string Name;
}
class DeliveryInfo
{
public string Description;
public NPCInfo Info;
public RewardItem Reward;
public float Multiplier;
}
class ActiveDelivery
{
public string VendorID;
public string TargetID;
public float Distance;
}
class QuestInfo
{
public string ShortName;
public QuestType Type;
}
class RewardItem
{
public bool isRP = false;
public bool isCoins = false;
public bool isHuntXP = false;
public string DisplayName;
public string ShortName;
public int ID;
public float Amount;
public bool BP;
public ulong Skin;
}
class QuestCreator
{
public QuestType type;
public QuestEntry entry;
public DeliveryInfo deliveryInfo;
public RewardItem item;
public string oldEntry;
public int partNum;
}
class ItemNames
{
public Dictionary<string, string> DisplayNames = new Dictionary<string, string>();
}
enum QuestType
{
Kill,
Craft,
Gather,
Loot,
Delivery
}
enum QuestStatus
{
Pending,
Completed,
Open
}
#endregion
#region UI Creation
class QUI
{
public static bool disableFade;
static public CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, bool cursor = false)
{
var NewElement = new CuiElementContainer()
{
{
new CuiPanel
{
Image = {Color = color},
RectTransform = {AnchorMin = aMin, AnchorMax = aMax},
CursorEnabled = cursor
},
new CuiElement().Parent = "Overlay",
panelName
}
};
return NewElement;
}
static public void CreatePanel(ref CuiElementContainer container, string panel, string color, string aMin, string aMax, bool cursor = false)
{
container.Add(new CuiPanel
{
Image = { Color = color },
RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
CursorEnabled = cursor
},
panel);
}
static public void CreateLabel(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter, float fadein = 1.0f)
{
if (disableFade)
fadein = 0;
container.Add(new CuiLabel
{
Text = { Color = color, FontSize = size, Align = align, FadeIn = fadein, Text = text },
RectTransform = { AnchorMin = aMin, AnchorMax = aMax }
},
panel);
}
static public void CreateButton(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, string command, TextAnchor align = TextAnchor.MiddleCenter, float fadein = 1.0f)
{
if (disableFade)
fadein = 0;
container.Add(new CuiButton
{
Button = { Color = color, Command = command, FadeIn = fadein },
RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
Text = { Text = text, FontSize = size, Align = align }
},
panel);
}
static public void LoadImage(ref CuiElementContainer container, string panel, string png, string aMin, string aMax)
{
container.Add(new CuiElement
{
Parent = panel,
Components =
{
new CuiRawImageComponent {Png = png},
new CuiRectTransformComponent {AnchorMin = aMin, AnchorMax = aMax}
}
});
}
static public void CreateTextOverlay(ref CuiElementContainer container, string panel, string text, string color, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter, float fadein = 1.0f)
{
if (disableFade)
fadein = 0;
container.Add(new CuiLabel
{
Text = { Color = color, FontSize = size, Align = align, FadeIn = fadein, Text = text },
RectTransform = { AnchorMin = aMin, AnchorMax = aMax }
},
panel);
}
static public string Color(string hexColor, float alpha)
{
if (hexColor.StartsWith("#"))
hexColor = hexColor.TrimStart('#');
int red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
int green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
int blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255} {alpha}";
}
}
#endregion
#region Oxide Hooks
void Loaded()
{
permission.RegisterPermission(permission_use, this);
permission.RegisterPermission(permission_manage, this);
Quest_Data = Interface.Oxide.DataFileSystem.GetFile("Quests/quests_data");
Player_Data = Interface.Oxide.DataFileSystem.GetFile("Quests/quests_players");
Quest_Vendors = Interface.Oxide.DataFileSystem.GetFile("Quests/quests_vendors");
Item_Names = Interface.Oxide.DataFileSystem.GetFile("Quests/quests_itemnames");
lang.RegisterMessages(Localization, this);
}
void OnServerInitialized()
{
LoadVariables();
LoadData();
QUI.disableFade = configData.DisableUI_FadeIn;
textPrimary = $"<color={configData.Colors.TextColor_Primary}>";
textSecondary = $"<color={configData.Colors.TextColor_Secondary}>";
ItemDefs = ItemManager.itemList.ToDictionary(i => i.shortname);
FillObjectiveList();
AddMapIcons();
timer.Once(900, () => SaveLoop());
}
void Unload()
{
foreach (var player in BasePlayer.activePlayerList)
DestroyUI(player);
SavePlayerData();
}
void OnPlayerConnected(BasePlayer player)
{
if (configData.KeybindOptions.Autoset_KeyBind)
{
if (!string.IsNullOrEmpty(configData.KeybindOptions.KeyBind_Key))
{
player.Command("bind " + configData.KeybindOptions.KeyBind_Key + " QUI_OpenQuestMenu");
}
}
}
#region Objective Hooks
//Kill
void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
try
{
if (entity == null || info == null) return;
string entname = entity?.ShortPrefabName;
if (entname == "testridablehorse")
{
entname = "horse";
}
if ((entname.Contains("scientist")) && (!entname.Contains("corpse")))
{
entname = "scientist";
}
BasePlayer player = null;
if (info.InitiatorPlayer != null)
player = info.InitiatorPlayer;
else if (entity.GetComponent<BaseHelicopter>() != null)
player = BasePlayer.FindByID(GetLastAttacker(entity.net.ID));
if (player != null)
{
if (entity.ToPlayer() != null && entity.ToPlayer() == player) return;
if (isPlaying(player)) return;
if (hasQuests(player.userID) && isQuestItem(player.userID, entname, QuestType.Kill))
ProcessProgress(player, QuestType.Kill, entname);
}
}
catch (Exception ex)
{
PrintWarning("Error at hook OnEntityDeath:\n" + ex);
}
}
void OnEntityTakeDamage(BaseCombatEntity victim, HitInfo info)
{
if (victim.GetComponent<BaseHelicopter>() != null && info?.Initiator?.ToPlayer() != null)
{
var heli = victim.GetComponent<BaseHelicopter>();
var player = info.Initiator.ToPlayer();
if (isPlaying(player)) return;
NextTick(() =>
{
if (heli == null) return;
if (!HeliAttackers.ContainsKey(heli.net.ID))
HeliAttackers.Add(heli.net.ID, new Dictionary<ulong, int>());
if (!HeliAttackers[heli.net.ID].ContainsKey(player.userID))
HeliAttackers[heli.net.ID].Add(player.userID, 0);
HeliAttackers[heli.net.ID][player.userID]++;
});
}
}
// Gather
void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item)
{
BasePlayer player = entity?.ToPlayer();
if (player != null)
if (hasQuests(player.userID) && isQuestItem(player.userID, item.info.shortname, QuestType.Gather))
ProcessProgress(player, QuestType.Gather, item.info.shortname, item.amount);
}
void OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item) => OnDispenserGather(dispenser, entity, item);
void OnGrowableGather(GrowableEntity growable, Item item, BasePlayer player)
{
if (player != null)
if (hasQuests(player.userID) && isQuestItem(player.userID, item.info.shortname, QuestType.Gather))
ProcessProgress(player, QuestType.Gather, item.info.shortname, item.amount);
}
void OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player)
{
if (player != null)
foreach (ItemAmount itemAmount in collectible.itemList)
if (hasQuests(player.userID) && isQuestItem(player.userID, itemAmount.itemDef.shortname, QuestType.Gather))
ProcessProgress(player, QuestType.Gather, itemAmount.itemDef.shortname, (int)itemAmount.amount);
}
//Craft
void OnItemCraftFinished(ItemCraftTask task, Item item, ItemCrafter crafter)
{
var player = crafter.owner;
if (player != null)
if (hasQuests(player.userID) && isQuestItem(player.userID, item.info.shortname, QuestType.Craft))
ProcessProgress(player, QuestType.Craft, item.info.shortname, item.amount);
}
//Loot
void OnItemAddedToContainer(ItemContainer container, Item item)
{
if (Looters.ContainsKey(item.uid))
{
if (container.playerOwner != null)
{
if (Looters[item.uid] != container.playerOwner.userID)
{
if (hasQuests(container.playerOwner.userID) && isQuestItem(container.playerOwner.userID, item.info.shortname, QuestType.Loot))
{
ProcessProgress(container.playerOwner, QuestType.Loot, item.info.shortname, item.amount);
Looters.Remove(item.uid);
}
}
}
}
else if (container.playerOwner != null) Looters.Add(item.uid, container.playerOwner.userID);
}
void OnItemRemovedFromContainer(ItemContainer container, Item item)
{
ulong id = 0U;
if (container.entityOwner != null)
id = container.entityOwner.OwnerID;
else if (container.playerOwner != null)
id = container.playerOwner.userID;
if (!Looters.ContainsKey(item.uid))
Looters.Add(item.uid, id);
}
// Delivery and Vendors
void OnUseNPC(BasePlayer npc, BasePlayer player)
{
if (player == null || npc == null) return;
CheckPlayerEntry(player);
var npcID = npc.UserIDString;
if (vendors.QuestVendors.ContainsKey(npcID) && configData.UseNPCVendors)
{
CreateMenu(player);
return;
}
if (vendors.DeliveryVendors.ContainsKey(npcID))
{
if (hasQuests(player.userID) && PlayerProgress[player.userID].CurrentDelivery.TargetID == npc.UserIDString)
AcceptDelivery(player, npcID, 1);
if (hasQuests(player.userID) && string.IsNullOrEmpty(PlayerProgress[player.userID].CurrentDelivery.TargetID))
AcceptDelivery(player, npcID);
else SendMSG(player, LA("delInprog", player.UserIDString), LA("Quests", player.UserIDString));
}
}
#endregion
object OnPlayerChat(BasePlayer player, string message)
{
if (BetterChat) return null;
if (player == null) return null;
if (ActiveEditors.ContainsKey(player.userID) || ActiveCreations.ContainsKey(player.userID) || AddVendor.ContainsKey(player.userID))
{
QuestChat(player, message.Split(' '));
return false;
}
return null;
}
object OnBetterChat(Dictionary<string, object> dict)
{
var player = (dict["Player"] as IPlayer).Object as BasePlayer;
if (player == null) return null;
string message = dict["Message"].ToString();
if (ActiveEditors.ContainsKey(player.userID) || ActiveCreations.ContainsKey(player.userID) || AddVendor.ContainsKey(player.userID))
{
QuestChat(player, message.Split(' '));
dict["CancelOption"] = 2;
return dict;
}
return dict;
}
void QuestChat(BasePlayer player, string[] arg)
{
bool isEditing = false;
bool isCreating = false;
QuestCreator Creator = new QuestCreator();
QuestEntry Quest = new QuestEntry();
// remove all html codes from the message (needed for colored chat messages)
System.Text.RegularExpressions.Regex rmHTML = new System.Text.RegularExpressions.Regex("<[^>]*>");
var args = rmHTML.Replace(string.Join(" ", arg), "");
var argsForNumbers = rmHTML.Replace(arg[0], "");
if (ActiveEditors.ContainsKey(player.userID))
{
isEditing = true;
Creator = ActiveEditors[player.userID];
Quest = Creator.entry;
}
else if (ActiveCreations.ContainsKey(player.userID))
{
isCreating = true;
Creator = ActiveCreations[player.userID];
Quest = Creator.entry;
}
if (AddVendor.ContainsKey(player.userID) && string.Join(" ", arg).Contains("exit"))
{
ExitQuest(player, true);
return;
}
if (!isEditing && !isCreating)
return;
if (args.Contains("exit"))
{
ExitQuest(player, isCreating);
return;
}
if (args.Contains("quest item"))
{
var item = GetItem(player);
if (item != null)
{
if (Creator.type != QuestType.Delivery)
{
Quest.Rewards.Add(item);
Creator.partNum++;
if (isCreating)
CreationHelp(player, 7);
else if (isEditing)
{
SaveRewardsEdit(player);
CreationHelp(player, 10);
}
}
else
{
Creator.deliveryInfo.Reward = item;
DeliveryHelp(player, 4);
}
}
else SendMSG(player, $"{LA("noAItem", player.UserIDString)}'quest item'", LA("QC", player.UserIDString));
return;
}
switch (Creator.partNum)
{
case 0:
foreach (var type in questData.Quest)
{
if (type.Value.ContainsKey(args))
{
SendMSG(player, LA("nameExists", player.UserIDString), LA("QC", player.UserIDString));
return;
}
}
Quest.QuestName = args;
SendMSG(player, args, "Name:");
Creator.partNum++;
if (isCreating)
CreationHelp(player, 1);
else CreationHelp(player, 6);
return;
case 2:
{
int amount;
if (!int.TryParse(argsForNumbers, out amount))
{
SendMSG(player, LA("objAmount", player.UserIDString), LA("QC", player.UserIDString));
return;
}
Quest.AmountRequired = amount;
SendMSG(player, argsForNumbers, LA("OA", player.UserIDString));
Creator.partNum++;
if (isCreating)
CreationHelp(player, 3);
else CreationHelp(player, 6);
}
return;
case 3:
{
if (Creator.type == QuestType.Delivery)
{
Creator.deliveryInfo.Description = args;
SendMSG(player, args, LA("Desc", player.UserIDString));
DeliveryHelp(player, 6);
return;
}
Quest.Description = args;
SendMSG(player, args, LA("Desc", player.UserIDString));
Creator.partNum++;
if (isCreating)
CreationHelp(player, 4);
else CreationHelp(player, 6);
}
return;
case 5:
{
if (Creator.type == QuestType.Delivery)
{
float amount;
if (!float.TryParse(argsForNumbers, out amount))
{
SendMSG(player, LA("noRM", player.UserIDString), LA("QC", player.UserIDString));
return;
}
Creator.deliveryInfo.Multiplier = amount;
SendMSG(player, argsForNumbers, LA("RM", player.UserIDString));
Creator.partNum++;
DeliveryHelp(player, 5);
}
else
{
int amount;
if (!int.TryParse(argsForNumbers, out amount))
{
SendMSG(player, LA("noRA", player.UserIDString), LA("QC", player.UserIDString));
return;
}
Creator.item.Amount = amount;
Quest.Rewards.Add(Creator.item);
Creator.item = new RewardItem();
SendMSG(player, argsForNumbers, LA("RA", player.UserIDString));
Creator.partNum++;
if (isCreating)
CreationHelp(player, 7);
else if (isEditing)
{
SaveRewardsEdit(player);
}
}
return;
}
case 6:
{
int amount;
if (!int.TryParse(argsForNumbers, out amount))
{
SendMSG(player, LA("noCD", player.UserIDString), LA("QC", player.UserIDString));
return;
}
Creator.entry.Cooldown = amount;
SendMSG(player, argsForNumbers, LA("CD1", player.UserIDString));
CreationHelp(player, 6);
}
return;
default:
break;
}
}
#endregion
#region External Calls
private bool isPlaying(BasePlayer player)
{
if (EventManager)
{
var inEvent = EventManager?.Call("isPlaying", player);
if (inEvent is bool && (bool)inEvent)
return true;
}
return false;
}
private void CloseMap(BasePlayer player)
{
if (LustyMap)
{
LustyMap.Call("DisableMaps", player);
}
}
private void OpenMap(BasePlayer player)
{
if (LustyMap)
{
LustyMap.Call("EnableMaps", player);
}
}
private void AddMapMarker(float x, float z, string name, string icon = "special", float r = 0)
{
if (LustyMap)
LustyMap.Call("AddMarker", x, z, name, icon);
}
private void RemoveMapMarker(string name)
{
if (LustyMap)
LustyMap.Call("RemoveMarker", name);
}
private object CanTeleport(BasePlayer player)
{
if (!PlayerProgress.ContainsKey(player.userID)) return null;
if (!string.IsNullOrEmpty(PlayerProgress[player.userID].CurrentDelivery.TargetID))
{
return LA("NoTP", player.UserIDString);
}
else
return null;
}
#endregion
#region Objective Lists
private void FillObjectiveList()
{
AllObjectives.Add(QuestType.Loot, new List<string>());
AllObjectives.Add(QuestType.Craft, new List<string>());
AllObjectives.Add(QuestType.Kill, new List<string>());
AllObjectives.Add(QuestType.Gather, new List<string>());
AllObjectives.Add(QuestType.Delivery, new List<string>());
GetAllCraftables();
GetAllItems();
GetAllKillables();
GetAllResources();
foreach (var category in AllObjectives)
category.Value.Sort();
if (itemNames.DisplayNames == null || itemNames.DisplayNames.Count < 1)
{
foreach (var item in ItemDefs)
{
if (!DisplayNames.ContainsKey(item.Key))
DisplayNames.Add(item.Key, item.Value.displayName.translated);
}
SaveDisplayNames();
}
else DisplayNames = itemNames.DisplayNames;
}
private void GetAllItems()
{
foreach (var item in ItemManager.itemList)
AllObjectives[QuestType.Loot].Add(item.shortname);
}
private void GetAllCraftables()
{
foreach (var bp in ItemManager.bpList)
if (bp.userCraftable)
AllObjectives[QuestType.Craft].Add(bp.targetItem.shortname);
}
private void GetAllResources()
{
AllObjectives[QuestType.Gather] = new List<string>
{
"wood",
"stones",
"metal.ore",
"hq.metal.ore",
"sulfur.ore",
"cloth",
"bone.fragments",
"crude.oil",
"fat.animal",
"leather",
"skull.wolf",
"skull.human",
"chicken.raw",
"mushroom",
"meat.boar",
"bearmeat",
"humanmeat.raw",
"wolfmeat.raw"
};
}
private void GetAllKillables()
{
AllObjectives[QuestType.Kill] = new List<string>
{
"bear",
"boar",
"bradleyapc",
"chicken",
"horse",
"stag",
"wolf",
"autoturret_deployed",
"patrolhelicopter",
"player",
"scientist",
"murderer",
"tunneldweller",
"underwaterdweller",
"scarecrow",
"simpleshark"
};
DisplayNames.Add("bear", "Bear");
DisplayNames.Add("boar", "Boar");
DisplayNames.Add("bradleyapc", "BradleyAPC");
DisplayNames.Add("chicken", "Chicken");
DisplayNames.Add("horse", "Horse");
DisplayNames.Add("stag", "Stag");
DisplayNames.Add("wolf", "Wolf");
DisplayNames.Add("autoturret_deployed", "Auto-Turret");
DisplayNames.Add("patrolhelicopter", "Helicopter");
DisplayNames.Add("player", "Player");
DisplayNames.Add("scientist", "Scientist");
DisplayNames.Add("murderer", "Murderer");
DisplayNames.Add("tunneldweller", "Tunneldweller");
DisplayNames.Add("underwaterdweller", "Underwater Dweller");
DisplayNames.Add("scarecrow", "Scarecrow");
DisplayNames.Add("simpleshark", "Shark");
}
#endregion
#region Functions
private bool isAdmin(BasePlayer player)
{
if (configData.UseOxidePermissions == true && permission.UserHasPermission(player.UserIDString, permission_manage) || player.IsAdmin && configData.UsePlayerIsAdmin == true) return true;
else return false;
}
void AddMapIcons()
{
int deliveryCount = 1;
foreach (var vendor in vendors.DeliveryVendors)
{
AddMapMarker(vendor.Value.Info.x, vendor.Value.Info.z, vendor.Value.Info.Name, $"{configData.LustyMapIntegration.Icon_Delivery}_{deliveryCount}.png");
++deliveryCount;
}
foreach (var vendor in vendors.QuestVendors)
{
AddMapMarker(vendor.Value.x, vendor.Value.z, vendor.Value.Name, $"{configData.LustyMapIntegration.Icon_Vendor}.png");
}
}
private void ProcessProgress(BasePlayer player, QuestType questType, string type, int amount = 0)
{
if (string.IsNullOrEmpty(type)) return;
var data = PlayerProgress[player.userID];
if (data.RequiredItems.Count > 0)
{
foreach (var entry in data.Quests.Where(x => x.Value.Status == QuestStatus.Pending))
{
var quest = GetQuest(entry.Key);
if (quest != null)
{
if (type == quest.Objective)
{
if (amount > 0)
{
var amountRequired = quest.AmountRequired - entry.Value.AmountCollected;
if (amount > amountRequired)
amount = amountRequired;
entry.Value.AmountCollected += amount;
if (quest.ItemDeduction)
TakeQuestItem(player, type, amount);
}
else entry.Value.AmountCollected++;
if (entry.Value.AmountCollected >= quest.AmountRequired)
CompleteQuest(player, entry.Key);
return;
}
}
}
}
}
private void TakeQuestItem(BasePlayer player, string item, int amount)
{
if (ItemDefs.ContainsKey(item))
{
var itemDef = ItemDefs[item];
NextTick(() => player.inventory.Take(null, itemDef.itemid, amount));
}
else PrintWarning($"Unable to find definition for: {item}.");
}
private void CompleteQuest(BasePlayer player, string questName)
{
var data = PlayerProgress[player.userID].Quests[questName];
var items = PlayerProgress[player.userID].RequiredItems;
var quest = GetQuest(questName);
if (quest != null)
{
data.Status = QuestStatus.Completed;
data.ResetTime = GrabCurrentTime() + (quest.Cooldown * 60);
for (int i = 0; i < items.Count; i++)
{
if (items[i].ShortName == quest.Objective && items[i].Type == data.Type)
{
items.Remove(items[i]);
break;
}
}
SendMSG(player, "", $"{LA("qComple", player.UserIDString)} {questName}. {LA("claRew", player.UserIDString)}");
PlayerChallenges?.Call("CompletedQuest", player);
}
}
private ItemDefinition FindItemDefinition(string shortname)
{
ItemDefinition itemDefinition;
return ItemDefs.TryGetValue(shortname, out itemDefinition) ? itemDefinition : null;
}
private string GetRewardString(List<RewardItem> entry)
{
var rewards = "";
int i = 1;
foreach (var item in entry)
{
rewards = rewards + $"{(int)item.Amount}x {item.DisplayName}";
if (i < entry.Count)
rewards = rewards + ", ";
i++;
}
return rewards;
}
private bool GiveReward(BasePlayer player, List<RewardItem> rewards)
{
foreach (var reward in rewards)
{
if (reward.isCoins && Economics)
{
Economics.Call("Deposit", player.UserIDString, (double)reward.Amount);
}
else if (reward.isRP && ServerRewards)
{
ServerRewards.Call("AddPoints", player.userID, (int)reward.Amount);
}
else if (reward.isHuntXP)
{
HuntRPG?.Call("GiveEXP", player, (int)reward.Amount);
}
else
{
if (string.IsNullOrEmpty(reward.ShortName)) return true;
var definition = FindItemDefinition(reward.ShortName);
if (definition != null)
{
// Use object pooling for retrieving player's inventory items
List<Item> itemList = Pool.Get<List<Item>>();
player.inventory.GetAllItems(itemList);
// Check if the player's inventory has enough space
if (itemList.Count >= 30)
{
Pool.FreeUnmanaged<Item>(ref itemList);
return false;
}
// Create the item and add it to the player's inventory
var item = ItemManager.Create(definition, (int)reward.Amount, reward.Skin);
if (item != null)
{
player.inventory.GiveItem(item, player.inventory.containerMain);
}
// Free the pooled list after usage
Pool.FreeUnmanaged<Item>(ref itemList);
}
else
{
PrintWarning($"Quests: Error building item {reward.ShortName} for {player.displayName}");
}
}
}
return true;
}
private void ReturnItems(BasePlayer player, string itemname, int amount)
{
if (amount > 0)
{
var definition = FindItemDefinition(itemname);
if (definition != null)
{
var item = ItemManager.Create(definition, amount);
if (item != null)
{
player.inventory.GiveItem(item);
PopupMessage(player, $"{LA("qCancel", player.UserIDString)} {item.amount}x {item.info.displayName.translated} {LA("rewRet", player.UserIDString)}");
}
}
}
}
private RewardItem GetItem(BasePlayer player)
{
Item item = player.GetActiveItem();
if (item == null) return null;
var newItem = new RewardItem
{
Amount = item.amount,
DisplayName = DisplayNames[item.info.shortname],
ID = item.info.itemid,
ShortName = item.info.shortname,
Skin = item.skin
};
return newItem;
}
private bool hasQuests(ulong player)
{
try
{
if (player.IsSteamId() && PlayerProgress.ContainsKey(player))
{
return true;
}
return false;
}
catch
{
Puts($"Error checking quests for {player}");
return false;
}
}
private bool isQuestItem(ulong player, string name, QuestType type)
{
var data = PlayerProgress[player].RequiredItems;
for (int i = 0; i < data.Count; i++)
{
if (data[i].ShortName == name && data[i].Type == type)
return true;
}
return false;
}
private void CheckPlayerEntry(BasePlayer player)
{
if (!PlayerProgress.ContainsKey(player.userID))
PlayerProgress.Add(player.userID, new PlayerQuestData());
}
private object GetQuestType(string name)
{
foreach (var entry in Quest)
if (entry.Value.ContainsKey(name))
return entry.Key;
return null;
}
private QuestEntry GetQuest(string name)
{
var type = GetQuestType(name);
if (type != null)
{
foreach (var entry in questData.Quest[(QuestType)type])
{
if (entry.Key == name)
return entry.Value;
}
}
PrintWarning($"Error retrieving quest info for: {name}");
return null;
}
private void SaveQuest(BasePlayer player, bool isCreating)
{
QuestCreator Creator;
QuestEntry Quest;
if (isCreating)
Creator = ActiveCreations[player.userID];
else Creator = ActiveEditors[player.userID];
Quest = Creator.entry;
if (isCreating)
{
if (Creator.type == QuestType.Delivery)
{
var npc = BasePlayer.FindByID(ulong.Parse(Creator.deliveryInfo.Info.ID));
if (npc != null)
{
npc.displayName = Creator.deliveryInfo.Info.Name;
npc.SendNetworkUpdateImmediate();
}
vendors.DeliveryVendors.Add(Creator.deliveryInfo.Info.ID, Creator.deliveryInfo);
AddMapMarker(Creator.deliveryInfo.Info.x, Creator.deliveryInfo.Info.z, Creator.deliveryInfo.Info.Name, $"{configData.LustyMapIntegration.Icon_Delivery}_{vendors.DeliveryVendors.Count}.png");
AddVendor.Remove(player.userID);
SaveVendorData();
DestroyUI(player);
if (vendors.DeliveryVendors.Count < 2)
PopupMessage(player, LA("minDV", player.UserIDString));
SendMSG(player, LA("DVSucc", player.UserIDString), LA("QC", player.UserIDString));
OpenMap(player);
return;
}
else questData.Quest[Creator.type].Add(Quest.QuestName, Quest);
ActiveCreations.Remove(player.userID);
}
else
{
questData.Quest[Creator.type].Remove(Creator.oldEntry);
questData.Quest[Creator.type].Add(Quest.QuestName, Quest);
ActiveEditors.Remove(player.userID);
}
DestroyUI(player);
SaveQuestData();
SendMSG(player, $"{LA("saveQ", player.UserIDString)} {Quest.QuestName}", LA("QC", player.UserIDString));
}
private void SaveRewardsEdit(BasePlayer player)
{
QuestCreator Creator = ActiveEditors[player.userID];
QuestEntry Quest = Creator.entry;
questData.Quest[Creator.type].Remove(Creator.entry.QuestName);
questData.Quest[Creator.type].Add(Quest.QuestName, Quest);
DestroyUI(player);
SaveQuestData();
CreationHelp(player, 10);
SendMSG(player, $"{LA("saveQ", player.UserIDString)} {Quest.QuestName}", LA("QC", player.UserIDString));
}
private void ExitQuest(BasePlayer player, bool isCreating)
{
if (isCreating)
ActiveCreations.Remove(player.userID);
else ActiveEditors.Remove(player.userID);
SendMSG(player, LA("QCCancel", player.UserIDString), LA("QC", player.UserIDString));
DestroyUI(player);
}
private void RemoveQuest(string questName)
{
var Quest = GetQuest(questName);
if (Quest == null) return;
var Type = (QuestType)GetQuestType(questName);
questData.Quest[Type].Remove(questName);
foreach (var player in PlayerProgress)
{
if (player.Value.Quests.ContainsKey(questName))
player.Value.Quests.Remove(questName);
}
if (vendors.DeliveryVendors.ContainsKey(Quest.Objective))
vendors.DeliveryVendors.Remove(Quest.Objective);
if (vendors.QuestVendors.ContainsKey(Quest.Objective))
vendors.QuestVendors.Remove(Quest.Objective);
SaveQuestData();
SaveVendorData();
}
private ulong GetLastAttacker(NetworkableId id)
{
int hits = 0;
ulong majorityPlayer = 0U;
if (HeliAttackers.ContainsKey(id))
{
foreach (var score in HeliAttackers[id])
{
if (score.Value > hits)
majorityPlayer = score.Key;
}
}
return majorityPlayer;
}
private string GetTypeDescription(QuestType type)
{
switch (type)
{
case QuestType.Kill:
return LA("KillOBJ");
case QuestType.Craft:
return LA("CraftOBJ");
case QuestType.Gather:
return LA("GatherOBJ");
case QuestType.Loot:
return LA("LootOBJ");
case QuestType.Delivery:
return LA("DelvOBJ");
}
return "";
}
private QuestType ConvertStringToType(string type)
{
switch (type)
{
case "gather":
case "Gather":
return QuestType.Gather;
case "loot":
case "Loot":
return QuestType.Loot;
case "craft":
case "Craft":
return QuestType.Craft;
case "delivery":
case "Delivery":
return QuestType.Delivery;
default:
return QuestType.Kill;
}
}
private string isNPCRegistered(string ID)
{
if (vendors.QuestVendors.ContainsKey(ID)) return LA("aQVReg");
if (vendors.DeliveryVendors.ContainsKey(ID)) return LA("aDVReg");
return null;
}
static double GrabCurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
private BasePlayer FindEntity(BasePlayer player)
{
var currentRot = Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward;
var rayResult = Ray(player, currentRot);
if (rayResult is BasePlayer)
{
var ent = rayResult as BasePlayer;
return ent;
}
return null;
}
private object Ray(BasePlayer player, Vector3 Aim)
{
var hits = Physics.RaycastAll(player.transform.position + new Vector3(0f, 1.5f, 0f), Aim);
float distance = 50f;
object target = null;
foreach (var hit in hits)
{
if (hit.collider.GetComponentInParent<BaseEntity>() != null)
{
if (hit.distance < distance)
{
distance = hit.distance;
target = hit.collider.GetComponentInParent<BaseEntity>();
}
}
}
return target;
}
private void SetVendorName()
{
foreach (var npc in vendors.DeliveryVendors)
{
var player = BasePlayer.FindByID(ulong.Parse(npc.Key));
if (player != null)
{
player.displayName = npc.Value.Info.Name;
}
}
foreach (var npc in vendors.QuestVendors)
{
var player = BasePlayer.FindByID(ulong.Parse(npc.Key));
if (player != null)
{
player.displayName = npc.Value.Name;
}
}
}
private void RemoveVendor(BasePlayer player, string ID, bool isVendor)
{
if (isVendor)
{
RemoveMapMarker(vendors.QuestVendors[ID].Name);
vendors.QuestVendors.Remove(ID);
int i = 1;
foreach (var npc in vendors.QuestVendors)
{
RemoveMapMarker(npc.Value.Name);
AddMapMarker(npc.Value.x, npc.Value.z, npc.Value.Name, $"{configData.LustyMapIntegration.Icon_Vendor}.png");
i++;
}
}
else
{
RemoveMapMarker(vendors.DeliveryVendors[ID].Info.Name);
vendors.DeliveryVendors.Remove(ID);
int i = 1;
foreach (var npc in vendors.DeliveryVendors)
{
RemoveMapMarker(npc.Value.Info.Name);
AddMapMarker(npc.Value.Info.x, npc.Value.Info.z, npc.Value.Info.Name, $"{configData.LustyMapIntegration.Icon_Delivery}_{i}.png");
i++;
}
foreach (var user in PlayerProgress)
{
if (user.Value.Quests.ContainsKey(ID))
user.Value.Quests.Remove(ID);
}
}
DeleteNPCMenu(player);
PopupMessage(player, $"You have successfully removed the npc with ID: {ID}");
SaveVendorData();
}
private string GetRandomNPC(string ID)
{
List<string> npcIDs = vendors.DeliveryVendors.Keys.ToList();
List<string> withoutSelected = npcIDs;
if (withoutSelected.Contains(ID))
withoutSelected.Remove(ID);
var randNum = UnityEngine.Random.Range(0, withoutSelected.Count - 1);
return withoutSelected[randNum];
}
private string LA(string key, string userID = null) => lang.GetMessage(key, this, userID);
#endregion
#region UI
private void CreateMenu(BasePlayer player)
{
CloseMap(player);
var MenuElement = QUI.CreateElementContainer(UIMain, QUI.Color(configData.Colors.Background_Dark.Color, configData.Colors.Background_Dark.Alpha), "0 0", "0.12 1");
QUI.CreatePanel(ref MenuElement, UIMain, QUI.Color(configData.Colors.Background_Light.Color, configData.Colors.Background_Light.Alpha), "0.05 0.01", "0.95 0.99", true);
QUI.CreateLabel(ref MenuElement, UIMain, "", $"{textPrimary}Quests</color>", 30, "0.05 0.9", "0.95 1");
int i = 0;
CreateMenuButton(ref MenuElement, UIMain, LA("Kill", player.UserIDString), "QUI_ChangeElement kill", i); i++;
CreateMenuButton(ref MenuElement, UIMain, LA("Gather", player.UserIDString), "QUI_ChangeElement gather", i); i++;
CreateMenuButton(ref MenuElement, UIMain, LA("Loot", player.UserIDString), "QUI_ChangeElement loot", i); i++;
CreateMenuButton(ref MenuElement, UIMain, LA("Craft", player.UserIDString), "QUI_ChangeElement craft", i); i++;
i++;
if (HumanNPC)
CreateMenuButton(ref MenuElement, UIMain, LA("Delivery", player.UserIDString), "QUI_ChangeElement delivery", i); i++;
CreateMenuButton(ref MenuElement, UIMain, LA("Your Quests", player.UserIDString), "QUI_ChangeElement personal", i); i++;
if (isAdmin(player)) QUI.CreateButton(ref MenuElement, UIMain, QUI.Color(configData.Colors.Button_Accept.Color, configData.Colors.Button_Accept.Alpha), LA("Create Quest", player.UserIDString), 18, "0.1 0.16", "0.9 0.215", "QUI_ChangeElement creation");
QUI.CreateButton(ref MenuElement, UIMain, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), LA("Close", player.UserIDString), 18, "0.1 0.03", "0.9 0.085", "QUI_DestroyAll");
CuiHelper.AddUi(player, MenuElement);
}
private void CreateEmptyMenu(BasePlayer player)
{
CloseMap(player);
var MenuElement = QUI.CreateElementContainer(UIMain, QUI.Color(configData.Colors.Background_Dark.Color, configData.Colors.Background_Dark.Alpha), "0 0", "0.12 1");
QUI.CreatePanel(ref MenuElement, UIMain, QUI.Color(configData.Colors.Background_Light.Color, configData.Colors.Background_Light.Alpha), "0.05 0.01", "0.95 0.99", true);
QUI.CreateLabel(ref MenuElement, UIMain, "", $"{textPrimary}Quests</color>", 30, "0.05 0.9", "0.95 1");
CreateMenuButton(ref MenuElement, UIMain, LA("Your Quests", player.UserIDString), "QUI_ChangeElement personal", 4);
QUI.CreateButton(ref MenuElement, UIMain, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), LA("Close", player.UserIDString), 18, "0.1 0.03", "0.9 0.085", "QUI_DestroyAll");
CuiHelper.AddUi(player, MenuElement);
}
private void CreateMenuButton(ref CuiElementContainer container, string panelName, string buttonname, string command, int number)
{
Vector2 dimensions = new Vector2(0.8f, 0.055f);
Vector2 origin = new Vector2(0.1f, 0.75f);
Vector2 offset = new Vector2(0, (0.01f + dimensions.y) * number);
Vector2 posMin = origin - offset;
Vector2 posMax = posMin + dimensions;
QUI.CreateButton(ref container, panelName, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), buttonname, 18, $"{posMin.x} {posMin.y}", $"{posMax.x} {posMax.y}", command);
}
private void ListElement(BasePlayer player, QuestType type, int page = 0)
{
DestroyEntries(player);
var Main = QUI.CreateElementContainer(UIPanel, QUI.Color(configData.Colors.Background_Dark.Color, configData.Colors.Background_Dark.Alpha), "0.12 0", "1 1");
QUI.CreatePanel(ref Main, UIPanel, QUI.Color(configData.Colors.Background_Light.Color, configData.Colors.Background_Light.Alpha), "0.01 0.01", "0.99 0.99", true);
QUI.CreateLabel(ref Main, UIPanel, "", GetTypeDescription(type), 16, "0.1 0.93", "0.9 0.99");
QUI.CreateLabel(ref Main, UIPanel, "1 1 1 0.015", type.ToString().ToUpper(), 200, "0.01 0.01", "0.99 0.99");
var quests = Quest[type];
if (quests.Count > 16)
{
var maxpages = (quests.Count - 1) / 16 + 1;
if (page < maxpages - 1)
QUI.CreateButton(ref Main, UIPanel, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), LA("Next", player.UserIDString), 16, "0.86 0.94", "0.97 0.98", $"QUI_ChangeElement listpage {type} {page + 1}");
if (page > 0)
QUI.CreateButton(ref Main, UIPanel, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), LA("Back", player.UserIDString), 16, "0.03 0.94", "0.14 0.98", $"QUI_ChangeElement listpage {type} {page - 1}");
}
int maxentries = (16 * (page + 1));
if (maxentries > quests.Count)
maxentries = quests.Count;
int rewardcount = 16 * page;
List<string> questNames = new List<string>();
foreach (var entry in Quest[type])
questNames.Add(entry.Key);
if (quests.Count == 0)
QUI.CreateLabel(ref Main, UIPanel, "", $"{textPrimary}{LA("noQ", player.UserIDString)} {type.ToString().ToLower()} {LA("quests", player.UserIDString)} </color>", 24, "0 0.82", "1 0.9");
CuiHelper.AddUi(player, Main);
int i = 0;
for (int n = rewardcount; n < maxentries; n++)
{
CreateQuestEntry(player, quests[questNames[n]], i);
i++;
}
}
private void CreateQuestEntry(BasePlayer player, QuestEntry entry, int num)
{
Vector2 posMin = CalcQuestPos(num);
Vector2 dimensions = new Vector2(0.21f, 0.22f);
Vector2 posMax = posMin + dimensions;
var panelName = UIEntry + num;
AddUIString(player, panelName);
var questEntry = QUI.CreateElementContainer(panelName, "0 0 0 0", $"{posMin.x} {posMin.y}", $"{posMax.x} {posMax.y}");
QUI.CreatePanel(ref questEntry, panelName, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), $"0 0", $"1 1");
string buttonCommand = "";
string buttonText = "";
string buttonColor = "";
QuestStatus status = QuestStatus.Open;
var prog = PlayerProgress[player.userID].Quests;
if (prog.ContainsKey(entry.QuestName))
{
status = prog[entry.QuestName].Status;
switch (prog[entry.QuestName].Status)
{
case QuestStatus.Pending:
buttonColor = QUI.Color(configData.Colors.Button_Pending.Color, configData.Colors.Button_Pending.Alpha);
buttonText = LA("Pending", player.UserIDString);
break;
case QuestStatus.Completed:
buttonColor = QUI.Color(configData.Colors.Button_Completed.Color, configData.Colors.Button_Completed.Alpha);
buttonText = LA("Completed", player.UserIDString);
break;
}
}
else
{
buttonColor = QUI.Color(configData.Colors.Button_Accept.Color, configData.Colors.Button_Accept.Alpha);
buttonText = LA("Accept Quest", player.UserIDString);
buttonCommand = $"QUI_AcceptQuest {entry.QuestName}";
}
if (configData.PlayerMaxQuests != 0 && !permission.UserHasPermission(player.UserIDString, "quests.bypassQuestsLimit") && playerData.PlayerProgress[player.userID].Quests.Count() >= configData.PlayerMaxQuests)
{
QUI.CreateButton(ref questEntry, panelName, QUI.Color(configData.Colors.Button_Cancel.Color, configData.Colors.Button_Cancel.Alpha), "Quests limit reached", 11, $"0.60 0.83", $"0.98 0.97", "");
}
else
{
QUI.CreateButton(ref questEntry, panelName, buttonColor, buttonText, 14, $"0.60 0.83", $"0.98 0.97", buttonCommand);
}
string rewards = GetRewardString(entry.Rewards);
string questInfo = $"{textPrimary}{LA("Status:", player.UserIDString)}</color> {status}";
questInfo = questInfo + $"\n{textPrimary}{LA("Desc", player.UserIDString)} </color>{textSecondary}{entry.Description}</color>";
questInfo = questInfo + $"\n{textPrimary}{LA("Objective:", player.UserIDString)} </color>{textSecondary}{entry.ObjectiveName}</color>";
questInfo = questInfo + $"\n{textPrimary}{LA("Amount Required:", player.UserIDString)} </color>{textSecondary}{entry.AmountRequired}</color>";
questInfo = questInfo + $"\n{textPrimary}{LA("Reward:", player.UserIDString)} </color>{textSecondary}{rewards}</color>";
QUI.CreateLabel(ref questEntry, panelName, "", $"{entry.QuestName}", 16, $"0.02 0.8", "0.72 0.95", TextAnchor.MiddleLeft);
QUI.CreateLabel(ref questEntry, panelName, buttonColor, questInfo, 14, $"0.02 0.01", "0.98 0.78", TextAnchor.UpperLeft);
if (isAdmin(player))
{
QUI.CreateButton(ref questEntry, panelName, QUI.Color(configData.Colors.Button_Completed.Color, configData.Colors.Button_Completed.Alpha), LA("Edit Quest", player.UserIDString), 10, "0.60 0.70", "0.77 0.80", $"QUI_EditQuest {entry.QuestName}");
QUI.CreateButton(ref questEntry, panelName, QUI.Color(configData.Colors.Button_Cancel.Color, configData.Colors.Button_Cancel.Alpha), LA("Delete Quest", player.UserIDString), 10, "0.78 0.70", "0.98 0.80", $"QUI_ConfirmDelete {entry.QuestName}");
}
CuiHelper.AddUi(player, questEntry);
}
private void PlayerStats(BasePlayer player, int page = 0)
{
DestroyEntries(player);
var Main = QUI.CreateElementContainer(UIPanel, QUI.Color(configData.Colors.Background_Dark.Color, configData.Colors.Background_Dark.Alpha), "0.12 0", "1 1");
QUI.CreatePanel(ref Main, UIPanel, QUI.Color(configData.Colors.Background_Light.Color, configData.Colors.Background_Light.Alpha), "0.01 0.01", "0.99 0.99", true);
QUI.CreateLabel(ref Main, UIPanel, "", LA("yqDesc", player.UserIDString), 16, "0.1 0.93", "0.9 0.99");
QUI.CreateLabel(ref Main, UIPanel, "1 1 1 0.015", LA("STATS", player.UserIDString), 200, "0.01 0.01", "0.99 0.99");
var stats = PlayerProgress[player.userID];
if (stats.Quests.Count > 16)
{
var maxpages = (stats.Quests.Count - 1) / 16 + 1;
if (page < maxpages - 1)
QUI.CreateButton(ref Main, UIPanel, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), LA("Next", player.UserIDString), 16, "0.86 0.94", "0.97 0.98", $"QUI_ChangeElement statspage {page + 1}");
if (page > 0)
QUI.CreateButton(ref Main, UIPanel, QUI.Color(configData.Colors.Button_Standard.Color, configData.Colors.Button_Standard.Alpha), LA("Back", player.UserIDString), 16, "0.03 0.94", "0.14 0.098", $"QUI_ChangeElement statspage {page - 1}");
}
int maxentries = (16 * (page + 1));
if (maxentries > stats.Quests.Count)
maxentries = stats.Quests.Count;
int rewardcount = 16 * page;
List<string> questNames = new List<string>();
foreach (var entry in stats.Quests)
questNames.Add(entry.Key);
if (stats.Quests.Count == 0)
QUI.CreateLabel(ref Main, UIPanel, "", $"{textPrimary}{LA("noQDSaved", player.UserIDString)}</color>", 24, "0 0.82", "1 0.9");
CuiHelper.AddUi(player, Main);
int i = 0;
for (int n = rewardcount; n < maxentries; n++)
{
var Quest = GetQuest(questNames[n]);
if (Quest == null) continue;
CreateStatEntry(player, Quest, i);
i++;
}
}
private void CreateStatEntry(BasePlayer player, QuestEntry entry, int num)
{
Vector2 posMin = CalcQuestPos(num);
Vector2 dimensions = new Vector2(0.21f, 0.22f);
Vector2 posMax = posMin + dimensions;
var panelName = UIEntry + num;
AddUIString(player, panelName);
var questEntry = QUI.CreateElementContainer(panelName, "0 0 0 0", $"{posMin.x} {posMin.y}", $"{posMax.x} {posMax.y}");
QUI.CreatePanel(ref questEntry, panelN