C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
* https://github.com/DocValerian/rust-plugins
* Copyright (C) 2022 DocValerian
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.*
* You should have received a copy of the GNU General Public License
* along with this program.If not, see <http://www.gnu.org/licenses/>.*
* Questions and (limited) Support can be found in our Discord: https://discord.gg/8tkBFRjg3W
*
*/
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Linq;
using System;
using Network;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using Random = System.Random;
using System.Globalization;
using Newtonsoft.Json.Linq;
namespace Oxide.Plugins
{
[Info("ZNQuests", "DocValerian", "1.2.4")]
class ZNQuests : RustPlugin
{
static ZNQuests Plugin;
[PluginReference]
private Plugin ImageLibrary, ServerRewards, InfoAPI, ZNExperience, Clans;
const string permUse = "znquests.use";
bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
#region ConfigDataLoad
protected override void SaveConfig() => Config.WriteObject(Cfg);
protected override void LoadConfig()
{
base.LoadConfig();
try
{
Cfg = Config.ReadObject<Configuration>();
}
catch (JsonException ex)
{
Puts(ex.Message);
PrintError("Your configuration file contains a json error, shown above.Please fix this.");
return;
}
catch (Exception ex)
{
Puts(ex.Message);
LoadDefaultConfig();
}
if (Cfg == null)
{
Puts("Config is null");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void LoadDefaultConfig()
{
Cfg = new Configuration();
Puts("Loaded default configuration file");
}
static Configuration Cfg = new Configuration();
class Configuration
{
public int questAmount = 10;
public int questAmountEasy = 3;
public int questAmountNormal = 4;
public int questAmountHard = 3;
public string costItem = "bleach";
public int rerollRPCost = 20000;
public bool useClans = true;
public int clanMinMembers = 3;
public float clanQuestMemberFactor = 0.5f;
public int globalQuestClaimThreshold = 4;
public int globalRewardCap = 40000;
public int globalRewardPerContributor = 750;
}
class StoredData
{
public List<ulong> PvpAdmins = new List<ulong>();
}
StoredData storedData;
void Loaded()
{
Plugin = this;
permission.RegisterPermission(permUse, this);
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("ZNQuests");
SaveData(storedData);
nfi.NumberDecimalSeparator = ",";
nfi.NumberGroupSeparator = ".";
nfi.NumberDecimalDigits = 0;
}
private void OnServerInitialized()
{
costItemId = ItemManager.itemDictionaryByName[Cfg.costItem].itemid;
foreach (var p in BasePlayer.activePlayerList)
{
QuestManager.Get(p.userID);
}
PopulateRewardList();
ImageLibrary?.Call("ImportImageList", "xpimg", new Dictionary<string, string>() { ["rp_img"] = "http://m2v.eu/i/zn/rp1.png", ["xp_img"] = "http://m2v.eu/i/zn/xp.png" });
_gm = GlobalQuestManager.Get();
}
void Unload()
{
foreach (var player in BasePlayer.activePlayerList)
{
OnPlayerDisconnected(player);
killUI(player);
}
_gm.SaveData();
}
private static void LoadData<T>(out T data, string filename = null)
{
try
{
data = Interface.Oxide.DataFileSystem.ReadObject<T>(filename ?? "ZNQuests");
}
catch (JsonException ex)
{
Plugin.Puts("E1:" + ex.Message);
data = default(T);
}
catch (Exception ex)
{
Plugin.Puts("E2: " + ex.Message + "\n" + ex.InnerException);
data = default(T);
}
}
private static void SaveData<T>(T data, string filename = null) =>
Interface.Oxide.DataFileSystem.WriteObject(filename ?? "ZNQuests", data);
#endregion
#region Lists and Clases
private int costItemId;
private Dictionary<ulong, QuestManager> _qm = new Dictionary<ulong, QuestManager>();
private GlobalQuestManager _gm = null;
private static List<ZQuest> AvailableEasyQuests = new List<ZQuest>
{
// kill quests
new ZQuest{ type = "kill", item = "chicken", difficulty = "easy", amountGoal = 3, desc = "Hunt and kill a number of Chicken" },
new ZQuest{ type = "kill", item = "wolf", difficulty = "easy", amountGoal = 5, desc = "Hunt and kill a number of Wolfs" },
//item list kills difficulty = "easy",
new ZQuest{ type = "kill", item = "itemRoadsigns", difficulty = "easy", amountGoal = 10, desc = "Destroy a number of Roadsigns" },
new ZQuest{ type = "kill", item = "itemBarrels", difficulty = "easy", amountGoal = 20, desc = "Destroy a number of Barrels" },
new ZQuest{ type = "kill", item = "itemNPC", difficulty = "easy", amountGoal = 20,desc = "Kill a number of Scientists or Zombies (no Dwellers!)" },
new ZQuest{ type = "kill", item = "itemBear", difficulty = "easy", amountGoal = 2, desc = "Hunt and kill a number of Bears or Polarbears" },
// farm quests difficulty = "easy",
new ZQuest{ type = "farm", item = "stones", difficulty = "easy", amountGoal = 10,desc = "Farm a number of Stone nodes" },
new ZQuest{ type = "farm", item = "wood", difficulty = "easy", amountGoal = 20, desc = "Farm a number of Trees" },
new ZQuest{ type = "farm", item = "metal.ore", difficulty = "easy", amountGoal = 10, desc = "Farm a number of Metal nodes" },
new ZQuest{ type = "farm", item = "sulfur.ore", difficulty = "easy", amountGoal = 10, desc = "Farm a number of Sulfur nodes" },
// collect quests difficulty = "easy",
new ZQuest{ type = "collect", item = "stones", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Stone piles" },
new ZQuest{ type = "collect", item = "wood", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Treestumps" },
new ZQuest{ type = "collect", item = "metal.ore", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Metal piles" },
new ZQuest{ type = "collect", item = "sulfur.ore", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Sulfur piles" },
new ZQuest{ type = "collect", item = "pumpkin", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Pumpkins" },
new ZQuest{ type = "collect", item = "corn", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Corn" },
new ZQuest{ type = "collect", item = "mushroom", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Mushrooms" },
new ZQuest{ type = "collect", item = "itemBerry", difficulty = "easy", amountGoal = 10, desc = "Pick up a number of Berries" },
// catch quests difficulty = "easy",
new ZQuest{ type = "catch", item = "fish", difficulty = "easy", amountGoal = 5, desc = "Catch a number of (any) Fish" },
// travel quests difficulty = "easy",
new ZQuest{ type = "travel", item = "saddletest", difficulty = "easy", amountGoal = 500, desc = "Ride a Horse for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "miniheliseat", difficulty = "easy", amountGoal = 1000, desc = "Pilot a Minicopter for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "transporthelicopilot", difficulty = "easy", amountGoal = 1000, desc = "Co-Pilot a Scrapheli for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "smallboatdriver", difficulty = "easy", amountGoal = 1000, desc = "Captain a Boat for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "snowmobiledriverseat", difficulty = "easy", amountGoal = 1000, desc = "Drive a SnowMobile for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarinesolodriverstanding", difficulty = "easy", amountGoal = 1000, desc = "Captain a Solo Submarine for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarineduodriverseat", difficulty = "easy", amountGoal = 1000, desc = "Captain a Duo Submarine for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "modularcardriverseat", difficulty = "easy", amountGoal = 1000, desc = "Drive a Modular Car for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "itemCarPassenger", difficulty = "easy", amountGoal = 1000, desc = "Be a Modular Car passenger for total distance (mount to unmount point)" },
//modularcardriverseat submarineduodriverseat...(15:55:02) | [ZNQuests] DEBUG: dismount submarineduopassengerseat...};
private static List<ZQuest> AvailableQuests = new List<ZQuest>
{
// kill quests
new ZQuest{ type = "kill", item = "boar", difficulty = "normal", amountGoal = 10, desc = "Hunt and kill a number of Boars" },
new ZQuest{ type = "kill", item = "chicken", difficulty = "normal", amountGoal = 6, desc = "Hunt and kill a number of Chicken" },
new ZQuest{ type = "kill", item = "wolf", difficulty = "normal", amountGoal = 10, desc = "Hunt and kill a number of Wolfs" },
new ZQuest{ type = "kill", item = "stag", difficulty = "normal", amountGoal = 10, desc = "Hunt and kill a number of Stags" },
//item list kills difficulty = "normal",
new ZQuest{ type = "kill", item = "itemRoadsigns", difficulty = "normal", amountGoal = 25, desc = "Destroy a number of Roadsigns" },
new ZQuest{ type = "kill", item = "itemBarrels", difficulty = "normal", amountGoal = 50, desc = "Destroy a number of Barrels" },
new ZQuest{ type = "kill", item = "itemNPC", difficulty = "normal", amountGoal = 100,desc = "Kill a number of Scientists or Zombies (no Dwellers!)" },
new ZQuest{ type = "kill", item = "itemBear", difficulty = "normal", amountGoal = 6, desc = "Hunt and kill a number of Bears or Polarbears" },
// farm quests difficulty = "normal",
new ZQuest{ type = "farm", item = "stones", difficulty = "normal", amountGoal = 40,desc = "Farm a number of Stone nodes" },
new ZQuest{ type = "farm", item = "wood", difficulty = "normal", amountGoal = 60, desc = "Farm a number of Trees" },
new ZQuest{ type = "farm", item = "metal.ore", difficulty = "normal", amountGoal = 40, desc = "Farm a number of Metal nodes" },
new ZQuest{ type = "farm", item = "sulfur.ore", difficulty = "normal", amountGoal = 40, desc = "Farm a number of Sulfur nodes" },
// collect quests difficulty = "normal",
new ZQuest{ type = "collect", item = "stones", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Stone piles" },
new ZQuest{ type = "collect", item = "wood", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Treestumps" },
new ZQuest{ type = "collect", item = "metal.ore", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Metal piles" },
new ZQuest{ type = "collect", item = "sulfur.ore", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Sulfur piles" },
new ZQuest{ type = "collect", item = "pumpkin", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Pumpkins" },
new ZQuest{ type = "collect", item = "corn", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Corn" },
new ZQuest{ type = "collect", item = "mushroom", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Mushrooms" },
new ZQuest{ type = "collect", item = "seed.hemp", difficulty = "normal", amountGoal = 30, desc = "Pick up a number of Hemp Seeds" },
new ZQuest{ type = "collect", item = "itemBerry", difficulty = "normal", amountGoal = 40, desc = "Pick up a number of Berries" },
// catch quests difficulty = "normal",
new ZQuest{ type = "catch", item = "fish", difficulty = "normal", amountGoal = 15, desc = "Catch a number of (any) Fish" },
// travel quests difficulty = "normal",
new ZQuest{ type = "travel", item = "saddletest", difficulty = "normal", amountGoal = 1500, desc = "Ride a Horse for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "miniheliseat", difficulty = "normal", amountGoal = 5000, desc = "Pilot a Minicopter for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "minihelipassenger", difficulty = "normal", amountGoal = 4000, desc = "Be passenger in a Minicopter for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "transporthelipilot", difficulty = "normal", amountGoal = 5000, desc = "Pilot a Scrapheli for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "transporthelicopilot", difficulty = "normal", amountGoal = 4000, desc = "Co-Pilot a Scrapheli for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "smallboatdriver", difficulty = "normal", amountGoal = 2000, desc = "Captain a Boat for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "smallboatpassenger", difficulty = "normal", amountGoal = 2000, desc = "Be a Boat/RHIB passenger for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "standingdriver", difficulty = "normal", amountGoal = 2000, desc = "Captain a RHIB for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "snowmobiledriverseat", difficulty = "normal", amountGoal = 3500, desc = "Drive a SnowMobile for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "snowmobilepassengerseat tomaha", difficulty = "normal", amountGoal = 3500, desc = "Be a SnowMobile passenger for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarinesolodriverstanding", difficulty = "normal", amountGoal = 2500, desc = "Captain a Solo Submarine for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarineduodriverseat", difficulty = "normal", amountGoal = 2500, desc = "Captain a Duo Submarine for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarineduopassengerseat", difficulty = "normal", amountGoal = 2500, desc = "Be a Duo Submarine passenger for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "modularcardriverseat", difficulty = "normal", amountGoal = 3500, desc = "Drive a Modular Car for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "itemCarPassenger", difficulty = "normal", amountGoal = 3500, desc = "Be a Modular Car passenger for total distance (mount to unmount point)" },
};
private static List<ZQuest> AvailableHardQuests = new List<ZQuest>
{
// kill quests
new ZQuest{ type = "kill", item = "boar", difficulty = "hard", amountGoal = 20, desc = "Hunt and kill a number of Boars" },
new ZQuest{ type = "kill", item = "npc_tunneldweller", difficulty = "hard", amountGoal = 30, desc = "Hunt and kill a number of Tunnel Dwellers" },
new ZQuest{ type = "kill", item = "npc_underwaterdweller", difficulty = "hard", amountGoal = 20, desc = "Hunt and kill a number of Underwater Dwellers" },
new ZQuest{ type = "kill", item = "chicken", difficulty = "hard", amountGoal = 10, desc = "Hunt and kill a number of Chicken" },
new ZQuest{ type = "kill", item = "wolf", difficulty = "hard", amountGoal = 20, desc = "Hunt and kill a number of Wolfs" },
new ZQuest{ type = "kill", item = "stag", difficulty = "hard", amountGoal = 15, desc = "Hunt and kill a number of Stags" },
//item list kills
new ZQuest{ type = "kill", item = "itemRoadsigns", difficulty = "hard", amountGoal = 50, desc = "Destroy a number of Roadsigns" },
new ZQuest{ type = "kill", item = "itemBarrels", difficulty = "hard", amountGoal = 100, desc = "Destroy a number of Barrels" },
new ZQuest{ type = "kill", item = "itemNPC", difficulty = "hard", amountGoal = 250,desc = "Kill a number of Scientists or Zombies (no Dwellers!)" },
new ZQuest{ type = "kill", item = "itemBear", difficulty = "hard", amountGoal = 15, desc = "Hunt and kill a number of Bears or Polarbears" },
// farm quests
new ZQuest{ type = "farm", item = "stones", difficulty = "hard", amountGoal = 80,desc = "Farm a number of Stone nodes" },
new ZQuest{ type = "farm", item = "wood", difficulty = "hard", amountGoal = 100, desc = "Farm a number of Trees" },
new ZQuest{ type = "farm", item = "metal.ore", difficulty = "hard", amountGoal = 80, desc = "Farm a number of Metal nodes" },
new ZQuest{ type = "farm", item = "sulfur.ore", difficulty = "hard", amountGoal = 80, desc = "Farm a number of Sulfur nodes" },
// collect quests
new ZQuest{ type = "collect", item = "stones", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Stone piles" },
new ZQuest{ type = "collect", item = "wood", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Treestumps" },
new ZQuest{ type = "collect", item = "metal.ore", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Metal piles" },
new ZQuest{ type = "collect", item = "sulfur.ore", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Sulfur piles" },
new ZQuest{ type = "collect", item = "pumpkin", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Pumpkins" },
new ZQuest{ type = "collect", item = "corn", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Corn" },
new ZQuest{ type = "collect", item = "mushroom", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Mushrooms" },
new ZQuest{ type = "collect", item = "seed.hemp", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Hemp Seeds" },
new ZQuest{ type = "collect", item = "itemBerry", difficulty = "hard", amountGoal = 80, desc = "Pick up a number of Berries" },
// catch quests
new ZQuest{ type = "catch", item = "fish", difficulty = "hard", amountGoal = 30, desc = "Catch a number of (any) Fish" },
// travel quests
new ZQuest{ type = "travel", item = "saddletest", difficulty = "hard", amountGoal = 5000, desc = "Ride a Horse for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "miniheliseat", difficulty = "hard", amountGoal = 10000, desc = "Pilot a Minicopter for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "minihelipassenger", difficulty = "hard", amountGoal = 10000, desc = "Be passenger in a Minicopter for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "transporthelipilot", difficulty = "hard", amountGoal = 10000, desc = "Pilot a Scrapheli for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "transporthelicopilot", difficulty = "hard", amountGoal = 10000, desc = "Co-Pilot a Scrapheli for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "smallboatdriver", difficulty = "hard", amountGoal = 10000, desc = "Captain a Boat for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "smallboatpassenger", difficulty = "hard", amountGoal = 10000, desc = "Be a Boat/RHIB passenger for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "standingdriver", difficulty = "hard", amountGoal = 10000, desc = "Captain a RHIB for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "snowmobiledriverseat", difficulty = "hard", amountGoal = 10000, desc = "Drive a SnowMobile for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "snowmobilepassengerseat tomaha", difficulty = "hard", amountGoal = 10000, desc = "Be a SnowMobile passenger for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarinesolodriverstanding", difficulty = "hard", amountGoal = 10000, desc = "Captain a Solo Submarine for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarineduodriverseat", difficulty = "hard", amountGoal = 10000, desc = "Captain a Duo Submarine for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "submarineduopassengerseat", difficulty = "hard", amountGoal = 10000, desc = "Be a Duo Submarine passenger for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "modularcardriverseat", difficulty = "hard", amountGoal = 10000, desc = "Drive a Modular Car for total distance (mount to unmount point)" },
new ZQuest{ type = "travel", item = "itemCarPassenger", difficulty = "hard", amountGoal = 10000, desc = "Be a Modular Car passenger for total distance (mount to unmount point)" },
};
private List<Dictionary<string, int>> rewardList = new List<Dictionary<string, int>>();
public Dictionary<ulong, Vector3> playerMountPoints = new Dictionary<ulong, Vector3>();
// multi type items to kill
public Dictionary<string, string> itemList = new Dictionary<string, string>()
{
["bear"] = "itemBear",
["polarbear"] = "itemBear",
["roadsign1"] = "itemRoadsigns",
["roadsign2"] = "itemRoadsigns",
["roadsign3"] = "itemRoadsigns",
["roadsign4"] = "itemRoadsigns",
["roadsign5"] = "itemRoadsigns",
["roadsign6"] = "itemRoadsigns",
["roadsign7"] = "itemRoadsigns",
["roadsign8"] = "itemRoadsigns",
["roadsign9"] = "itemRoadsigns",
["loot_barrel_1"] = "itemBarrels",
["loot_barrel_2"] = "itemBarrels",
["loot-barrel-1"] = "itemBarrels",
["loot-barrel-2"] = "itemBarrels",
["oil_barrel"] = "itemBarrels",
["scientistnpc_heavy"] = "itemNPC",
["scientist"] = "itemNPC",
["scientistnpc_junkpile_pistol"] = "itemNPC",
["scientistnpc_full_lr300"] = "itemNPC",
["scientistnpc_full_mp5"] = "itemNPC",
["scientistnpc_full_pistol"] = "itemNPC",
["scientistnpc_full_any"] = "itemNPC",
["scientistnpc_full_shotgun"] = "itemNPC",
["scientistnpc"] = "itemNPC",
["scientistnpc_oilrig"] = "itemNPC",
["scarecrow"] = "itemNPC",
["heavyscientist"] = "itemNPC",
["heavyscientistad"] = "itemNPC",
["scientistnpc_roamtethered"] = "itemNPC",
["scientistnpc_roam"] = "itemNPC",
["scientistnpc_patrol"] = "itemNPC",
["red.berry"] = "itemBerry",
["blue.berry"] = "itemBerry",
["green.berry"] = "itemBerry",
["yellow.berry"] = "itemBerry",
["white.berry"] = "itemBerry",
["black.berry"] = "itemBerry",
["modularcarpassengerseatlesslegroomleft"] = "itemCarPassenger",
["modularcarpassengerseatlesslegroomright"] = "itemCarPassenger",
["modularcarpassengerseatleft"] = "itemCarPassenger",
["modularcarpassengerseatright"] = "itemCarPassenger",
["modularcarpassengerseatsidewayleft"] = "itemCarPassenger"
};
public class ZQuest
{
public string id() { return this.type + "_" + this.item; }
public string type { get; set; }
public string item { get; set; }
public int amountGoal { get; set; }
public int amountDone { get; set; } = 0;
public string desc { get; set; }
public bool completed { get; set; } = false;
public bool claimed { get; set; } = false;
public string difficulty { get; set; } = "normal";
public ZQuest()
{
}
public ZQuest(ZQuest other)
{
type = other.type;
item = other.item;
amountGoal = other.amountGoal;
amountDone = 0;
desc = other.desc;
completed = false;
claimed = false;
difficulty = other.difficulty;
}
}
private class QuestManager
{
public ulong playerID;
private BasePlayer bPlayer;
public Dictionary<string, ZQuest> questMap = new Dictionary<string, ZQuest>();
public DateTime questDay = DateTime.Now;
public int questGenerationCounter = 0;
public int questsCompleted = 0;
public int questsClaimed = 0;
public int lifetimeCompleted = 0;
public int lifetimeClaimed = 0;
public int lifetimeClanContributed = 0;
public int lifetimeClanClaimed = 0;
public int lifetimeGlobalContributed = 0;
public int lifetimeGlobalClaimed = 0;
public bool hasRerolled = false;
public bool hasClanContributed = false;
public bool hasClanClaimed = false;
public bool hasClanClaimedYesterday = false;
public bool hasGlobalClaimed = false;
public bool hasGlobalClaimedYesterday = false;
public string PlayerClan = "";
public QuestManager(ulong playerId) : base()
{
playerID = playerId;
}
public static QuestManager Get(ulong playerId, bool wipe = false)
{
if (Plugin._qm.ContainsKey(playerId) && !wipe)
return Plugin._qm[playerId];
var fileName = $"{Plugin.Name}/{playerId}";
QuestManager manager;
if (Interface.Oxide.DataFileSystem.ExistsDatafile(fileName) && !wipe)
{
// Load existing Data
ZNQuests.LoadData(out manager, fileName);
if (!(manager is QuestManager)) return null;
}
else
{
// Create a completely new Playerdataset
manager = new QuestManager(playerId);
ZNQuests.SaveData(manager, fileName);
}
Interface.Oxide.DataFileSystem.GetDatafile(fileName).Settings = new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.Populate
};
manager.bPlayer = BasePlayer.FindAwakeOrSleeping(playerId.ToString());
Plugin._qm[playerId] = manager;
manager.checkQuestsToday();
return manager;
}
public void SaveData()
{
ZNQuests.SaveData(this, $"{Plugin.Name}/{playerID}");
}
public void checkQuestsToday()
{
// check if list is empty (first launch)
if (questMap == null || questMap.Count == 0)
{
createNewQuestMap();
}
// create new quest list
if (questDay.Day != DateTime.Now.Day)
{
createNewQuestMap();
hasRerolled = false;
hasClanContributed = false;
hasClanClaimed = false;
hasClanClaimedYesterday = false;
hasGlobalClaimed = false;
hasGlobalClaimedYesterday = false;
}
}
private void createNewQuestMap()
{
// reset all the stats
if (questMap == null) questMap = new Dictionary<string, ZQuest>();
questGenerationCounter = 0;
questMap.Clear();
questsClaimed = 0;
questsCompleted = 0;
questDay = DateTime.Now;
int travelCount = 0;
int i = 0;
//reroll quests
while (i < Cfg.questAmountEasy)
{
Random rand = new Random((int)DateTimeOffset.Now.ToUnixTimeMilliseconds());
ZQuest randomQuest = new ZQuest(ZNQuests.AvailableEasyQuests.ElementAt(rand.Next(0, ZNQuests.AvailableEasyQuests.Count)));
// don't add the same quest twice
if (questMap.ContainsKey(randomQuest.id())) continue;
if(randomQuest.type == "travel")
{
if (travelCount >= 2) continue;
travelCount++;
}
questMap.Add(randomQuest.id(), randomQuest);
questGenerationCounter++;
i++;
}
i = 0;
while (i < Cfg.questAmountNormal)
{
Random rand = new Random((int)DateTimeOffset.Now.ToUnixTimeMilliseconds());
ZQuest randomQuest = new ZQuest(ZNQuests.AvailableQuests.ElementAt(rand.Next(0, ZNQuests.AvailableQuests.Count)));
// don't add the same quest twice
if (questMap.ContainsKey(randomQuest.id())) continue;
if (randomQuest.type == "travel")
{
if (travelCount >= 2) continue;
travelCount++;
}
questMap.Add(randomQuest.id(), randomQuest);
questGenerationCounter++;
i++;
}
i = 0;
while (i < Cfg.questAmountHard)
{
Random rand = new Random((int)DateTimeOffset.Now.ToUnixTimeMilliseconds());
ZQuest randomQuest = new ZQuest(ZNQuests.AvailableHardQuests.ElementAt(rand.Next(0, ZNQuests.AvailableHardQuests.Count)));
// don't add the same quest twice
if (questMap.ContainsKey(randomQuest.id())) continue;
if (randomQuest.type == "travel")
{
if (travelCount >= 2) continue;
travelCount++;
}
questMap.Add(randomQuest.id(), randomQuest);
questGenerationCounter++;
i++;
}
SaveData();
Plugin.SendReply(bPlayer, "<color=green>[ZN-Quests]</color> New Daily Quests are available! Check /q");
}
public bool HasActiveQuest(string type, string item)
{
if (questMap.Count == 0)
{
createNewQuestMap();
}
return questMap.ContainsKey(type + "_" + item) && !questMap[type + "_" + item].completed;
}
public bool HasQuest(string id)
{
if (questMap.Count == 0)
{
createNewQuestMap();
}
return questMap.ContainsKey(id) && !questMap[id].claimed;
}
public bool CanReroll()
{
return questsClaimed == 0;
}
public void RerollQuests()
{
createNewQuestMap();
hasRerolled = true;
}
public void AddQuestProgress(string type, string item, int amount)
{
string qid = type + "_" + item;
if (!questMap.ContainsKey(qid) || questMap[qid].completed) return;
questMap[qid].amountDone += amount;
// completed quest logic
if (questMap[qid].amountDone >= questMap[qid].amountGoal)
{
questMap[qid].amountDone = questMap[qid].amountGoal;
questMap[qid].completed = true;
questsCompleted++;
lifetimeCompleted++;
Plugin.InfoAPI.Call("ShowInfoPopup", bPlayer, "You completed a Daily Quest!\nCheck /q!");
}
}
public void Claim(string id)
{
if (questMap.ContainsKey(id))
{
questMap[id].claimed = true;
questsClaimed++;
lifetimeClaimed++;
if(!hasGlobalClaimed) Plugin._gm.AddContribution(bPlayer, this);
}
}
}
private class GlobalQuestManager
{
public Dictionary<ulong,int> todayUnclaimed = new Dictionary<ulong, int>();
public Dictionary<ulong, int> yesterdayUnclaimed = new Dictionary<ulong, int>();
public DateTime questDay = DateTime.Now;
public int todayContributors = 0;
public int yesterdayContributors = 0;
public GlobalQuestManager() : base()
{
}
public static GlobalQuestManager Get(bool wipe = false)
{
if (Plugin._gm != null && !wipe)
return Plugin._gm;
var fileName = $"{Plugin.Name}/global/globalData";
GlobalQuestManager manager;
if (Interface.Oxide.DataFileSystem.ExistsDatafile(fileName) && !wipe)
{
// Load existing Data
ZNQuests.LoadData(out manager, fileName);
if (!(manager is GlobalQuestManager)) return null;
}
else
{
// Create a completely new Playerdataset
manager = new GlobalQuestManager();
ZNQuests.SaveData(manager, fileName);
}
Interface.Oxide.DataFileSystem.GetDatafile(fileName).Settings = new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.Populate
};
Plugin._gm = manager;
manager.checkQuestsToday();
return manager;
}
public void SaveData()
{
ZNQuests.SaveData(this, $"{Plugin.Name}/global/globalData");
}
public void checkQuestsToday()
{
if (todayUnclaimed == null) todayUnclaimed = new Dictionary<ulong, int>();
if (yesterdayUnclaimed == null) yesterdayUnclaimed = new Dictionary<ulong, int>();
// create new quest list
if (questDay.Day != DateTime.Now.Day)
{
RefreshDay();
}
}
private void RefreshDay()
{
yesterdayContributors = todayContributors;
yesterdayUnclaimed.Clear();
foreach (KeyValuePair<ulong, int> cont in todayUnclaimed)
{
yesterdayUnclaimed.Add(cont.Key, cont.Value);
}
todayContributors = 0;
todayUnclaimed.Clear();
questDay = DateTime.Now;
SaveData();
}
public int GetCurrentBonus(BasePlayer player, bool yesterday = false)
{
int bonus = 0;
int claims;
int contribCnt;
if (yesterday)
{
if (!CanClaimYesterday(player)) return bonus;
claims = yesterdayUnclaimed[player.userID];
contribCnt = yesterdayContributors;
}
else
{
if (!CanClaim(player)) return bonus;
claims = todayUnclaimed[player.userID];
contribCnt = todayContributors;
}
bonus = (int) Math.Ceiling(contribCnt * Cfg.globalRewardPerContributor * (claims / 10f));
if (bonus > Cfg.globalRewardCap) bonus = Cfg.globalRewardCap;
return bonus;
}
public int GetCurrentSharePercent(BasePlayer player)
{
if (todayUnclaimed.ContainsKey(player.userID))
{
return ((todayUnclaimed[player.userID] >= Cfg.globalQuestClaimThreshold) ? todayUnclaimed[player.userID] * 10 : 0);
}
else
{
return 0;
}
}
public bool CanClaim(BasePlayer player)
{
return (todayUnclaimed.ContainsKey(player.userID) && todayUnclaimed[player.userID] >= Cfg.globalQuestClaimThreshold);
}
public bool CanClaimYesterday(BasePlayer player)
{
return (yesterdayUnclaimed.ContainsKey(player.userID) && yesterdayUnclaimed[player.userID] >= Cfg.globalQuestClaimThreshold);
}
public void Claim(BasePlayer player, QuestManager qm)
{
if (!CanClaim(player)) return;
qm.lifetimeGlobalClaimed++;
qm.hasGlobalClaimed = true;
qm.SaveData();
int currentBonus = GetCurrentBonus(player);
todayUnclaimed.Remove(player.userID);
SaveData();
Plugin.ZNExperience?.Call("AddXp", player.userID, currentBonus);
Plugin.Puts("INFO: " + player + " claimed today's Global Bonus of " + currentBonus);
}
public void ClaimYesterday(BasePlayer player, QuestManager qm)
{
if (!CanClaimYesterday(player)) return;
qm.lifetimeGlobalClaimed++;
qm.hasGlobalClaimedYesterday = true;
qm.SaveData();
int currentBonus = GetCurrentBonus(player, true);
yesterdayUnclaimed.Remove(player.userID);
SaveData();
Plugin.ZNExperience?.Call("AddXp", player.userID, currentBonus);
Plugin.Puts("INFO: " + player + " claimed yesterday's Global Bonus of " + currentBonus);
}
public void AddContribution(BasePlayer player, QuestManager qm)
{
if (todayUnclaimed.ContainsKey(player.userID))
{
todayUnclaimed[player.userID]++;
if (todayUnclaimed[player.userID] == Cfg.globalQuestClaimThreshold)
{
todayContributors++;
qm.lifetimeGlobalContributed++;
qm.SaveData();
Plugin.Puts("INFO: " + player + " contributed " + Cfg.globalQuestClaimThreshold + " quest claims to Global");
}
}
else
{
todayUnclaimed.Add(player.userID, 1);
}
SaveData();
}
}
#endregion
#region Hooks
void OnPlayerSleepEnded(BasePlayer player)
{
if (player is NPCPlayer || player is HumanNPC || player.IsNpc) return;
if (!_qm.ContainsKey(player.userID))
{
_qm[player.userID] = QuestManager.Get(player.userID);
}
}
void OnPlayerDisconnected(BasePlayer player)
{
killUI(player);
if (_qm.ContainsKey(player.userID))
{
_qm[player.userID].SaveData();
_qm.Remove(player.userID);
}
}
private void OnEntityDeath(BaseCombatEntity victimEntity, HitInfo info)
{
// Ignore - there is no victim for some reason
if (victimEntity == null)
return;
// Try to avoid error when entity was destroyed
if (victimEntity.gameObject == null)
return;
// barrel quest
var name = victimEntity.ShortPrefabName;
if (name != null)
{
if (info != null && info.Initiator != null)
{
if (!(info.Initiator is BasePlayer) || (info.Initiator as BasePlayer).IsNpc) return;
if (info.Initiator is BasePlayer)
{
try
{
BasePlayer bplayer = info.Initiator.ToPlayer();
if (bplayer != null)
questProgress(bplayer, "kill", name);
}
catch { }
}
}
}
}
Item OnFishCatch(Item fish, BaseFishingRod fishingRod, BasePlayer player)
{
if (fish.info == null || fish.info.shortname == null) return fish;
questProgress(player, "catch", "fish");
return fish;
}
private void OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item)
{
var player = entity as BasePlayer;
if (player == null) return;
questProgress(player, "farm", item.info?.shortname);
}
object OnCollectiblePickup(CollectibleEntity collectible, BasePlayer player)
{
if (player == null) return null;
Item item = collectible.GetItem();
for (int i = 0; i < collectible.itemList.Length; i++)
{
ItemAmount itemAmount = collectible.itemList[i];
string itemName = itemAmount.itemDef.shortname;
questProgress(player, "collect", itemName);
}
return null;
}
void OnEntityMounted(BaseMountable entity, BasePlayer player)
{
if (playerMountPoints.ContainsKey(player.userID))
{
playerMountPoints[player.userID] = entity.transform.position;
}
else
{
playerMountPoints.Add(player.userID, entity.transform.position);
}
}
void OnEntityDismounted(BaseMountable entity, BasePlayer player)
{
if (playerMountPoints.ContainsKey(player.userID))
{
int distance = (int)Math.Floor(Vector3Ex.Distance2D(entity.transform.position, playerMountPoints[player.userID]));
playerMountPoints.Remove(player.userID);
questProgress(player, "travel", entity.ShortPrefabName, distance);
//Puts("DEBUG: dismount " + entity.ShortPrefabName + "...");
}
}
#endregion
#region Commands
[ConsoleCommand("znquests.admreset")]
private void CmdAdmReset(ConsoleSystem.Arg arg)
{
var player = arg.Connection.player as BasePlayer;
if (!player.IsAdmin) return;
killUI(player);
if (_qm.ContainsKey(player.userID))
{
_qm[player.userID] = QuestManager.Get(player.userID, true);
}
}
[ConsoleCommand("znquests.close")]
private void CmdClose(ConsoleSystem.Arg arg)
{
var player = arg.Connection.player as BasePlayer;
killUI(player);
if (_qm.ContainsKey(player.userID))
{
_qm[player.userID].SaveData();
}
}
[ConsoleCommand("znquests.claim")]
private void CmdClaim(ConsoleSystem.Arg arg)
{
var player = arg.Connection.player as BasePlayer;
if (player == null)// || !HasPermission(arg.Player().UserIDString, permUse))
return;
string qid = arg.GetStr
// ... [Code preview truncated due to length. Full source in attached file] ...