Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
944
Scripts/Services/BulkOrders/BulkOrderSystem.cs
Normal file
944
Scripts/Services/BulkOrders/BulkOrderSystem.cs
Normal file
@@ -0,0 +1,944 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.BulkOrders
|
||||
{
|
||||
public enum PointsMode
|
||||
{
|
||||
Enabled,
|
||||
Disabled,
|
||||
Automatic
|
||||
}
|
||||
|
||||
public interface IBOD
|
||||
{
|
||||
int AmountMax { get; set; }
|
||||
bool RequireExceptional { get; set; }
|
||||
bool Complete { get; }
|
||||
BulkMaterialType Material { get; set; }
|
||||
BODType BODType { get; }
|
||||
}
|
||||
|
||||
public class BulkOrderSystem
|
||||
{
|
||||
// Logic (EA says 3 cached): 2 cached, 1 in the pipe if the last bod > 6 hours = 3
|
||||
public static readonly int MaxCachedDeeds = 2;
|
||||
public static readonly int Delay = 6;
|
||||
|
||||
public static bool NewSystemEnabled = Core.TOL;
|
||||
public static BulkOrderSystem Instance { get; set; }
|
||||
|
||||
public Dictionary<PlayerMobile, BODContext> BODPlayerData { get; set; }
|
||||
|
||||
public BulkOrderSystem()
|
||||
{
|
||||
BODPlayerData = new Dictionary<PlayerMobile, BODContext>();
|
||||
}
|
||||
|
||||
static BulkOrderSystem()
|
||||
{
|
||||
Instance = new BulkOrderSystem();
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(0);
|
||||
|
||||
writer.Write(BODPlayerData.Count);
|
||||
foreach (KeyValuePair<PlayerMobile, BODContext> kvp in BODPlayerData)
|
||||
{
|
||||
writer.Write(kvp.Key);
|
||||
kvp.Value.Serialize(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
int count = reader.ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
PlayerMobile player = reader.ReadMobile() as PlayerMobile;
|
||||
BODContext context = new BODContext(reader);
|
||||
|
||||
if (player != null)
|
||||
BODPlayerData[player] = context;
|
||||
}
|
||||
}
|
||||
|
||||
public static BODContext GetContext(Mobile m, bool create = true)
|
||||
{
|
||||
BODContext context = null;
|
||||
|
||||
if (m is PlayerMobile)
|
||||
{
|
||||
PlayerMobile pm = m as PlayerMobile;
|
||||
|
||||
if (Instance.BODPlayerData.ContainsKey(pm))
|
||||
{
|
||||
context = Instance.BODPlayerData[pm];
|
||||
}
|
||||
else if (create)
|
||||
{
|
||||
Instance.BODPlayerData[pm] = context = new BODContext();
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
public static double GetPoints(Mobile m, BODType type)
|
||||
{
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
if (context.Entries.ContainsKey(type))
|
||||
{
|
||||
return context.Entries[type].BankedPoints;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void SetPoints(Mobile m, BODType type, double points)
|
||||
{
|
||||
if (points < 0)
|
||||
points = 0.0;
|
||||
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
if (context.Entries.ContainsKey(type))
|
||||
{
|
||||
context.Entries[type].BankedPoints += points;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeductPoints(Mobile m, BODType type, double points)
|
||||
{
|
||||
if (points < 0)
|
||||
points = 0.0;
|
||||
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
if (context.Entries.ContainsKey(type))
|
||||
{
|
||||
context.Entries[type].BankedPoints -= points;
|
||||
|
||||
if (context.Entries[type].BankedPoints < 0.0)
|
||||
context.Entries[type].BankedPoints = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static double GetBODSkill(Mobile m, SkillName skill)
|
||||
{
|
||||
return Math.Max(m.Skills[skill].Base, m.GetRacialSkillBonus(skill));
|
||||
}
|
||||
|
||||
public static List<CollectionItem> GetRewardCollection(BODType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: return SmithRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Tailor: return TailorRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Alchemy: return AlchemyRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Inscription: return InscriptionRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Tinkering: return TinkeringRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Fletching: return FletchingRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Carpentry: return CarpentryRewardCalculator.Instance.RewardCollection;
|
||||
case BODType.Cooking: return CookingRewardCalculator.Instance.RewardCollection;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanGetBulkOrder(Mobile m, BODType type)
|
||||
{
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null && context.Entries.ContainsKey(type))
|
||||
{
|
||||
var entry = context.Entries[type];
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
entry.CheckCache();
|
||||
|
||||
if (entry.LastBulkOrder + TimeSpan.FromHours(Delay) < DateTime.UtcNow)
|
||||
{
|
||||
entry.LastBulkOrder = DateTime.UtcNow;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (entry.CachedDeeds > 0)
|
||||
{
|
||||
entry.CachedDeeds--;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TimeSpan GetNextBulkOrder(BODType type, PlayerMobile pm)
|
||||
{
|
||||
BODContext context = GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
if (NewSystemEnabled)
|
||||
{
|
||||
DateTime last = context.Entries[type].LastBulkOrder;
|
||||
|
||||
return (last + TimeSpan.FromHours(Delay)) - DateTime.UtcNow;
|
||||
}
|
||||
else if (context.Entries.ContainsKey(type))
|
||||
{
|
||||
DateTime dt = context.Entries[type].NextBulkOrder;
|
||||
|
||||
if (dt < DateTime.UtcNow)
|
||||
return TimeSpan.Zero;
|
||||
|
||||
return DateTime.UtcNow - dt;
|
||||
}
|
||||
}
|
||||
|
||||
return TimeSpan.MaxValue;
|
||||
}
|
||||
|
||||
public static void SetNextBulkOrder(BODType type, PlayerMobile pm, TimeSpan ts)
|
||||
{
|
||||
BODContext context = GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
if (NewSystemEnabled)
|
||||
{
|
||||
if (context.Entries.ContainsKey(type))
|
||||
{
|
||||
if (context.Entries[type].LastBulkOrder < DateTime.UtcNow - TimeSpan.FromHours(Delay * MaxCachedDeeds))
|
||||
context.Entries[type].LastBulkOrder = DateTime.UtcNow - TimeSpan.FromHours(Delay * MaxCachedDeeds);
|
||||
else
|
||||
context.Entries[type].LastBulkOrder = (context.Entries[type].LastBulkOrder + ts) - TimeSpan.FromHours(Delay);
|
||||
}
|
||||
}
|
||||
else if (context.Entries.ContainsKey(type))
|
||||
{
|
||||
context.Entries[type].NextBulkOrder = DateTime.UtcNow + ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Item CreateBulkOrder(Mobile m, BODType type, bool fromContextMenu)
|
||||
{
|
||||
PlayerMobile pm = m as PlayerMobile;
|
||||
|
||||
if (pm == null)
|
||||
return null;
|
||||
|
||||
if (pm.AccessLevel > AccessLevel.Player || fromContextMenu || 0.2 > Utility.RandomDouble())
|
||||
{
|
||||
SkillName sk = GetSkillForBOD(type);
|
||||
double theirSkill = pm.Skills[sk].Base;
|
||||
bool doLarge = theirSkill >= 70.1 && ((theirSkill - 40.0) / 300.0) > Utility.RandomDouble();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case BODType.Smith:
|
||||
if (doLarge) return new LargeSmithBOD();
|
||||
else return SmallSmithBOD.CreateRandomFor(pm);
|
||||
case BODType.Tailor: if (doLarge) return new LargeTailorBOD();
|
||||
else return SmallTailorBOD.CreateRandomFor(pm);
|
||||
case BODType.Alchemy:
|
||||
if (doLarge) return new LargeAlchemyBOD();
|
||||
else return SmallAlchemyBOD.CreateRandomFor(pm);
|
||||
case BODType.Inscription:
|
||||
if (doLarge) return new LargeInscriptionBOD();
|
||||
else return SmallInscriptionBOD.CreateRandomFor(pm);
|
||||
case BODType.Tinkering:
|
||||
if (doLarge) return new LargeTinkerBOD();
|
||||
else return SmallTinkerBOD.CreateRandomFor(pm);
|
||||
case BODType.Cooking:
|
||||
if (doLarge) return new LargeCookingBOD();
|
||||
else return SmallCookingBOD.CreateRandomFor(pm);
|
||||
case BODType.Fletching:
|
||||
if (doLarge) return new LargeFletchingBOD();
|
||||
else return SmallFletchingBOD.CreateRandomFor(pm);
|
||||
case BODType.Carpentry:
|
||||
if (doLarge) return new LargeCarpentryBOD();
|
||||
else return SmallCarpentryBOD.CreateRandomFor(pm);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SkillName GetSkillForBOD(BODType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: return SkillName.Blacksmith;
|
||||
case BODType.Tailor: return SkillName.Tailoring;
|
||||
case BODType.Alchemy: return SkillName.Alchemy;
|
||||
case BODType.Inscription: return SkillName.Inscribe;
|
||||
case BODType.Tinkering: return SkillName.Tinkering;
|
||||
case BODType.Cooking: return SkillName.Cooking;
|
||||
case BODType.Fletching: return SkillName.Fletching;
|
||||
case BODType.Carpentry: return SkillName.Carpentry;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetBodHue(BODType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: return 0x44E;
|
||||
case BODType.Tailor: return 0x483;
|
||||
case BODType.Alchemy: return 2505;
|
||||
case BODType.Inscription: return 2598;
|
||||
case BODType.Tinkering: return 1109;
|
||||
case BODType.Cooking: return 1169;
|
||||
case BODType.Fletching: return 1425;
|
||||
case BODType.Carpentry: return 1512;
|
||||
}
|
||||
}
|
||||
|
||||
public static BOBFilter GetBOBFilter(PlayerMobile pm)
|
||||
{
|
||||
return GetContext(pm).BOBFilter;
|
||||
}
|
||||
|
||||
public static void SetBOBFilter(PlayerMobile pm, BOBFilter filter)
|
||||
{
|
||||
BODContext context = GetContext(pm);
|
||||
context.BOBFilter = filter;
|
||||
}
|
||||
|
||||
public static int ComputePoints(SmallBOD bod)
|
||||
{
|
||||
switch (bod.BODType)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: return SmithRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Tailor: return TailorRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Alchemy: return AlchemyRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Inscription: return InscriptionRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Tinkering: return TinkeringRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Cooking: return CookingRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Fletching: return FletchingRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Carpentry: return CarpentryRewardCalculator.Instance.ComputePoints(bod);
|
||||
}
|
||||
}
|
||||
|
||||
public static int ComputePoints(LargeBOD bod)
|
||||
{
|
||||
switch (bod.BODType)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: return SmithRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Tailor: return TailorRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Alchemy: return AlchemyRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Inscription: return InscriptionRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Tinkering: return TinkeringRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Cooking: return CookingRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Fletching: return FletchingRewardCalculator.Instance.ComputePoints(bod);
|
||||
case BODType.Carpentry: return CarpentryRewardCalculator.Instance.ComputePoints(bod);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ComputeGold(Type type, int quantity, out int gold)
|
||||
{
|
||||
if (GenericBuyInfo.BuyPrices.ContainsKey(type))
|
||||
{
|
||||
gold = (quantity * GenericBuyInfo.BuyPrices[type]) / 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
gold = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ComputePoints(SmallBOD bod, out int points, out double banked)
|
||||
{
|
||||
points = 0;
|
||||
banked = 0.0;
|
||||
|
||||
switch (bod.BODType)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: points = SmithRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Tailor: points = TailorRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Alchemy: points = AlchemyRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Inscription: points = InscriptionRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Tinkering: points = TinkeringRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Cooking: points = CookingRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Fletching: points = FletchingRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Carpentry: points = CarpentryRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
}
|
||||
|
||||
banked = (double)points * 0.02;
|
||||
}
|
||||
|
||||
public static void ComputePoints(LargeBOD bod, out int points, out double banked)
|
||||
{
|
||||
points = 0;
|
||||
banked = 0.0;
|
||||
|
||||
switch (bod.BODType)
|
||||
{
|
||||
default:
|
||||
case BODType.Smith: points = SmithRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Tailor: points = TailorRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Alchemy: points = AlchemyRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Inscription: points = InscriptionRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Tinkering: points = TinkeringRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Cooking: points = CookingRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Fletching: points = FletchingRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
case BODType.Carpentry: points = CarpentryRewardCalculator.Instance.ComputePoints(bod); break;
|
||||
}
|
||||
|
||||
banked = (double)points * .2;
|
||||
}
|
||||
|
||||
public static void AddToPending(Mobile m, BODType type, int points)
|
||||
{
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
context.AddPending(type, points);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemovePending(Mobile m, BODType type)
|
||||
{
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
context.RemovePending(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanClaimRewards(Mobile m)
|
||||
{
|
||||
BODContext context = GetContext(m);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
return context.CanClaimRewards();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CanExchangeBOD(Mobile from, BaseVendor vendor, IBOD bod, int cost)
|
||||
{
|
||||
if (bod.BODType != vendor.BODType)
|
||||
{
|
||||
vendor.SayTo(from, 1152298, 0x3B2); // I don't deal in those goods.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bod is SmallBOD && ((SmallBOD)bod).AmountCur > 0) ||
|
||||
(bod is LargeBOD && ((LargeBOD)bod).Entries != null &&
|
||||
((LargeBOD)bod).Entries.FirstOrDefault(e => e.Amount > 0) != null))
|
||||
{
|
||||
vendor.SayTo(from, 1152299, 0x3B2); // I am sorry to say I cannot work with a deed that is even partially filled.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bod.AmountMax == 20 && (!CanBeExceptional(bod) || bod.RequireExceptional) &&
|
||||
(!CanUseMaterial(bod) ||
|
||||
(bod.Material == BulkMaterialType.Valorite ||
|
||||
bod.Material == BulkMaterialType.Frostwood ||
|
||||
bod.Material == BulkMaterialType.Barbed)))
|
||||
{
|
||||
vendor.SayTo(from, 1152291, 0x3B2); // I won't be able to replace that bulk order with a better one.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cost > -1 && !Banker.Withdraw(from, cost, true))
|
||||
{
|
||||
vendor.SayTo(from, 1152302, 0x3B2); // I am afraid your bank box does not contain the funds needed to complete this transaction.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Type GetTypeFromBOD(IBOD bod)
|
||||
{
|
||||
Type t = null;
|
||||
|
||||
if (bod is SmallBOD)
|
||||
{
|
||||
t = ((SmallBOD)bod).Type;
|
||||
}
|
||||
else if (bod is LargeBOD && ((LargeBOD)bod).Entries != null && ((LargeBOD)bod).Entries.Length > 0)
|
||||
{
|
||||
t = ((LargeBOD)bod).Entries[0].Details.Type;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public static bool CanBeExceptional(IBOD bod)
|
||||
{
|
||||
switch (bod.BODType)
|
||||
{
|
||||
default: return true;
|
||||
case BODType.Alchemy:
|
||||
case BODType.Inscription: return false;
|
||||
case BODType.Tinkering:
|
||||
case BODType.Cooking:
|
||||
case BODType.Fletching:
|
||||
return !IsInExceptionalExcludeList(bod);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsInExceptionalExcludeList(IBOD bod)
|
||||
{
|
||||
Type t = GetTypeFromBOD(bod);
|
||||
|
||||
if (t == null)
|
||||
return false;
|
||||
|
||||
return _ExceptionalExcluded.FirstOrDefault(type => type == t) != null;
|
||||
}
|
||||
|
||||
public static bool CanUseMaterial(IBOD bod)
|
||||
{
|
||||
switch (bod.BODType)
|
||||
{
|
||||
default: return true;
|
||||
case BODType.Alchemy:
|
||||
case BODType.Inscription:
|
||||
case BODType.Cooking: return false;
|
||||
case BODType.Tinkering:
|
||||
case BODType.Fletching: return !IsInExceptionalExcludeList(bod);
|
||||
case BODType.Tailor: return BGTClassifier.Classify(BODType.Tailor, GetTypeFromBOD(bod)) == BulkGenericType.Leather;
|
||||
}
|
||||
}
|
||||
|
||||
private static Type[] _ExceptionalExcluded =
|
||||
{
|
||||
typeof(Arrow), typeof(Bolt), typeof(Kindling), typeof(Shaft),
|
||||
|
||||
typeof(EnchantedApple), typeof(TribalPaint), typeof(GrapesOfWrath),
|
||||
typeof(EggBomb), typeof(CookedBird), typeof(FishSteak), typeof(FriedEggs),
|
||||
typeof(LambLeg), typeof(Ribs),
|
||||
|
||||
typeof(Gears), typeof(Axle), typeof(Springs), typeof(AxleGears), typeof(ClockParts),
|
||||
typeof(Clock), typeof(PotionKeg), typeof(ClockFrame), typeof(MetalContainerEngraver)
|
||||
};
|
||||
|
||||
public static void MutateBOD(IBOD bod)
|
||||
{
|
||||
List<int> picker = new List<int>();
|
||||
|
||||
if (!bod.RequireExceptional && CanBeExceptional(bod))
|
||||
{
|
||||
picker.Add(0);
|
||||
}
|
||||
|
||||
if (bod.AmountMax < 20)
|
||||
{
|
||||
picker.Add(1);
|
||||
}
|
||||
|
||||
if (CanUseMaterial(bod) && bod.Material != BulkMaterialType.Frostwood && bod.Material != BulkMaterialType.Barbed && bod.Material != BulkMaterialType.Valorite)
|
||||
{
|
||||
picker.Add(2);
|
||||
}
|
||||
|
||||
if (picker.Count == 0)
|
||||
return;
|
||||
|
||||
switch (picker[Utility.Random(picker.Count)])
|
||||
{
|
||||
case 0: bod.RequireExceptional = true; break;
|
||||
case 1: bod.AmountMax += 5; break;
|
||||
case 2:
|
||||
if (bod.Material == BulkMaterialType.None)
|
||||
{
|
||||
BulkGenericType type = BGTClassifier.Classify(bod.BODType, null);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case BulkGenericType.Iron: bod.Material = BulkMaterialType.DullCopper; break;
|
||||
case BulkGenericType.Cloth: break;
|
||||
case BulkGenericType.Leather: bod.Material = BulkMaterialType.Spined; break;
|
||||
case BulkGenericType.Wood: bod.Material = BulkMaterialType.OakWood; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bod.Material++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
picker.Clear();
|
||||
}
|
||||
|
||||
public static int GetBribe(IBOD bod)
|
||||
{
|
||||
int worth = 0;
|
||||
|
||||
if (bod.RequireExceptional)
|
||||
{
|
||||
worth += 400;
|
||||
}
|
||||
|
||||
switch (bod.Material)
|
||||
{
|
||||
case BulkMaterialType.DullCopper: worth += 25; break;
|
||||
case BulkMaterialType.ShadowIron: worth += 50; break;
|
||||
case BulkMaterialType.Copper: worth += 100; break;
|
||||
case BulkMaterialType.Bronze: worth += 200; break;
|
||||
case BulkMaterialType.Gold: worth += 300; break;
|
||||
case BulkMaterialType.Agapite: worth += 400; break;
|
||||
case BulkMaterialType.Verite: worth += 500; break;
|
||||
case BulkMaterialType.Valorite: worth += 600; break;
|
||||
case BulkMaterialType.Spined: worth += 100; break;
|
||||
case BulkMaterialType.Horned: worth += 250; break;
|
||||
case BulkMaterialType.Barbed: worth += 500; break;
|
||||
case BulkMaterialType.OakWood: worth += 100; break;
|
||||
case BulkMaterialType.AshWood: worth += 200; break;
|
||||
case BulkMaterialType.YewWood: worth += 300; break;
|
||||
case BulkMaterialType.Heartwood: worth += 400; break;
|
||||
case BulkMaterialType.Bloodwood: worth += 500; break;
|
||||
case BulkMaterialType.Frostwood: worth += 600; break;
|
||||
}
|
||||
|
||||
switch (bod.AmountMax)
|
||||
{
|
||||
default:
|
||||
case 10:
|
||||
case 15: worth += 100; break;
|
||||
case 20: worth += 250; break;
|
||||
}
|
||||
|
||||
if (bod is LargeBOD && ((LargeBOD)bod).Entries != null)
|
||||
{
|
||||
worth *= Math.Min(4, ((LargeBOD)bod).Entries.Length);
|
||||
}
|
||||
|
||||
return worth;
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var kvp in Instance.BODPlayerData)
|
||||
{
|
||||
kvp.Value.CheckCache();
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnLogin(LoginEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
public static string FilePath = Path.Combine("Saves/CraftContext", "BODs.bin");
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
EventSink.WorldSave += OnSave;
|
||||
EventSink.WorldLoad += OnLoad;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (NewSystemEnabled)
|
||||
{
|
||||
Timer.DelayCall(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1), OnTick);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnSave(WorldSaveEventArgs e)
|
||||
{
|
||||
Persistence.Serialize(
|
||||
FilePath,
|
||||
writer =>
|
||||
{
|
||||
writer.Write(0);
|
||||
|
||||
Instance.Serialize(writer);
|
||||
});
|
||||
}
|
||||
|
||||
public static void OnLoad()
|
||||
{
|
||||
Persistence.Deserialize(
|
||||
FilePath,
|
||||
reader =>
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Instance.Deserialize(reader);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class BODContext
|
||||
{
|
||||
public Dictionary<BODType, BODEntry> Entries { get; set; }
|
||||
|
||||
public BOBFilter BOBFilter { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public PointsMode PointsMode { get; set; }
|
||||
|
||||
public BODContext()
|
||||
{
|
||||
BOBFilter = new BOBFilter();
|
||||
|
||||
ConfigEntries();
|
||||
}
|
||||
|
||||
public void AddPending(BODType type, int points)
|
||||
{
|
||||
if (Entries.ContainsKey(type))
|
||||
{
|
||||
Entries[type].PendingRewardPoints = points;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemovePending(BODType type)
|
||||
{
|
||||
if (Entries.ContainsKey(type))
|
||||
{
|
||||
Entries[type].PendingRewardPoints = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPendingRewardFor(BODType type)
|
||||
{
|
||||
if (Entries.ContainsKey(type))
|
||||
{
|
||||
return Entries[type].PendingRewardPoints;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool CanClaimRewards()
|
||||
{
|
||||
foreach (var kvp in Entries)
|
||||
{
|
||||
if (kvp.Value.PendingRewardPoints > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public BODContext(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
ConfigEntries();
|
||||
|
||||
this.PointsMode = (PointsMode)reader.ReadInt();
|
||||
BOBFilter = new BOBFilter(reader);
|
||||
|
||||
int count = reader.ReadInt();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
BODType type = (BODType)reader.ReadInt();
|
||||
BODEntry entry = new BODEntry(reader);
|
||||
|
||||
if (Entries.ContainsKey(type))
|
||||
Entries[type] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(0);
|
||||
|
||||
writer.Write((int)this.PointsMode);
|
||||
BOBFilter.Serialize(writer);
|
||||
|
||||
// Lets do this dynamically incase we add new bods in the future
|
||||
writer.Write(Entries.Count);
|
||||
foreach (KeyValuePair<BODType, BODEntry> kvp in Entries)
|
||||
{
|
||||
writer.Write((int)kvp.Key);
|
||||
kvp.Value.Serialize(writer);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigEntries()
|
||||
{
|
||||
Entries = new Dictionary<BODType, BODEntry>();
|
||||
|
||||
Entries[BODType.Smith] = new BODEntry();
|
||||
Entries[BODType.Tailor] = new BODEntry();
|
||||
Entries[BODType.Tinkering] = new BODEntry();
|
||||
Entries[BODType.Carpentry] = new BODEntry();
|
||||
Entries[BODType.Fletching] = new BODEntry();
|
||||
Entries[BODType.Cooking] = new BODEntry();
|
||||
Entries[BODType.Alchemy] = new BODEntry();
|
||||
Entries[BODType.Inscription] = new BODEntry();
|
||||
}
|
||||
|
||||
public void CheckCache()
|
||||
{
|
||||
foreach (var kvp in Entries)
|
||||
{
|
||||
kvp.Value.CheckCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[PropertyObject]
|
||||
public class BODEntry
|
||||
{
|
||||
private int _CachedDeeds;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int CachedDeeds
|
||||
{
|
||||
get { return _CachedDeeds; }
|
||||
set
|
||||
{
|
||||
int old = _CachedDeeds;
|
||||
|
||||
_CachedDeeds = Math.Max(0, Math.Min(BulkOrderSystem.MaxCachedDeeds, value));
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime LastBulkOrder { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public double BankedPoints { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int PendingRewardPoints { get; set; }
|
||||
|
||||
// Legacy System
|
||||
private DateTime _NextBulkOrder;
|
||||
|
||||
public DateTime NextBulkOrder
|
||||
{
|
||||
get
|
||||
{
|
||||
return _NextBulkOrder;
|
||||
}
|
||||
set
|
||||
{
|
||||
_NextBulkOrder = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "...";
|
||||
}
|
||||
|
||||
public BODEntry()
|
||||
{
|
||||
_CachedDeeds = BulkOrderSystem.MaxCachedDeeds;
|
||||
}
|
||||
|
||||
public void CheckCache()
|
||||
{
|
||||
if (_CachedDeeds >= BulkOrderSystem.MaxCachedDeeds)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (LastBulkOrder == DateTime.MinValue)
|
||||
{
|
||||
CachedDeeds = BulkOrderSystem.MaxCachedDeeds;
|
||||
LastBulkOrder = DateTime.UtcNow - TimeSpan.FromHours(BulkOrderSystem.Delay);
|
||||
}
|
||||
else if (LastBulkOrder + TimeSpan.FromHours(BulkOrderSystem.Delay) < DateTime.UtcNow)
|
||||
{
|
||||
CachedDeeds++;
|
||||
LastBulkOrder = LastBulkOrder + TimeSpan.FromHours(BulkOrderSystem.Delay);
|
||||
}
|
||||
}
|
||||
|
||||
public BODEntry(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
if (reader.ReadInt() == 0)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
case 0:
|
||||
_CachedDeeds = reader.ReadInt();
|
||||
LastBulkOrder = reader.ReadDateTime();
|
||||
BankedPoints = reader.ReadDouble();
|
||||
PendingRewardPoints = reader.ReadInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_NextBulkOrder = reader.ReadDateTime();
|
||||
}
|
||||
|
||||
if (version == 0 && _CachedDeeds > BulkOrderSystem.MaxCachedDeeds)
|
||||
{
|
||||
_CachedDeeds = BulkOrderSystem.MaxCachedDeeds;
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(1);
|
||||
|
||||
if (BulkOrderSystem.NewSystemEnabled)
|
||||
{
|
||||
writer.Write(0);
|
||||
writer.Write(_CachedDeeds);
|
||||
writer.Write(LastBulkOrder);
|
||||
writer.Write(BankedPoints);
|
||||
writer.Write(PendingRewardPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(1);
|
||||
writer.Write(_NextBulkOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PendingBribe
|
||||
{
|
||||
public IBOD BOD { get; set; }
|
||||
public int Amount { get; set; }
|
||||
|
||||
public PendingBribe(IBOD bod, int amount)
|
||||
{
|
||||
BOD = bod;
|
||||
Amount = amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user